summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Documentation/DocBook/media/Makefile2
-rw-r--r--Documentation/DocBook/media/v4l/controls.xml295
-rw-r--r--Documentation/DocBook/media/v4l/dev-raw-vbi.xml12
-rw-r--r--Documentation/DocBook/media/v4l/dev-sdr.xml18
-rw-r--r--Documentation/DocBook/media/v4l/dev-sliced-vbi.xml9
-rw-r--r--Documentation/DocBook/media/v4l/io.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml418
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml44
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml47
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml40
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt-srggb12.xml2
-rw-r--r--Documentation/DocBook/media/v4l/pixfmt.xml61
-rw-r--r--Documentation/DocBook/media/v4l/selection-api.xml95
-rw-r--r--Documentation/DocBook/media/v4l/v4l2.xml8
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-dqevent.xml50
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml51
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml12
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-g-selection.xml40
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-querycap.xml6
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-queryctrl.xml234
-rw-r--r--Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml8
-rw-r--r--Documentation/devicetree/bindings/media/sunxi-ir.txt23
-rw-r--r--Documentation/video4linux/v4l2-controls.txt63
-rw-r--r--Documentation/video4linux/v4l2-framework.txt8
-rw-r--r--Documentation/video4linux/v4l2-pci-skeleton.c5
-rw-r--r--Documentation/zh_CN/video4linux/v4l2-framework.txt7
-rw-r--r--MAINTAINERS30
-rw-r--r--drivers/media/Kconfig12
-rw-r--r--drivers/media/common/saa7146/saa7146_fops.c14
-rw-r--r--drivers/media/dvb-core/dvb-usb-ids.h1
-rw-r--r--drivers/media/dvb-core/dvb_frontend.c8
-rw-r--r--drivers/media/dvb-core/dvbdev.h4
-rw-r--r--drivers/media/dvb-frontends/Kconfig9
-rw-r--r--drivers/media/dvb-frontends/Makefile6
-rw-r--r--drivers/media/dvb-frontends/au8522_decoder.c180
-rw-r--r--drivers/media/dvb-frontends/au8522_priv.h2
-rw-r--r--drivers/media/dvb-frontends/dib0090.c15
-rw-r--r--drivers/media/dvb-frontends/dib7000p.c433
-rw-r--r--drivers/media/dvb-frontends/dib7000p.h131
-rw-r--r--drivers/media/dvb-frontends/dib8000.c732
-rw-r--r--drivers/media/dvb-frontends/dib8000.h150
-rw-r--r--drivers/media/dvb-frontends/drx39xyj/drxj.c14
-rw-r--r--drivers/media/dvb-frontends/drxd.h1
-rw-r--r--drivers/media/dvb-frontends/drxd_hard.c3
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.c (renamed from drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c)100
-rw-r--r--drivers/media/dvb-frontends/rtl2832_sdr.h (renamed from drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h)0
-rw-r--r--drivers/media/dvb-frontends/si2168.c280
-rw-r--r--drivers/media/dvb-frontends/si2168_priv.h9
-rw-r--r--drivers/media/dvb-frontends/tda18271c2dd_maps.h8
-rw-r--r--drivers/media/i2c/Kconfig1
-rw-r--r--drivers/media/i2c/adv7180.c1
-rw-r--r--drivers/media/i2c/adv7604.c5
-rw-r--r--drivers/media/i2c/mt9v032.c170
-rw-r--r--drivers/media/i2c/noon010pc30.c1
-rw-r--r--drivers/media/i2c/s5k4ecgx.c1
-rw-r--r--drivers/media/i2c/s5k5baf.c2
-rw-r--r--drivers/media/i2c/s5k6a3.c1
-rw-r--r--drivers/media/i2c/smiapp/smiapp-core.c17
-rw-r--r--drivers/media/i2c/soc_camera/mt9m001.c6
-rw-r--r--drivers/media/i2c/soc_camera/mt9t031.c6
-rw-r--r--drivers/media/i2c/soc_camera/mt9v022.c4
-rw-r--r--drivers/media/media-device.c2
-rw-r--r--drivers/media/parport/bw-qcam.c3
-rw-r--r--drivers/media/parport/c-qcam.c1
-rw-r--r--drivers/media/parport/pms.c1
-rw-r--r--drivers/media/parport/w9966.c1
-rw-r--r--drivers/media/pci/bt8xx/bttv-driver.c1
-rw-r--r--drivers/media/pci/cx18/cx18-alsa.h1
-rw-r--r--drivers/media/pci/cx18/cx18-ioctl.c1
-rw-r--r--drivers/media/pci/cx18/cx18-streams.c1
-rw-r--r--drivers/media/pci/cx23885/cx23885-cards.c31
-rw-r--r--drivers/media/pci/cx23885/cx23885-dvb.c8
-rw-r--r--drivers/media/pci/cx23885/cx23885-video.c1
-rw-r--r--drivers/media/pci/cx23885/cx23885.h1
-rw-r--r--drivers/media/pci/cx25821/cx25821-video.c4
-rw-r--r--drivers/media/pci/cx88/cx88-core.c1
-rw-r--r--drivers/media/pci/ivtv/ivtv-controls.c4
-rw-r--r--drivers/media/pci/ivtv/ivtv-ioctl.c3
-rw-r--r--drivers/media/pci/ivtv/ivtv-streams.c1
-rw-r--r--drivers/media/pci/meye/meye.c3
-rw-r--r--drivers/media/pci/ngene/ngene-core.c7
-rw-r--r--drivers/media/pci/saa7134/saa7134-core.c1
-rw-r--r--drivers/media/pci/saa7134/saa7134-empress.c4
-rw-r--r--drivers/media/pci/saa7134/saa7134-video.c2
-rw-r--r--drivers/media/pci/saa7164/saa7164-dvb.c32
-rw-r--r--drivers/media/pci/sta2x11/sta2x11_vip.c2
-rw-r--r--drivers/media/pci/zoran/zr36050.h1
-rw-r--r--drivers/media/platform/Kconfig1
-rw-r--r--drivers/media/platform/arv.c1
-rw-r--r--drivers/media/platform/blackfin/bfin_capture.c1
-rw-r--r--drivers/media/platform/coda.c210
-rw-r--r--drivers/media/platform/davinci/dm644x_ccdc.c5
-rw-r--r--drivers/media/platform/davinci/vpbe_display.c1
-rw-r--r--drivers/media/platform/davinci/vpfe_capture.c1
-rw-r--r--drivers/media/platform/davinci/vpif_capture.c248
-rw-r--r--drivers/media/platform/davinci/vpif_capture.h11
-rw-r--r--drivers/media/platform/davinci/vpif_display.c4
-rw-r--r--drivers/media/platform/m2m-deinterlace.c7
-rw-r--r--drivers/media/platform/mem2mem_testdev.c1
-rw-r--r--drivers/media/platform/omap/omap_vout.c2
-rw-r--r--drivers/media/platform/s3c-camif/camif-capture.c3
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c5
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_dec.c9
-rw-r--r--drivers/media/platform/s5p-mfc/s5p_mfc_pm.c24
-rw-r--r--drivers/media/platform/s5p-tv/mixer_video.c2
-rw-r--r--drivers/media/platform/sh_veu.c2
-rw-r--r--drivers/media/platform/soc_camera/Kconfig18
-rw-r--r--drivers/media/platform/soc_camera/Makefile1
-rw-r--r--drivers/media/platform/soc_camera/mx1_camera.c866
-rw-r--r--drivers/media/platform/soc_camera/rcar_vin.c12
-rw-r--r--drivers/media/platform/soc_camera/soc_camera.c12
-rw-r--r--drivers/media/platform/vino.c5
-rw-r--r--drivers/media/platform/vivi.c11
-rw-r--r--drivers/media/platform/vsp1/vsp1.h14
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.c85
-rw-r--r--drivers/media/platform/vsp1/vsp1_bru.h9
-rw-r--r--drivers/media/platform/vsp1/vsp1_drv.c22
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.c42
-rw-r--r--drivers/media/platform/vsp1/vsp1_entity.h10
-rw-r--r--drivers/media/platform/vsp1/vsp1_regs.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_rpf.c72
-rw-r--r--drivers/media/platform/vsp1/vsp1_rwpf.h2
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.c107
-rw-r--r--drivers/media/platform/vsp1/vsp1_sru.h1
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.c63
-rw-r--r--drivers/media/platform/vsp1/vsp1_uds.h6
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.c219
-rw-r--r--drivers/media/platform/vsp1/vsp1_video.h11
-rw-r--r--drivers/media/platform/vsp1/vsp1_wpf.c72
-rw-r--r--drivers/media/radio/dsbr100.c1
-rw-r--r--drivers/media/radio/radio-cadet.c1
-rw-r--r--drivers/media/radio/radio-isa.c1
-rw-r--r--drivers/media/radio/radio-keene.c3
-rw-r--r--drivers/media/radio/radio-ma901.c1
-rw-r--r--drivers/media/radio/radio-miropcm20.c1
-rw-r--r--drivers/media/radio/radio-mr800.c3
-rw-r--r--drivers/media/radio/radio-raremono.c1
-rw-r--r--drivers/media/radio/radio-sf16fmi.c1
-rw-r--r--drivers/media/radio/radio-si476x.c1
-rw-r--r--drivers/media/radio/radio-tea5764.c1
-rw-r--r--drivers/media/radio/radio-tea5777.c1
-rw-r--r--drivers/media/radio/radio-timb.c1
-rw-r--r--drivers/media/radio/si470x/radio-si470x-usb.c1
-rw-r--r--drivers/media/radio/si4713/radio-platform-si4713.c1
-rw-r--r--drivers/media/radio/si4713/radio-usb-si4713.c1
-rw-r--r--drivers/media/radio/si4713/si4713.c4
-rw-r--r--drivers/media/radio/tea575x.c1
-rw-r--r--drivers/media/rc/Kconfig10
-rw-r--r--drivers/media/rc/Makefile1
-rw-r--r--drivers/media/rc/img-ir/img-ir-core.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-hw.h5
-rw-r--r--drivers/media/rc/img-ir/img-ir-jvc.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-nec.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-raw.h5
-rw-r--r--drivers/media/rc/img-ir/img-ir-sanyo.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-sharp.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir-sony.c5
-rw-r--r--drivers/media/rc/img-ir/img-ir.h5
-rw-r--r--drivers/media/rc/sunxi-cir.c318
-rw-r--r--drivers/media/tuners/Kconfig6
-rw-r--r--drivers/media/tuners/Makefile1
-rw-r--r--drivers/media/tuners/msi001.c (renamed from drivers/staging/media/msi3101/msi001.c)2
-rw-r--r--drivers/media/tuners/r820t.c2
-rw-r--r--drivers/media/tuners/si2157.c257
-rw-r--r--drivers/media/tuners/si2157.h7
-rw-r--r--drivers/media/tuners/si2157_priv.h9
-rw-r--r--drivers/media/usb/Kconfig6
-rw-r--r--drivers/media/usb/Makefile2
-rw-r--r--drivers/media/usb/airspy/Kconfig10
-rw-r--r--drivers/media/usb/airspy/Makefile1
-rw-r--r--drivers/media/usb/airspy/airspy.c1132
-rw-r--r--drivers/media/usb/au0828/Kconfig1
-rw-r--r--drivers/media/usb/au0828/au0828-video.c62
-rw-r--r--drivers/media/usb/cpia2/cpia2_v4l.c1
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-417.c3
-rw-r--r--drivers/media/usb/cx231xx/cx231xx-video.c14
-rw-r--r--drivers/media/usb/dvb-usb-v2/Kconfig1
-rw-r--r--drivers/media/usb/dvb-usb-v2/lmedm04.c25
-rw-r--r--drivers/media/usb/dvb-usb-v2/mxl111sf.c2
-rw-r--r--drivers/media/usb/dvb-usb/Kconfig3
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.c231
-rw-r--r--drivers/media/usb/dvb-usb/cxusb.h2
-rw-r--r--drivers/media/usb/dvb-usb/dib0700_devices.c612
-rw-r--r--drivers/media/usb/dvb-usb/technisat-usb2.c2
-rw-r--r--drivers/media/usb/em28xx/em28xx-cards.c2
-rw-r--r--drivers/media/usb/em28xx/em28xx-dvb.c1
-rw-r--r--drivers/media/usb/em28xx/em28xx-video.c1
-rw-r--r--drivers/media/usb/gspca/autogain_functions.c4
-rw-r--r--drivers/media/usb/gspca/gspca.c29
-rw-r--r--drivers/media/usb/gspca/gspca.h1
-rw-r--r--drivers/media/usb/gspca/kinect.c98
-rw-r--r--drivers/media/usb/gspca/pac7302.c8
-rw-r--r--drivers/media/usb/gspca/sonixb.c2
-rw-r--r--drivers/media/usb/hdpvr/hdpvr-video.c4
-rw-r--r--drivers/media/usb/msi2500/Kconfig5
-rw-r--r--drivers/media/usb/msi2500/Makefile1
-rw-r--r--drivers/media/usb/msi2500/msi2500.c (renamed from drivers/staging/media/msi3101/sdr-msi3101.c)79
-rw-r--r--drivers/media/usb/pvrusb2/pvrusb2-v4l2.c12
-rw-r--r--drivers/media/usb/pwc/pwc-if.c1
-rw-r--r--drivers/media/usb/s2255/s2255drv.c1
-rw-r--r--drivers/media/usb/stk1160/stk1160-v4l.c1
-rw-r--r--drivers/media/usb/stkwebcam/stk-webcam.c3
-rw-r--r--drivers/media/usb/tlg2300/pd-main.c2
-rw-r--r--drivers/media/usb/tlg2300/pd-radio.c1
-rw-r--r--drivers/media/usb/tlg2300/pd-video.c1
-rw-r--r--drivers/media/usb/tm6000/tm6000-video.c3
-rw-r--r--drivers/media/usb/usbtv/usbtv-core.c2
-rw-r--r--drivers/media/usb/usbtv/usbtv-video.c1
-rw-r--r--drivers/media/usb/usbvision/usbvision-core.c16
-rw-r--r--drivers/media/usb/uvc/uvc_driver.c1
-rw-r--r--drivers/media/usb/zr364xx/zr364xx.c4
-rw-r--r--drivers/media/v4l2-core/v4l2-common.c6
-rw-r--r--drivers/media/v4l2-core/v4l2-compat-ioctl32.c19
-rw-r--r--drivers/media/v4l2-core/v4l2-ctrls.c904
-rw-r--r--drivers/media/v4l2-core/v4l2-dev.c14
-rw-r--r--drivers/media/v4l2-core/v4l2-fh.c13
-rw-r--r--drivers/media/v4l2-core/v4l2-ioctl.c239
-rw-r--r--drivers/media/v4l2-core/v4l2-mem2mem.c8
-rw-r--r--drivers/media/v4l2-core/v4l2-subdev.c125
-rw-r--r--drivers/media/v4l2-core/videobuf2-core.c122
-rw-r--r--drivers/media/v4l2-core/videobuf2-dma-contig.c8
-rw-r--r--drivers/staging/media/Kconfig6
-rw-r--r--drivers/staging/media/Makefile3
-rw-r--r--drivers/staging/media/bcm2048/radio-bcm2048.c22
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe.c2
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h1
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_ipipeif.c5
-rw-r--r--drivers/staging/media/davinci_vpfe/dm365_resizer.c4
-rw-r--r--drivers/staging/media/davinci_vpfe/vpfe_video.c1
-rw-r--r--drivers/staging/media/go7007/README1
-rw-r--r--drivers/staging/media/go7007/go7007-driver.c133
-rw-r--r--drivers/staging/media/go7007/go7007-fw.c32
-rw-r--r--drivers/staging/media/go7007/go7007-i2c.c4
-rw-r--r--drivers/staging/media/go7007/go7007-loader.c4
-rw-r--r--drivers/staging/media/go7007/go7007-priv.h20
-rw-r--r--drivers/staging/media/go7007/go7007-usb.c4
-rw-r--r--drivers/staging/media/go7007/go7007-v4l2.c322
-rw-r--r--drivers/staging/media/go7007/go7007.h40
-rw-r--r--drivers/staging/media/go7007/s2250-board.c9
-rw-r--r--drivers/staging/media/go7007/saa7134-go7007.c35
-rw-r--r--drivers/staging/media/go7007/snd-go7007.c4
-rw-r--r--drivers/staging/media/msi3101/Kconfig10
-rw-r--r--drivers/staging/media/msi3101/Makefile2
-rw-r--r--drivers/staging/media/omap4iss/iss.c86
-rw-r--r--drivers/staging/media/omap4iss/iss_video.c22
-rw-r--r--drivers/staging/media/rtl2832u_sdr/Kconfig7
-rw-r--r--drivers/staging/media/rtl2832u_sdr/Makefile6
-rw-r--r--drivers/staging/media/sn9c102/Kconfig17
-rw-r--r--drivers/staging/media/sn9c102/Makefile15
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.h214
-rw-r--r--drivers/staging/media/sn9c102/sn9c102.txt592
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_config.h86
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_core.c3465
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_devtable.h145
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131d.c269
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_hv7131r.c369
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0343.c352
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mi0360.c453
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_mt9v111.c260
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7630.c634
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_ov7660.c546
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas106b.c308
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_pas202bcb.c340
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_sensor.h307
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c154
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5110d.c119
-rw-r--r--drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c165
-rw-r--r--drivers/staging/media/solo6x10/Kconfig1
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-core.c6
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-disp.c18
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-eeprom.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-enc.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-g723.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-gpio.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-i2c.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-jpeg.h6
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-offsets.h4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-p2m.c4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-regs.h4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-tw28.c5
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-tw28.h4
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c200
-rw-r--r--drivers/staging/media/solo6x10/solo6x10-v4l2.c9
-rw-r--r--drivers/staging/media/solo6x10/solo6x10.h30
-rw-r--r--include/media/v4l2-ctrls.h196
-rw-r--r--include/media/v4l2-dev.h2
-rw-r--r--include/media/v4l2-ioctl.h2
-rw-r--r--include/media/videobuf2-core.h3
-rw-r--r--include/uapi/linux/v4l2-controls.h17
-rw-r--r--include/uapi/linux/videodev2.h99
292 files changed, 7894 insertions, 13111 deletions
diff --git a/Documentation/DocBook/media/Makefile b/Documentation/DocBook/media/Makefile
index 639e74857968..df2962d9e11e 100644
--- a/Documentation/DocBook/media/Makefile
+++ b/Documentation/DocBook/media/Makefile
@@ -174,7 +174,7 @@ FILENAME = \
DOCUMENTED = \
-e "s/\(enum *\)v4l2_mpeg_cx2341x_video_\([a-z]*_spatial_filter_type\)/\1<link linkend=\"\2\">v4l2_mpeg_cx2341x_video_\2<\/link>/g" \
-e "s/\(\(enum\|struct\) *\)\(v4l2_[a-zA-Z0-9_]*\)/\1<link linkend=\"\3\">\3<\/link>/g" \
- -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\) /<link linkend=\"\1\">\1<\/link> /g" \
+ -e "s/\(V4L2_PIX_FMT_[A-Z0-9_]\+\)\(\s\+v4l2_fourcc\)/<link linkend=\"\1\">\1<\/link>\2/g" \
-e ":a;s/\(linkend=\".*\)_\(.*\">\)/\1-\2/;ta" \
-e "s/v4l2\-mpeg\-vbi\-ITV0/v4l2-mpeg-vbi-itv0-1/g"
diff --git a/Documentation/DocBook/media/v4l/controls.xml b/Documentation/DocBook/media/v4l/controls.xml
index 47198eef75a4..74f575560f1b 100644
--- a/Documentation/DocBook/media/v4l/controls.xml
+++ b/Documentation/DocBook/media/v4l/controls.xml
@@ -13,6 +13,19 @@ correctly with any device.</para>
<para>All controls are accessed using an ID value. V4L2 defines
several IDs for specific purposes. Drivers can also implement their
own custom controls using <constant>V4L2_CID_PRIVATE_BASE</constant>
+<footnote><para>The use of <constant>V4L2_CID_PRIVATE_BASE</constant>
+is problematic because different drivers may use the same
+<constant>V4L2_CID_PRIVATE_BASE</constant> ID for different controls.
+This makes it hard to programatically set such controls since the meaning
+of the control with that ID is driver dependent. In order to resolve this
+drivers use unique IDs and the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs are mapped to those unique IDs by the kernel. Consider these
+<constant>V4L2_CID_PRIVATE_BASE</constant> IDs as aliases to the real
+IDs.</para>
+<para>Many applications today still use the <constant>V4L2_CID_PRIVATE_BASE</constant>
+IDs instead of using &VIDIOC-QUERYCTRL; with the <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>
+flag to enumerate all IDs, so support for <constant>V4L2_CID_PRIVATE_BASE</constant>
+is still around.</para></footnote>
and higher values. The pre-defined control IDs have the prefix
<constant>V4L2_CID_</constant>, and are listed in <xref
linkend="control-id" />. The ID is used when querying the attributes of
@@ -31,25 +44,22 @@ the current video input or output, tuner or modulator, or audio input
or output. Different in the sense of other bounds, another default and
current value, step size or other menu items. A control with a certain
<emphasis>custom</emphasis> ID can also change name and
-type.<footnote>
- <para>It will be more convenient for applications if drivers
-make use of the <constant>V4L2_CTRL_FLAG_DISABLED</constant> flag, but
-that was never required.</para>
- </footnote> Control values are stored globally, they do not
+type.</para>
+
+ <para>If a control is not applicable to the current configuration
+of the device (for example, it doesn't apply to the current video input)
+drivers set the <constant>V4L2_CTRL_FLAG_INACTIVE</constant> flag.</para>
+
+ <para>Control values are stored globally, they do not
change when switching except to stay within the reported bounds. They
also do not change &eg; when the device is opened or closed, when the
tuner radio frequency is changed or generally never without
-application request. Since V4L2 specifies no event mechanism, panel
-applications intended to cooperate with other panel applications (be
-they built into a larger application, as a TV viewer) may need to
-regularly poll control values to update their user
-interface.<footnote>
- <para>Applications could call an ioctl to request events.
-After another process called &VIDIOC-S-CTRL; or another ioctl changing
-shared properties the &func-select; function would indicate
-readability until any ioctl (querying the properties) is
-called.</para>
- </footnote></para>
+application request.</para>
+
+ <para>V4L2 specifies an event mechanism to notify applications
+when controls change value (see &VIDIOC-SUBSCRIBE-EVENT;, event
+<constant>V4L2_EVENT_CTRL</constant>), panel applications might want to make
+use of that in order to always reflect the correct control value.</para>
<para>
All controls use machine endianness.
@@ -398,14 +408,17 @@ to work.</entry>
<row id="v4l2-alpha-component">
<entry><constant>V4L2_CID_ALPHA_COMPONENT</constant></entry>
<entry>integer</entry>
- <entry> Sets the alpha color component on the capture device or on
- the capture buffer queue of a mem-to-mem device. When a mem-to-mem
- device produces frame format that includes an alpha component
+ <entry>Sets the alpha color component. When a capture device (or
+ capture queue of a mem-to-mem device) produces a frame format that
+ includes an alpha component
(e.g. <link linkend="rgb-formats">packed RGB image formats</link>)
- and the alpha value is not defined by the mem-to-mem input data
- this control lets you select the alpha component value of all
- pixels. It is applicable to any pixel format that contains an alpha
- component.
+ and the alpha value is not defined by the device or the mem-to-mem
+ input data this control lets you select the alpha component value of
+ all pixels. When an output device (or output queue of a mem-to-mem
+ device) consumes a frame format that doesn't include an alpha
+ component and the device supports alpha channel processing this
+ control lets you set the alpha component value of all pixels for
+ further processing in the device.
</entry>
</row>
<row>
@@ -434,127 +447,152 @@ Drivers must implement <constant>VIDIOC_QUERYCTRL</constant>,
controls, <constant>VIDIOC_QUERYMENU</constant> when it has one or
more menu type controls.</para>
- <example>
- <title>Enumerating all controls</title>
+ <example id="enum_all_controls">
+ <title>Enumerating all user controls</title>
<programlisting>
&v4l2-queryctrl; queryctrl;
&v4l2-querymenu; querymenu;
-static void
-enumerate_menu (void)
+static void enumerate_menu(void)
{
- printf (" Menu items:\n");
+ printf(" Menu items:\n");
- memset (&amp;querymenu, 0, sizeof (querymenu));
+ memset(&amp;querymenu, 0, sizeof(querymenu));
querymenu.id = queryctrl.id;
for (querymenu.index = queryctrl.minimum;
querymenu.index &lt;= queryctrl.maximum;
- querymenu.index++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
- printf (" %s\n", querymenu.name);
+ querymenu.index++) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYMENU;, &amp;querymenu)) {
+ printf(" %s\n", querymenu.name);
}
}
}
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
for (queryctrl.id = V4L2_CID_BASE;
queryctrl.id &lt; V4L2_CID_LASTP1;
queryctrl.id++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
continue;
- printf ("Control %s\n", queryctrl.name);
+ printf("Control %s\n", queryctrl.name);
if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu ();
+ enumerate_menu();
} else {
if (errno == EINVAL)
continue;
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
}
}
for (queryctrl.id = V4L2_CID_PRIVATE_BASE;;
queryctrl.id++) {
- if (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
continue;
- printf ("Control %s\n", queryctrl.name);
+ printf("Control %s\n", queryctrl.name);
if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
- enumerate_menu ();
+ enumerate_menu();
} else {
if (errno == EINVAL)
break;
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
}
}
</programlisting>
</example>
<example>
+ <title>Enumerating all user controls (alternative)</title>
+ <programlisting>
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
+
+queryctrl.id = V4L2_CTRL_CLASS_USER | V4L2_CTRL_FLAG_NEXT_CTRL;
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+ if (V4L2_CTRL_ID2CLASS(queryctrl.id) != V4L2_CTRL_CLASS_USER)
+ break;
+ if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED)
+ continue;
+
+ printf("Control %s\n", queryctrl.name);
+
+ if (queryctrl.type == V4L2_CTRL_TYPE_MENU)
+ enumerate_menu();
+
+ queryctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
+if (errno != EINVAL) {
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
+}
+</programlisting>
+ </example>
+
+ <example>
<title>Changing controls</title>
<programlisting>
&v4l2-queryctrl; queryctrl;
&v4l2-control; control;
-memset (&amp;queryctrl, 0, sizeof (queryctrl));
+memset(&amp;queryctrl, 0, sizeof(queryctrl));
queryctrl.id = V4L2_CID_BRIGHTNESS;
-if (-1 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
+if (-1 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;queryctrl)) {
if (errno != EINVAL) {
- perror ("VIDIOC_QUERYCTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_QUERYCTRL");
+ exit(EXIT_FAILURE);
} else {
- printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ printf("V4L2_CID_BRIGHTNESS is not supported\n");
}
} else if (queryctrl.flags &amp; V4L2_CTRL_FLAG_DISABLED) {
- printf ("V4L2_CID_BRIGHTNESS is not supported\n");
+ printf("V4L2_CID_BRIGHTNESS is not supported\n");
} else {
- memset (&amp;control, 0, sizeof (control));
+ memset(&amp;control, 0, sizeof (control));
control.id = V4L2_CID_BRIGHTNESS;
control.value = queryctrl.default_value;
- if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)) {
- perror ("VIDIOC_S_CTRL");
- exit (EXIT_FAILURE);
+ if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)) {
+ perror("VIDIOC_S_CTRL");
+ exit(EXIT_FAILURE);
}
}
-memset (&amp;control, 0, sizeof (control));
+memset(&amp;control, 0, sizeof(control));
control.id = V4L2_CID_CONTRAST;
-if (0 == ioctl (fd, &VIDIOC-G-CTRL;, &amp;control)) {
+if (0 == ioctl(fd, &VIDIOC-G-CTRL;, &amp;control)) {
control.value += 1;
/* The driver may clamp the value or return ERANGE, ignored here */
- if (-1 == ioctl (fd, &VIDIOC-S-CTRL;, &amp;control)
+ if (-1 == ioctl(fd, &VIDIOC-S-CTRL;, &amp;control)
&amp;&amp; errno != ERANGE) {
- perror ("VIDIOC_S_CTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_S_CTRL");
+ exit(EXIT_FAILURE);
}
/* Ignore if V4L2_CID_CONTRAST is unsupported */
} else if (errno != EINVAL) {
- perror ("VIDIOC_G_CTRL");
- exit (EXIT_FAILURE);
+ perror("VIDIOC_G_CTRL");
+ exit(EXIT_FAILURE);
}
control.id = V4L2_CID_AUDIO_MUTE;
-control.value = TRUE; /* silence */
+control.value = 1; /* silence */
/* Errors ignored */
-ioctl (fd, VIDIOC_S_CTRL, &amp;control);
+ioctl(fd, VIDIOC_S_CTRL, &amp;control);
</programlisting>
</example>
</section>
@@ -625,16 +663,29 @@ supported.</para>
&v4l2-control;, except for the fact that it also allows for 64-bit
values and pointers to be passed.</para>
+ <para>Since the &v4l2-ext-control; supports pointers it is now
+also possible to have controls with compound types such as N-dimensional arrays
+and/or structures. You need to specify the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+when enumerating controls to actually be able to see such compound controls.
+In other words, these controls with compound types should only be used
+programmatically.</para>
+
+ <para>Since such compound controls need to expose more information
+about themselves than is possible with &VIDIOC-QUERYCTRL; the
+&VIDIOC-QUERY-EXT-CTRL; ioctl was added. In particular, this ioctl gives
+the dimensions of the N-dimensional array if this control consists of more than
+one element.</para>
+
<para>It is important to realize that due to the flexibility of
controls it is necessary to check whether the control you want to set
actually is supported in the driver and what the valid range of values
-is. So use the &VIDIOC-QUERYCTRL; and &VIDIOC-QUERYMENU; ioctls to
-check this. Also note that it is possible that some of the menu
-indices in a control of type <constant>V4L2_CTRL_TYPE_MENU</constant>
-may not be supported (<constant>VIDIOC_QUERYMENU</constant> will
-return an error). A good example is the list of supported MPEG audio
-bitrates. Some drivers only support one or two bitrates, others
-support a wider range.</para>
+is. So use the &VIDIOC-QUERYCTRL; (or &VIDIOC-QUERY-EXT-CTRL;) and
+&VIDIOC-QUERYMENU; ioctls to check this. Also note that it is possible
+that some of the menu indices in a control of type
+<constant>V4L2_CTRL_TYPE_MENU</constant> may not be supported
+(<constant>VIDIOC_QUERYMENU</constant> will return an error). A good
+example is the list of supported MPEG audio bitrates. Some drivers only
+support one or two bitrates, others support a wider range.</para>
<para>
All controls use machine endianness.
@@ -675,12 +726,12 @@ control class is found:</para>
<informalexample>
<programlisting>
qctrl.id = V4L2_CTRL_CLASS_MPEG | V4L2_CTRL_FLAG_NEXT_CTRL;
-while (0 == ioctl (fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
- if (V4L2_CTRL_ID2CLASS (qctrl.id) != V4L2_CTRL_CLASS_MPEG)
+while (0 == ioctl(fd, &VIDIOC-QUERYCTRL;, &amp;qctrl)) {
+ if (V4L2_CTRL_ID2CLASS(qctrl.id) != V4L2_CTRL_CLASS_MPEG)
break;
/* ... */
- qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
- }
+ qctrl.id |= V4L2_CTRL_FLAG_NEXT_CTRL;
+}
</programlisting>
</informalexample>
@@ -700,7 +751,7 @@ ID based on a control ID.</para>
<constant>VIDIOC_QUERYCTRL</constant> will fail when used in
combination with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant>. In
that case the old method of enumerating control should be used (see
-1.8). But if it is supported, then it is guaranteed to enumerate over
+<xref linkend="enum_all_controls" />). But if it is supported, then it is guaranteed to enumerate over
all controls, including driver-private controls.</para>
</section>
@@ -5007,6 +5058,102 @@ defines possible values for de-emphasis. Here they are:</entry>
</tbody>
</tgroup>
</table>
+ </section>
+
+ <section id="detect-controls">
+ <title>Detect Control Reference</title>
+
+ <para>The Detect class includes controls for common features of
+ various motion or object detection capable devices.</para>
+
+ <table pgwide="1" frame="none" id="detect-control-id">
+ <title>Detect Control IDs</title>
+
+ <tgroup cols="4">
+ <colspec colname="c1" colwidth="1*" />
+ <colspec colname="c2" colwidth="6*" />
+ <colspec colname="c3" colwidth="2*" />
+ <colspec colname="c4" colwidth="6*" />
+ <spanspec namest="c1" nameend="c2" spanname="id" />
+ <spanspec namest="c2" nameend="c4" spanname="descr" />
+ <thead>
+ <row>
+ <entry spanname="id" align="left">ID</entry>
+ <entry align="left">Type</entry>
+ </row><row rowsep="1"><entry spanname="descr" align="left">Description</entry>
+ </row>
+ </thead>
+ <tbody valign="top">
+ <row><entry></entry></row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_CLASS</constant>&nbsp;</entry>
+ <entry>class</entry>
+ </row><row><entry spanname="descr">The Detect class
+descriptor. Calling &VIDIOC-QUERYCTRL; for this control will return a
+description of this control class.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_MODE</constant>&nbsp;</entry>
+ <entry>menu</entry>
+ </row><row><entry spanname="descr">Sets the motion detection mode.</entry>
+ </row>
+ <row>
+ <entrytbl spanname="descr" cols="2">
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_DISABLED</constant>
+ </entry><entry>Disable motion detection.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_GLOBAL</constant>
+ </entry><entry>Use a single motion detection threshold.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+ </entry><entry>The image is divided into a grid, each cell with its own
+ motion detection threshold. These thresholds are set through the
+ <constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant> matrix control.</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+ </entry><entry>The image is divided into a grid, each cell with its own
+ region value that specifies which per-region motion detection thresholds
+ should be used. Each region has its own thresholds. How these per-region
+ thresholds are set up is driver-specific. The region values for the grid are set
+ through the <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> matrix
+ control.</entry>
+ </row>
+ </tbody>
+ </entrytbl>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD</constant>&nbsp;</entry>
+ <entry>integer</entry>
+ </row>
+ <row><entry spanname="descr">Sets the global motion detection threshold to be
+ used with the <constant>V4L2_DETECT_MD_MODE_GLOBAL</constant> motion detection mode.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_THRESHOLD_GRID</constant>&nbsp;</entry>
+ <entry>__u16 matrix</entry>
+ </row>
+ <row><entry spanname="descr">Sets the motion detection thresholds for each cell in the grid.
+ To be used with the <constant>V4L2_DETECT_MD_MODE_THRESHOLD_GRID</constant>
+ motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+ grid.</entry>
+ </row>
+ <row>
+ <entry spanname="id"><constant>V4L2_CID_DETECT_MD_REGION_GRID</constant>&nbsp;</entry>
+ <entry>__u8 matrix</entry>
+ </row>
+ <row><entry spanname="descr">Sets the motion detection region value for each cell in the grid.
+ To be used with the <constant>V4L2_DETECT_MD_MODE_REGION_GRID</constant>
+ motion detection mode. Matrix element (0, 0) represents the cell at the top-left of the
+ grid.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</section>
diff --git a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml b/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
index b788c72c885e..f4b61b6ce3c2 100644
--- a/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
+++ b/Documentation/DocBook/media/v4l/dev-raw-vbi.xml
@@ -150,9 +150,15 @@ signal. Drivers shall not convert the sample format by software.</para></entry>
<entry>This is the scanning system line number
associated with the first line of the VBI image, of the first and the
second field respectively. See <xref linkend="vbi-525" /> and
-<xref linkend="vbi-625" /> for valid values. VBI input drivers can
-return start values 0 if the hardware cannot reliable identify
-scanning lines, VBI acquisition may not require this
+<xref linkend="vbi-625" /> for valid values.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start line
+numbers for each field for each 525 or 625 line format as a convenience.
+Don't forget that ITU line numbering starts at 1, not 0.
+VBI input drivers can return start values 0 if the hardware cannot
+reliable identify scanning lines, VBI acquisition may not require this
information.</entry>
</row>
<row>
diff --git a/Documentation/DocBook/media/v4l/dev-sdr.xml b/Documentation/DocBook/media/v4l/dev-sdr.xml
index dc14804f5436..f8903568a243 100644
--- a/Documentation/DocBook/media/v4l/dev-sdr.xml
+++ b/Documentation/DocBook/media/v4l/dev-sdr.xml
@@ -72,9 +72,12 @@ To use the <link linkend="format">format</link> ioctls applications set the
<constant>V4L2_BUF_TYPE_SDR_CAPTURE</constant> and use the &v4l2-sdr-format;
<structfield>sdr</structfield> member of the <structfield>fmt</structfield>
union as needed per the desired operation.
-Currently only the <structfield>pixelformat</structfield> field of
-&v4l2-sdr-format; is used. The content of that field is the V4L2 fourcc code
-of the data format.
+Currently there is two fields, <structfield>pixelformat</structfield> and
+<structfield>buffersize</structfield>, of struct &v4l2-sdr-format; which are
+used. Content of the <structfield>pixelformat</structfield> is V4L2 FourCC
+code of the data format. The <structfield>buffersize</structfield> field is
+maximum buffer size in bytes required for data transfer, set by the driver in
+order to inform application.
</para>
<table pgwide="1" frame="none" id="v4l2-sdr-format">
@@ -92,8 +95,15 @@ V4L2 defines SDR formats in <xref linkend="sdr-formats" />.
</entry>
</row>
<row>
+ <entry>__u32</entry>
+ <entry><structfield>buffersize</structfield></entry>
+ <entry>
+Maximum size in bytes required for data. Value is set by the driver.
+ </entry>
+ </row>
+ <row>
<entry>__u8</entry>
- <entry><structfield>reserved[28]</structfield></entry>
+ <entry><structfield>reserved[24]</structfield></entry>
<entry>This array is reserved for future extensions.
Drivers and applications must set it to zero.</entry>
</row>
diff --git a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml b/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
index 548f8ea28dee..7a8bf3011ee9 100644
--- a/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
+++ b/Documentation/DocBook/media/v4l/dev-sliced-vbi.xml
@@ -185,7 +185,14 @@ tables, sigh. --></para></entry>
<entry></entry>
<entry spanname="hspan">Drivers must set
<structfield>service_lines</structfield>[0][0] and
-<structfield>service_lines</structfield>[1][0] to zero.</entry>
+<structfield>service_lines</structfield>[1][0] to zero.
+The <constant>V4L2_VBI_ITU_525_F1_START</constant>,
+<constant>V4L2_VBI_ITU_525_F2_START</constant>,
+<constant>V4L2_VBI_ITU_625_F1_START</constant> and
+<constant>V4L2_VBI_ITU_625_F2_START</constant> defines give the start
+line numbers for each field for each 525 or 625 line format as a
+convenience. Don't forget that ITU line numbering starts at 1, not 0.
+</entry>
</row>
<row>
<entry>__u32</entry>
diff --git a/Documentation/DocBook/media/v4l/io.xml b/Documentation/DocBook/media/v4l/io.xml
index a086a5db7a18..8c4ee746a731 100644
--- a/Documentation/DocBook/media/v4l/io.xml
+++ b/Documentation/DocBook/media/v4l/io.xml
@@ -1066,7 +1066,7 @@ state, in the application domain so to say.</entry>
<entry>Drivers set or clear this flag when calling the
<constant>VIDIOC_DQBUF</constant> ioctl. It may be set by video
capture devices when the buffer contains a compressed image which is a
-key frame (or field), &ie; can be decompressed on its own. Also know as
+key frame (or field), &ie; can be decompressed on its own. Also known as
an I-frame. Applications can set this bit when <structfield>type</structfield>
refers to an output stream.</entry>
</row>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
index e1c4f8b4c0b3..2aae8e9452a4 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-packed-rgb.xml
@@ -15,9 +15,6 @@ typical PC graphics frame buffers. They occupy 8, 16, 24 or 32 bits
per pixel. These are all packed-pixel formats, meaning all the data
for a pixel lie next to each other in memory.</para>
- <para>When one of these formats is used, drivers shall report the
-colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
-
<table pgwide="1" frame="none" id="rgb-formats">
<title>Packed RGB Image Formats</title>
<tgroup cols="37" align="center">
@@ -130,9 +127,9 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB444">
- <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
- <entry>'R444'</entry>
+ <row id="V4L2-PIX-FMT-ARGB444">
+ <entry><constant>V4L2_PIX_FMT_ARGB444</constant></entry>
+ <entry>'AR12'</entry>
<entry></entry>
<entry>g<subscript>3</subscript></entry>
<entry>g<subscript>2</subscript></entry>
@@ -152,9 +149,31 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>r<subscript>1</subscript></entry>
<entry>r<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB555">
- <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
- <entry>'RGBO'</entry>
+ <row id="V4L2-PIX-FMT-XRGB444">
+ <entry><constant>V4L2_PIX_FMT_XRGB444</constant></entry>
+ <entry>'XR12'</entry>
+ <entry></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-ARGB555">
+ <entry><constant>V4L2_PIX_FMT_ARGB555</constant></entry>
+ <entry>'AR15'</entry>
<entry></entry>
<entry>g<subscript>2</subscript></entry>
<entry>g<subscript>1</subscript></entry>
@@ -174,6 +193,28 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>g<subscript>4</subscript></entry>
<entry>g<subscript>3</subscript></entry>
</row>
+ <row id="V4L2-PIX-FMT-XRGB555">
+ <entry><constant>V4L2_PIX_FMT_XRGB555</constant></entry>
+ <entry>'XR15'</entry>
+ <entry></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ </row>
<row id="V4L2-PIX-FMT-RGB565">
<entry><constant>V4L2_PIX_FMT_RGB565</constant></entry>
<entry>'RGBP'</entry>
@@ -341,9 +382,9 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-BGR32">
- <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
- <entry>'BGR4'</entry>
+ <row id="V4L2-PIX-FMT-ABGR32">
+ <entry><constant>V4L2_PIX_FMT_ABGR32</constant></entry>
+ <entry>'AR24'</entry>
<entry></entry>
<entry>b<subscript>7</subscript></entry>
<entry>b<subscript>6</subscript></entry>
@@ -381,9 +422,49 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>a<subscript>1</subscript></entry>
<entry>a<subscript>0</subscript></entry>
</row>
- <row id="V4L2-PIX-FMT-RGB32">
- <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
- <entry>'RGB4'</entry>
+ <row id="V4L2-PIX-FMT-XBGR32">
+ <entry><constant>V4L2_PIX_FMT_XBGR32</constant></entry>
+ <entry>'XR24'</entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ </row>
+ <row id="V4L2-PIX-FMT-ARGB32">
+ <entry><constant>V4L2_PIX_FMT_ARGB32</constant></entry>
+ <entry>'AX24'</entry>
<entry></entry>
<entry>a<subscript>7</subscript></entry>
<entry>a<subscript>6</subscript></entry>
@@ -421,18 +502,76 @@ colorspace <constant>V4L2_COLORSPACE_SRGB</constant>.</para>
<entry>b<subscript>1</subscript></entry>
<entry>b<subscript>0</subscript></entry>
</row>
+ <row id="V4L2-PIX-FMT-XRGB32">
+ <entry><constant>V4L2_PIX_FMT_XRGB32</constant></entry>
+ <entry>'BX24'</entry>
+ <entry></entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry>-</entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
</tbody>
</tgroup>
</table>
- <para>Bit 7 is the most significant bit. The value of the a = alpha
-bits is undefined when reading from the driver, ignored when writing
-to the driver, except when alpha blending has been negotiated for a
-<link linkend="overlay">Video Overlay</link> or <link linkend="osd">
-Video Output Overlay</link> or when the alpha component has been configured
-for a <link linkend="capture">Video Capture</link> by means of <link
-linkend="v4l2-alpha-component"> <constant>V4L2_CID_ALPHA_COMPONENT
-</constant> </link> control.</para>
+ <para>Bit 7 is the most significant bit.</para>
+
+ <para>The usage and value of the alpha bits (a) in the ARGB and ABGR formats
+ (collectively referred to as alpha formats) depend on the device type and
+ hardware operation. <link linkend="capture">Capture</link> devices
+ (including capture queues of mem-to-mem devices) fill the alpha component in
+ memory. When the device outputs an alpha channel the alpha component will
+ have a meaningful value. Otherwise, when the device doesn't output an alpha
+ channel but can set the alpha bit to a user-configurable value, the <link
+ linkend="v4l2-alpha-component"><constant>V4L2_CID_ALPHA_COMPONENT</constant>
+ </link> control is used to specify that alpha value, and the alpha component
+ of all pixels will be set to the value specified by that control. Otherwise
+ a corresponding format without an alpha component (XRGB or XBGR) must be
+ used instead of an alpha format.</para>
+
+ <para><link linkend="output">Output</link> devices (including output queues
+ of mem-to-mem devices and <link linkend="osd">video output overlay</link>
+ devices) read the alpha component from memory. When the device processes the
+ alpha channel the alpha component must be filled with meaningful values by
+ applications. Otherwise a corresponding format without an alpha component
+ (XRGB or XBGR) must be used instead of an alpha format.</para>
+
+ <para>The XRGB and XBGR formats contain undefined bits (-). Applications,
+ devices and drivers must ignore those bits, for both <link
+ linkend="capture">capture</link> and <link linkend="output">output</link>
+ devices.</para>
<example>
<title><constant>V4L2_PIX_FMT_BGR24</constant> 4 &times; 4 pixel
@@ -512,6 +651,239 @@ image</title>
</formalpara>
</example>
+ <para>Formats defined in <xref linkend="rgb-formats-deprecated"/> are
+ deprecated and must not be used by new drivers. They are documented here for
+ reference. The meaning of their alpha bits (a) is ill-defined and
+ interpreted as in either the corresponding ARGB or XRGB format, depending on
+ the driver.</para>
+
+ <table pgwide="1" frame="none" id="rgb-formats-deprecated">
+ <title>Deprecated Packed RGB Image Formats</title>
+ <tgroup cols="37" align="center">
+ <colspec colname="id" align="left" />
+ <colspec colname="fourcc" />
+ <colspec colname="bit" />
+
+ <colspec colnum="4" colname="b07" align="center" />
+ <colspec colnum="5" colname="b06" align="center" />
+ <colspec colnum="6" colname="b05" align="center" />
+ <colspec colnum="7" colname="b04" align="center" />
+ <colspec colnum="8" colname="b03" align="center" />
+ <colspec colnum="9" colname="b02" align="center" />
+ <colspec colnum="10" colname="b01" align="center" />
+ <colspec colnum="11" colname="b00" align="center" />
+
+ <colspec colnum="13" colname="b17" align="center" />
+ <colspec colnum="14" colname="b16" align="center" />
+ <colspec colnum="15" colname="b15" align="center" />
+ <colspec colnum="16" colname="b14" align="center" />
+ <colspec colnum="17" colname="b13" align="center" />
+ <colspec colnum="18" colname="b12" align="center" />
+ <colspec colnum="19" colname="b11" align="center" />
+ <colspec colnum="20" colname="b10" align="center" />
+
+ <colspec colnum="22" colname="b27" align="center" />
+ <colspec colnum="23" colname="b26" align="center" />
+ <colspec colnum="24" colname="b25" align="center" />
+ <colspec colnum="25" colname="b24" align="center" />
+ <colspec colnum="26" colname="b23" align="center" />
+ <colspec colnum="27" colname="b22" align="center" />
+ <colspec colnum="28" colname="b21" align="center" />
+ <colspec colnum="29" colname="b20" align="center" />
+
+ <colspec colnum="31" colname="b37" align="center" />
+ <colspec colnum="32" colname="b36" align="center" />
+ <colspec colnum="33" colname="b35" align="center" />
+ <colspec colnum="34" colname="b34" align="center" />
+ <colspec colnum="35" colname="b33" align="center" />
+ <colspec colnum="36" colname="b32" align="center" />
+ <colspec colnum="37" colname="b31" align="center" />
+ <colspec colnum="38" colname="b30" align="center" />
+
+ <spanspec namest="b07" nameend="b00" spanname="b0" />
+ <spanspec namest="b17" nameend="b10" spanname="b1" />
+ <spanspec namest="b27" nameend="b20" spanname="b2" />
+ <spanspec namest="b37" nameend="b30" spanname="b3" />
+ <thead>
+ <row>
+ <entry>Identifier</entry>
+ <entry>Code</entry>
+ <entry>&nbsp;</entry>
+ <entry spanname="b0">Byte&nbsp;0 in memory</entry>
+ <entry spanname="b1">Byte&nbsp;1</entry>
+ <entry spanname="b2">Byte&nbsp;2</entry>
+ <entry spanname="b3">Byte&nbsp;3</entry>
+ </row>
+ <row>
+ <entry>&nbsp;</entry>
+ <entry>&nbsp;</entry>
+ <entry>Bit</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ <entry>&nbsp;</entry>
+ <entry>7</entry>
+ <entry>6</entry>
+ <entry>5</entry>
+ <entry>4</entry>
+ <entry>3</entry>
+ <entry>2</entry>
+ <entry>1</entry>
+ <entry>0</entry>
+ </row>
+ </thead>
+ <tbody>
+ <row id="V4L2-PIX-FMT-RGB444">
+ <entry><constant>V4L2_PIX_FMT_RGB444</constant></entry>
+ <entry>'R444'</entry>
+ <entry></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-RGB555">
+ <entry><constant>V4L2_PIX_FMT_RGB555</constant></entry>
+ <entry>'RGBO'</entry>
+ <entry></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a</entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-BGR32">
+ <entry><constant>V4L2_PIX_FMT_BGR32</constant></entry>
+ <entry>'BGR4'</entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>a<subscript>7</subscript></entry>
+ <entry>a<subscript>6</subscript></entry>
+ <entry>a<subscript>5</subscript></entry>
+ <entry>a<subscript>4</subscript></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ </row>
+ <row id="V4L2-PIX-FMT-RGB32">
+ <entry><constant>V4L2_PIX_FMT_RGB32</constant></entry>
+ <entry>'RGB4'</entry>
+ <entry></entry>
+ <entry>a<subscript>7</subscript></entry>
+ <entry>a<subscript>6</subscript></entry>
+ <entry>a<subscript>5</subscript></entry>
+ <entry>a<subscript>4</subscript></entry>
+ <entry>a<subscript>3</subscript></entry>
+ <entry>a<subscript>2</subscript></entry>
+ <entry>a<subscript>1</subscript></entry>
+ <entry>a<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>r<subscript>7</subscript></entry>
+ <entry>r<subscript>6</subscript></entry>
+ <entry>r<subscript>5</subscript></entry>
+ <entry>r<subscript>4</subscript></entry>
+ <entry>r<subscript>3</subscript></entry>
+ <entry>r<subscript>2</subscript></entry>
+ <entry>r<subscript>1</subscript></entry>
+ <entry>r<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>g<subscript>7</subscript></entry>
+ <entry>g<subscript>6</subscript></entry>
+ <entry>g<subscript>5</subscript></entry>
+ <entry>g<subscript>4</subscript></entry>
+ <entry>g<subscript>3</subscript></entry>
+ <entry>g<subscript>2</subscript></entry>
+ <entry>g<subscript>1</subscript></entry>
+ <entry>g<subscript>0</subscript></entry>
+ <entry></entry>
+ <entry>b<subscript>7</subscript></entry>
+ <entry>b<subscript>6</subscript></entry>
+ <entry>b<subscript>5</subscript></entry>
+ <entry>b<subscript>4</subscript></entry>
+ <entry>b<subscript>3</subscript></entry>
+ <entry>b<subscript>2</subscript></entry>
+ <entry>b<subscript>1</subscript></entry>
+ <entry>b<subscript>0</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<para>A test utility to determine which RGB formats a driver
actually supports is available from the LinuxTV v4l-dvb repository.
See &v4l-dvb; for access instructions.</para>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
new file mode 100644
index 000000000000..6118d8f7a20c
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs08.xml
@@ -0,0 +1,44 @@
+<refentry id="V4L2-SDR-FMT-CS08">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CS8 ('CS08')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CS8</constant>
+ </refname>
+ <refpurpose>Complex signed 8-bit IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 8 bit signed number. I value comes first and Q value after
+that.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CS8</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="2" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0</subscript></entry>
+ </row>
+ <row>
+ <entry>start&nbsp;+&nbsp;1:</entry>
+ <entry>Q'<subscript>0</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
new file mode 100644
index 000000000000..e4b494ce1369
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-cs14le.xml
@@ -0,0 +1,47 @@
+<refentry id="V4L2-SDR-FMT-CS14LE">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_CS14LE ('CS14')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_CS14LE</constant>
+ </refname>
+ <refpurpose>Complex signed 14-bit little endian IQ sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of complex number samples. Each complex number
+consist two parts, called In-phase and Quadrature (IQ). Both I and Q are
+represented as a 14 bit signed little endian number. I value comes first
+and Q value after that. 14 bit value is stored in 16 bit space with unused
+high bits padded with 0.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_CS14LE</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="3" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0[7:0]</subscript></entry>
+ <entry>I'<subscript>0[13:8]</subscript></entry>
+ </row>
+ <row>
+ <entry>start&nbsp;+&nbsp;2:</entry>
+ <entry>Q'<subscript>0[7:0]</subscript></entry>
+ <entry>Q'<subscript>0[13:8]</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml b/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
new file mode 100644
index 000000000000..3df076b99f94
--- /dev/null
+++ b/Documentation/DocBook/media/v4l/pixfmt-sdr-ru12le.xml
@@ -0,0 +1,40 @@
+<refentry id="V4L2-SDR-FMT-RU12LE">
+ <refmeta>
+ <refentrytitle>V4L2_SDR_FMT_RU12LE ('RU12')</refentrytitle>
+ &manvol;
+ </refmeta>
+ <refnamediv>
+ <refname>
+ <constant>V4L2_SDR_FMT_RU12LE</constant>
+ </refname>
+ <refpurpose>Real unsigned 12-bit little endian sample</refpurpose>
+ </refnamediv>
+ <refsect1>
+ <title>Description</title>
+ <para>
+This format contains sequence of real number samples. Each sample is
+represented as a 12 bit unsigned little endian number. Sample is stored
+in 16 bit space with unused high bits padded with 0.
+ </para>
+ <example>
+ <title><constant>V4L2_SDR_FMT_RU12LE</constant> 1 sample</title>
+ <formalpara>
+ <title>Byte Order.</title>
+ <para>Each cell is one byte.
+ <informaltable frame="none">
+ <tgroup cols="3" align="center">
+ <colspec align="left" colwidth="2*" />
+ <tbody valign="top">
+ <row>
+ <entry>start&nbsp;+&nbsp;0:</entry>
+ <entry>I'<subscript>0[7:0]</subscript></entry>
+ <entry>I'<subscript>0[11:8]</subscript></entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </informaltable>
+ </para>
+ </formalpara>
+ </example>
+ </refsect1>
+</refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
index 9ba4fb690bc0..96947f17fca1 100644
--- a/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt-srggb12.xml
@@ -18,7 +18,7 @@
<title>Description</title>
<para>The following four pixel formats are raw sRGB / Bayer formats with
-12 bits per colour. Each colour component is stored in a 16-bit word, with 6
+12 bits per colour. Each colour component is stored in a 16-bit word, with 4
unused high bits filled with zeros. Each n-pixel row contains n/2 green samples
and n/2 blue or red samples, with alternating red and blue rows. Bytes are
stored in memory in little endian order. They are conventionally described
diff --git a/Documentation/DocBook/media/v4l/pixfmt.xml b/Documentation/DocBook/media/v4l/pixfmt.xml
index 91dcbc84f3f8..df5b23d46552 100644
--- a/Documentation/DocBook/media/v4l/pixfmt.xml
+++ b/Documentation/DocBook/media/v4l/pixfmt.xml
@@ -112,9 +112,34 @@ see <xref linkend="colorspaces" />.</entry>
<row>
<entry>__u32</entry>
<entry><structfield>priv</structfield></entry>
- <entry>Reserved for custom (driver defined) additional
-information about formats. When not used drivers and applications must
-set this field to zero.</entry>
+ <entry><para>This field indicates whether the remaining fields of the
+<structname>v4l2_pix_format</structname> structure, also called the extended
+fields, are valid. When set to <constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, it
+indicates that the extended fields have been correctly initialized. When set to
+any other value it indicates that the extended fields contain undefined values.
+</para>
+<para>Applications that wish to use the pixel format extended fields must first
+ensure that the feature is supported by querying the device for the
+<link linkend="querycap"><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></link>
+capability. If the capability isn't set the pixel format extended fields are not
+supported and using the extended fields will lead to undefined results.</para>
+<para>To use the extended fields, applications must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant>, initialize all the extended fields
+and zero the unused bytes of the <structname>v4l2_format</structname>
+<structfield>raw_data</structfield> field.</para>
+<para>When the <structfield>priv</structfield> field isn't set to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> drivers must act as if all the
+extended fields were set to zero. On return drivers must set the
+<structfield>priv</structfield> field to
+<constant>V4L2_PIX_FMT_PRIV_MAGIC</constant> and all the extended fields to
+applicable values.</para></entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
</row>
</tbody>
</tgroup>
@@ -201,9 +226,15 @@ codes can be used.</entry>
and the number of valid entries in the
<structfield>plane_fmt</structfield> array.</entry>
</row>
+ <row>
+ <entry>__u8</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Flags set by the application or driver, see <xref
+linkend="format-flags" />.</entry>
+ </row>
<row>
<entry>__u8</entry>
- <entry><structfield>reserved[11]</structfield></entry>
+ <entry><structfield>reserved[10]</structfield></entry>
<entry>Reserved for future extensions. Should be zeroed by the
application.</entry>
</row>
@@ -248,7 +279,7 @@ has just as many pad bytes after it as the other rows.</para>
<para>In V4L2 each format has an identifier which looks like
<constant>PIX_FMT_XXX</constant>, defined in the <link
-linkend="videodev">videodev.h</link> header file. These identifiers
+linkend="videodev">videodev2.h</link> header file. These identifiers
represent <link linkend="v4l2-fourcc">four character (FourCC) codes</link>
which are also listed below, however they are not the same as those
used in the Windows world.</para>
@@ -828,6 +859,9 @@ interface only.</para>
&sub-sdr-cu08;
&sub-sdr-cu16le;
+ &sub-sdr-cs08;
+ &sub-sdr-cs14le;
+ &sub-sdr-ru12le;
</section>
@@ -1060,4 +1094,21 @@ concatenated to form the JPEG stream. </para>
</tbody>
</tgroup>
</table>
+
+ <table frame="none" pgwide="1" id="format-flags">
+ <title>Format Flags</title>
+ <tgroup cols="3">
+ &cs-def;
+ <tbody valign="top">
+ <row>
+ <entry><constant>V4L2_PIX_FMT_FLAG_PREMUL_ALPHA</constant></entry>
+ <entry>0x00000001</entry>
+ <entry>The color values are premultiplied by the alpha channel
+value. For example, if a light blue pixel with 50% transparency was described by
+RGBA values (128, 192, 255, 128), the same pixel described with premultiplied
+colors would be described by RGBA values (64, 96, 128, 128) </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
</section>
diff --git a/Documentation/DocBook/media/v4l/selection-api.xml b/Documentation/DocBook/media/v4l/selection-api.xml
index 4c238ce068b0..28cbded766c9 100644
--- a/Documentation/DocBook/media/v4l/selection-api.xml
+++ b/Documentation/DocBook/media/v4l/selection-api.xml
@@ -86,47 +86,47 @@ selection targets available for a video capture device. It is recommended to
configure the cropping targets before to the composing targets.</para>
<para>The range of coordinates of the top left corner, width and height of
-areas that can be sampled is given by the <constant> V4L2_SEL_TGT_CROP_BOUNDS
-</constant> target. It is recommended for the driver developers to put the
-top/left corner at position <constant> (0,0) </constant>. The rectangle's
+areas that can be sampled is given by the <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>
+target. It is recommended for the driver developers to put the
+top/left corner at position <constant>(0,0)</constant>. The rectangle's
coordinates are expressed in pixels.</para>
<para>The top left corner, width and height of the source rectangle, that is
-the area actually sampled, is given by the <constant> V4L2_SEL_TGT_CROP
-</constant> target. It uses the same coordinate system as <constant>
-V4L2_SEL_TGT_CROP_BOUNDS </constant>. The active cropping area must lie
-completely inside the capture boundaries. The driver may further adjust the
-requested size and/or position according to hardware limitations.</para>
+the area actually sampled, is given by the <constant>V4L2_SEL_TGT_CROP</constant>
+target. It uses the same coordinate system as <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
+The active cropping area must lie completely inside the capture boundaries. The
+driver may further adjust the requested size and/or position according to hardware
+limitations.</para>
<para>Each capture device has a default source rectangle, given by the
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant> target. This rectangle shall
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant> target. This rectangle shall
over what the driver writer considers the complete picture. Drivers shall set
the active crop rectangle to the default when the driver is first loaded, but
not later.</para>
<para>The composing targets refer to a memory buffer. The limits of composing
-coordinates are obtained using <constant> V4L2_SEL_TGT_COMPOSE_BOUNDS
-</constant>. All coordinates are expressed in pixels. The rectangle's top/left
-corner must be located at position <constant> (0,0) </constant>. The width and
-height are equal to the image size set by <constant> VIDIOC_S_FMT </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_COMPOSE_BOUNDS</constant>.
+All coordinates are expressed in pixels. The rectangle's top/left
+corner must be located at position <constant>(0,0)</constant>. The width and
+height are equal to the image size set by <constant>VIDIOC_S_FMT</constant>.
</para>
<para>The part of a buffer into which the image is inserted by the hardware is
-controlled by the <constant> V4L2_SEL_TGT_COMPOSE </constant> target.
+controlled by the <constant>V4L2_SEL_TGT_COMPOSE</constant> target.
The rectangle's coordinates are also expressed in the same coordinate system as
the bounds rectangle. The composing rectangle must lie completely inside bounds
rectangle. The driver must adjust the composing rectangle to fit to the
bounding limits. Moreover, the driver can perform other adjustments according
to hardware limitations. The application can control rounding behaviour using
-<link linkend="v4l2-selection-flags"> constraint flags </link>.</para>
+<link linkend="v4l2-selection-flags"> constraint flags</link>.</para>
<para>For capture devices the default composing rectangle is queried using
-<constant> V4L2_SEL_TGT_COMPOSE_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant>. It is usually equal to the
bounding rectangle.</para>
<para>The part of a buffer that is modified by the hardware is given by
-<constant> V4L2_SEL_TGT_COMPOSE_PADDED </constant>. It contains all pixels
-defined using <constant> V4L2_SEL_TGT_COMPOSE </constant> plus all
+<constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>. It contains all pixels
+defined using <constant>V4L2_SEL_TGT_COMPOSE</constant> plus all
padding data modified by hardware during insertion process. All pixels outside
this rectangle <emphasis>must not</emphasis> be changed by the hardware. The
content of pixels that lie inside the padded area but outside active area is
@@ -140,52 +140,51 @@ where the rubbish pixels are located and remove them if needed.</para>
<title>Configuration of video output</title>
<para>For output devices targets and ioctls are used similarly to the video
-capture case. The <emphasis> composing </emphasis> rectangle refers to the
+capture case. The <emphasis>composing</emphasis> rectangle refers to the
insertion of an image into a video signal. The cropping rectangles refer to a
memory buffer. It is recommended to configure the composing targets before to
the cropping targets.</para>
<para>The cropping targets refer to the memory buffer that contains an image to
be inserted into a video signal or graphical screen. The limits of cropping
-coordinates are obtained using <constant> V4L2_SEL_TGT_CROP_BOUNDS </constant>.
+coordinates are obtained using <constant>V4L2_SEL_TGT_CROP_BOUNDS</constant>.
All coordinates are expressed in pixels. The top/left corner is always point
-<constant> (0,0) </constant>. The width and height is equal to the image size
-specified using <constant> VIDIOC_S_FMT </constant> ioctl.</para>
+<constant>(0,0)</constant>. The width and height is equal to the image size
+specified using <constant>VIDIOC_S_FMT</constant> ioctl.</para>
<para>The top left corner, width and height of the source rectangle, that is
the area from which image date are processed by the hardware, is given by the
-<constant> V4L2_SEL_TGT_CROP </constant>. Its coordinates are expressed
+<constant>V4L2_SEL_TGT_CROP</constant>. Its coordinates are expressed
in in the same coordinate system as the bounds rectangle. The active cropping
area must lie completely inside the crop boundaries and the driver may further
adjust the requested size and/or position according to hardware
limitations.</para>
<para>For output devices the default cropping rectangle is queried using
-<constant> V4L2_SEL_TGT_CROP_DEFAULT </constant>. It is usually equal to the
+<constant>V4L2_SEL_TGT_CROP_DEFAULT</constant>. It is usually equal to the
bounding rectangle.</para>
<para>The part of a video signal or graphics display where the image is
-inserted by the hardware is controlled by <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target. The rectangle's coordinates
-are expressed in pixels. The composing rectangle must lie completely inside the
-bounds rectangle. The driver must adjust the area to fit to the bounding
-limits. Moreover, the driver can perform other adjustments according to
-hardware limitations. </para>
-
-<para>The device has a default composing rectangle, given by the <constant>
-V4L2_SEL_TGT_COMPOSE_DEFAULT </constant> target. This rectangle shall cover what
+inserted by the hardware is controlled by <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target. The rectangle's coordinates are expressed in pixels. The composing
+rectangle must lie completely inside the bounds rectangle. The driver must
+adjust the area to fit to the bounding limits. Moreover, the driver can
+perform other adjustments according to hardware limitations.</para>
+
+<para>The device has a default composing rectangle, given by the
+<constant>V4L2_SEL_TGT_COMPOSE_DEFAULT</constant> target. This rectangle shall cover what
the driver writer considers the complete picture. It is recommended for the
-driver developers to put the top/left corner at position <constant> (0,0)
-</constant>. Drivers shall set the active composing rectangle to the default
+driver developers to put the top/left corner at position <constant>(0,0)</constant>.
+Drivers shall set the active composing rectangle to the default
one when the driver is first loaded.</para>
<para>The devices may introduce additional content to video signal other than
an image from memory buffers. It includes borders around an image. However,
such a padded area is driver-dependent feature not covered by this document.
Driver developers are encouraged to keep padded rectangle equal to active one.
-The padded target is accessed by the <constant> V4L2_SEL_TGT_COMPOSE_PADDED
-</constant> identifier. It must contain all pixels from the <constant>
-V4L2_SEL_TGT_COMPOSE </constant> target.</para>
+The padded target is accessed by the <constant>V4L2_SEL_TGT_COMPOSE_PADDED</constant>
+identifier. It must contain all pixels from the <constant>V4L2_SEL_TGT_COMPOSE</constant>
+target.</para>
</section>
@@ -194,8 +193,8 @@ V4L2_SEL_TGT_COMPOSE </constant> target.</para>
<title>Scaling control</title>
<para>An application can detect if scaling is performed by comparing the width
-and the height of rectangles obtained using <constant> V4L2_SEL_TGT_CROP
-</constant> and <constant> V4L2_SEL_TGT_COMPOSE </constant> targets. If
+and the height of rectangles obtained using <constant>V4L2_SEL_TGT_CROP</constant>
+and <constant>V4L2_SEL_TGT_COMPOSE</constant> targets. If
these are not equal then the scaling is applied. The application can compute
the scaling ratios using these values.</para>
@@ -208,7 +207,7 @@ the scaling ratios using these values.</para>
<title>Comparison with old cropping API</title>
<para>The selection API was introduced to cope with deficiencies of previous
-<link linkend="crop"> API </link>, that was designed to control simple capture
+<link linkend="crop"> API</link>, that was designed to control simple capture
devices. Later the cropping API was adopted by video output drivers. The ioctls
are used to select a part of the display were the video signal is inserted. It
should be considered as an API abuse because the described operation is
@@ -220,7 +219,7 @@ part of an image by abusing V4L2 API. Cropping a smaller image from a larger
one is achieved by setting the field
&v4l2-pix-format;<structfield>::bytesperline</structfield>. Introducing an image offsets
could be done by modifying field &v4l2-buffer;<structfield>::m_userptr</structfield>
-before calling <constant> VIDIOC_QBUF </constant>. Those
+before calling <constant>VIDIOC_QBUF</constant>. Those
operations should be avoided because they are not portable (endianness), and do
not work for macroblock and Bayer formats and mmap buffers. The selection API
deals with configuration of buffer cropping/composing in a clear, intuitive and
@@ -229,7 +228,7 @@ and constraints flags are introduced. Finally, &v4l2-crop; and &v4l2-cropcap;
have no reserved fields. Therefore there is no way to extend their functionality.
The new &v4l2-selection; provides a lot of place for future
extensions. Driver developers are encouraged to implement only selection API.
-The former cropping API would be simulated using the new one. </para>
+The former cropping API would be simulated using the new one.</para>
</section>
@@ -238,9 +237,9 @@ The former cropping API would be simulated using the new one. </para>
<example>
<title>Resetting the cropping parameters</title>
- <para>(A video capture device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_CAPTURE </constant> for other devices; change target to
-<constant> V4L2_SEL_TGT_COMPOSE_* </constant> family to configure composing
+ <para>(A video capture device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant> for other devices; change target to
+<constant>V4L2_SEL_TGT_COMPOSE_*</constant> family to configure composing
area)</para>
<programlisting>
@@ -292,8 +291,8 @@ area)</para>
<example>
<title>Querying for scaling factors</title>
- <para>A video output device is assumed; change <constant>
-V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> for other devices</para>
+ <para>A video output device is assumed; change
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> for other devices</para>
<programlisting>
&v4l2-selection; compose = {
diff --git a/Documentation/DocBook/media/v4l/v4l2.xml b/Documentation/DocBook/media/v4l/v4l2.xml
index b445161b912c..f2f81f06a17b 100644
--- a/Documentation/DocBook/media/v4l/v4l2.xml
+++ b/Documentation/DocBook/media/v4l/v4l2.xml
@@ -152,6 +152,14 @@ structs, ioctls) must be noted in more detail in the history chapter
applications. -->
<revision>
+ <revnumber>3.16</revnumber>
+ <date>2014-05-27</date>
+ <authorinitials>lp</authorinitials>
+ <revremark>Extended &v4l2-pix-format;. Added format flags.
+ </revremark>
+ </revision>
+
+ <revision>
<revnumber>3.15</revnumber>
<date>2014-02-03</date>
<authorinitials>hv, ap</authorinitials>
diff --git a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
index 820f86e8744b..cb7732582f03 100644
--- a/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-dqevent.xml
@@ -94,6 +94,18 @@
</row>
<row>
<entry></entry>
+ <entry>&v4l2-event-motion-det;</entry>
+ <entry><structfield>motion_det</structfield></entry>
+ <entry>Event data for event V4L2_EVENT_MOTION_DET.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>&v4l2-event-src-change;</entry>
+ <entry><structfield>src_change</structfield></entry>
+ <entry>Event data for event V4L2_EVENT_SOURCE_CHANGE.</entry>
+ </row>
+ <row>
+ <entry></entry>
<entry>__u8</entry>
<entry><structfield>data</structfield>[64]</entry>
<entry>Event data. Defined by the event type. The union
@@ -258,6 +270,44 @@
</tgroup>
</table>
+ <table frame="none" pgwide="1" id="v4l2-event-motion-det">
+ <title>struct <structname>v4l2_event_motion_det</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>
+ Currently only one flag is available: if <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant>
+ is set, then the <structfield>frame_sequence</structfield> field is valid,
+ otherwise that field should be ignored.
+ </entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>frame_sequence</structfield></entry>
+ <entry>
+ The sequence number of the frame being received. Only valid if the
+ <constant>V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ</constant> flag was set.
+ </entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>region_mask</structfield></entry>
+ <entry>
+ The bitmask of the regions that reported motion. There is at least one
+ region. If this field is 0, then no motion was detected at all.
+ If there is no <constant>V4L2_CID_DETECT_MD_REGION_GRID</constant> control
+ (see <xref linkend="detect-controls" />) to assign a different region
+ to each cell in the motion detection grid, then that all cells
+ are automatically assigned to the default region 0.
+ </entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<table pgwide="1" frame="none" id="changes-flags">
<title>Changes</title>
<tgroup cols="3">
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
index e9f6735c0823..c5bdbfcc42b3 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-ext-ctrls.xml
@@ -72,23 +72,30 @@ initialize the <structfield>id</structfield>,
<structfield>size</structfield> and <structfield>reserved2</structfield> fields
of each &v4l2-ext-control; and call the
<constant>VIDIOC_G_EXT_CTRLS</constant> ioctl. String controls controls
-must also set the <structfield>string</structfield> field.</para>
+must also set the <structfield>string</structfield> field. Controls
+of compound types (<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set)
+must set the <structfield>ptr</structfield> field.</para>
<para>If the <structfield>size</structfield> is too small to
receive the control result (only relevant for pointer-type controls
like strings), then the driver will set <structfield>size</structfield>
to a valid value and return an &ENOSPC;. You should re-allocate the
-string memory to this new size and try again. It is possible that the
-same issue occurs again if the string has grown in the meantime. It is
+memory to this new size and try again. For the string type it is possible that
+the same issue occurs again if the string has grown in the meantime. It is
recommended to call &VIDIOC-QUERYCTRL; first and use
<structfield>maximum</structfield>+1 as the new <structfield>size</structfield>
value. It is guaranteed that that is sufficient memory.
</para>
+ <para>N-dimensional arrays are set and retrieved row-by-row. You cannot set a partial
+array, all elements have to be set or retrieved. The total size is calculated
+as <structfield>elems</structfield> * <structfield>elem_size</structfield>.
+These values can be obtained by calling &VIDIOC-QUERY-EXT-CTRL;.</para>
+
<para>To change the value of a set of controls applications
initialize the <structfield>id</structfield>, <structfield>size</structfield>,
<structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
call the <constant>VIDIOC_S_EXT_CTRLS</constant> ioctl. The controls
will only be set if <emphasis>all</emphasis> control values are
valid.</para>
@@ -96,7 +103,7 @@ valid.</para>
<para>To check if a set of controls have correct values applications
initialize the <structfield>id</structfield>, <structfield>size</structfield>,
<structfield>reserved2</structfield> and
-<structfield>value/string</structfield> fields of each &v4l2-ext-control; and
+<structfield>value/value64/string/ptr</structfield> fields of each &v4l2-ext-control; and
call the <constant>VIDIOC_TRY_EXT_CTRLS</constant> ioctl. It is up to
the driver whether wrong values are automatically adjusted to a valid
value or if an error is returned.</para>
@@ -158,19 +165,47 @@ applications must set the array to zero.</entry>
<entry></entry>
<entry>__s32</entry>
<entry><structfield>value</structfield></entry>
- <entry>New value or current value.</entry>
+ <entry>New value or current value. Valid if this control is not of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
</row>
<row>
<entry></entry>
<entry>__s64</entry>
<entry><structfield>value64</structfield></entry>
- <entry>New value or current value.</entry>
+ <entry>New value or current value. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_INTEGER64</constant> and
+<constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is not set.</entry>
</row>
<row>
<entry></entry>
<entry>char *</entry>
<entry><structfield>string</structfield></entry>
- <entry>A pointer to a string.</entry>
+ <entry>A pointer to a string. Valid if this control is of
+type <constant>V4L2_CTRL_TYPE_STRING</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__u8 *</entry>
+ <entry><structfield>p_u8</structfield></entry>
+ <entry>A pointer to a matrix control of unsigned 8-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U8</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>__u16 *</entry>
+ <entry><structfield>p_u16</structfield></entry>
+ <entry>A pointer to a matrix control of unsigned 16-bit values.
+Valid if this control is of type <constant>V4L2_CTRL_TYPE_U16</constant>.</entry>
+ </row>
+ <row>
+ <entry></entry>
+ <entry>void *</entry>
+ <entry><structfield>ptr</structfield></entry>
+ <entry>A pointer to a compound type which can be an N-dimensional array and/or a
+compound type (the control's type is >= <constant>V4L2_CTRL_COMPOUND_TYPES</constant>).
+Valid if <constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant> is set for this control.
+</entry>
</row>
</tbody>
</tgroup>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
index 7c63815e7afd..20460730b02c 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-fbuf.xml
@@ -152,13 +152,10 @@ a valid base address, so applications can find the corresponding Linux
framebuffer device (see <xref linkend="osd" />).</entry>
</row>
<row>
- <entry>&v4l2-pix-format;</entry>
+ <entry>struct</entry>
<entry><structfield>fmt</structfield></entry>
<entry></entry>
- <entry>Layout of the frame buffer. The
-<structname>v4l2_pix_format</structname> structure is defined in <xref
-linkend="pixfmt" />, for clarification the fields and acceptable values
- are listed below:</entry>
+ <entry>Layout of the frame buffer.</entry>
</row>
<row>
<entry></entry>
@@ -276,9 +273,8 @@ see <xref linkend="colorspaces" />.</entry>
<entry></entry>
<entry>__u32</entry>
<entry><structfield>priv</structfield></entry>
- <entry>Reserved for additional information about custom
-(driver defined) formats. When not used drivers and applications must
-set this field to zero.</entry>
+ <entry>Reserved. Drivers and applications must set this field to
+zero.</entry>
</row>
</tbody>
</tgroup>
diff --git a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
index b11ec75e21a1..9c04ac8661b1 100644
--- a/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-g-selection.xml
@@ -58,17 +58,16 @@
<para>The ioctls are used to query and configure selection rectangles.</para>
-<para> To query the cropping (composing) rectangle set &v4l2-selection;
+<para>To query the cropping (composing) rectangle set &v4l2-selection;
<structfield> type </structfield> field to the respective buffer type.
-Do not use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
+Do not use multiplanar buffers. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> field
-to <constant> V4L2_SEL_TGT_CROP </constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets. The <structfield>flags</structfield> and <structfield>reserved
+to <constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets. The <structfield>flags</structfield> and <structfield>reserved
</structfield> fields of &v4l2-selection; are ignored and they must be filled
with zeros. The driver fills the rest of the structure or
returns &EINVAL; if incorrect buffer type or target was used. If cropping
@@ -77,19 +76,18 @@ always equal to the bounds rectangle. Finally, the &v4l2-rect;
<structfield>r</structfield> rectangle is filled with the current cropping
(composing) coordinates. The coordinates are expressed in driver-dependent
units. The only exception are rectangles for images in raw formats, whose
-coordinates are always expressed in pixels. </para>
+coordinates are always expressed in pixels.</para>
-<para> To change the cropping (composing) rectangle set the &v4l2-selection;
+<para>To change the cropping (composing) rectangle set the &v4l2-selection;
<structfield>type</structfield> field to the respective buffer type. Do not
-use multiplanar buffers. Use <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE
-</constant> instead of <constant> V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE
-</constant>. Use <constant> V4L2_BUF_TYPE_VIDEO_OUTPUT </constant> instead of
-<constant> V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE </constant>. The next step is
+use multiplanar buffers. Use <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>
+instead of <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>. Use
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> instead of
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>. The next step is
setting the value of &v4l2-selection; <structfield>target</structfield> to
-<constant>V4L2_SEL_TGT_CROP</constant> (<constant>
-V4L2_SEL_TGT_COMPOSE </constant>). Please refer to table <xref
-linkend="v4l2-selections-common" /> or <xref linkend="selection-api" /> for additional
-targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
+<constant>V4L2_SEL_TGT_CROP</constant> (<constant>V4L2_SEL_TGT_COMPOSE</constant>).
+Please refer to table <xref linkend="v4l2-selections-common" /> or <xref linkend="selection-api" />
+for additional targets. The &v4l2-rect; <structfield>r</structfield> rectangle need to be
set to the desired active area. Field &v4l2-selection; <structfield> reserved
</structfield> is ignored and must be filled with zeros. The driver may adjust
coordinates of the requested rectangle. An application may
@@ -149,8 +147,8 @@ On success the &v4l2-rect; <structfield>r</structfield> field contains
the adjusted rectangle. When the parameters are unsuitable the application may
modify the cropping (composing) or image parameters and repeat the cycle until
satisfactory parameters have been negotiated. If constraints flags have to be
-violated at then ERANGE is returned. The error indicates that <emphasis> there
-exist no rectangle </emphasis> that satisfies the constraints.</para>
+violated at then ERANGE is returned. The error indicates that <emphasis>there
+exist no rectangle</emphasis> that satisfies the constraints.</para>
<para>Selection targets and flags are documented in <xref
linkend="v4l2-selections-common"/>.</para>
diff --git a/Documentation/DocBook/media/v4l/vidioc-querycap.xml b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
index 370d49d6fb64..d0c5e604f014 100644
--- a/Documentation/DocBook/media/v4l/vidioc-querycap.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-querycap.xml
@@ -302,6 +302,12 @@ modulator programming see
<link linkend="sdr">SDR Capture</link> interface.</entry>
</row>
<row>
+ <entry><constant>V4L2_CAP_EXT_PIX_FORMAT</constant></entry>
+ <entry>0x00200000</entry>
+ <entry>The device supports the &v4l2-pix-format; extended
+fields.</entry>
+ </row>
+ <row>
<entry><constant>V4L2_CAP_READWRITE</constant></entry>
<entry>0x01000000</entry>
<entry>The device supports the <link
diff --git a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
index e6645b996558..2bd98fd7a4e5 100644
--- a/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-queryctrl.xml
@@ -1,11 +1,12 @@
<refentry id="vidioc-queryctrl">
<refmeta>
- <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</refentrytitle>
+ <refentrytitle>ioctl VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</refentrytitle>
&manvol;
</refmeta>
<refnamediv>
<refname>VIDIOC_QUERYCTRL</refname>
+ <refname>VIDIOC_QUERY_EXT_CTRL</refname>
<refname>VIDIOC_QUERYMENU</refname>
<refpurpose>Enumerate controls and menu control items</refpurpose>
</refnamediv>
@@ -24,6 +25,14 @@
<funcdef>int <function>ioctl</function></funcdef>
<paramdef>int <parameter>fd</parameter></paramdef>
<paramdef>int <parameter>request</parameter></paramdef>
+ <paramdef>struct v4l2_query_ext_ctrl *<parameter>argp</parameter></paramdef>
+ </funcprototype>
+ </funcsynopsis>
+ <funcsynopsis>
+ <funcprototype>
+ <funcdef>int <function>ioctl</function></funcdef>
+ <paramdef>int <parameter>fd</parameter></paramdef>
+ <paramdef>int <parameter>request</parameter></paramdef>
<paramdef>struct v4l2_querymenu *<parameter>argp</parameter></paramdef>
</funcprototype>
</funcsynopsis>
@@ -42,7 +51,7 @@
<varlistentry>
<term><parameter>request</parameter></term>
<listitem>
- <para>VIDIOC_QUERYCTRL, VIDIOC_QUERYMENU</para>
+ <para>VIDIOC_QUERYCTRL, VIDIOC_QUERY_EXT_CTRL, VIDIOC_QUERYMENU</para>
</listitem>
</varlistentry>
<varlistentry>
@@ -67,7 +76,7 @@ structure. The driver fills the rest of the structure or returns an
<constant>VIDIOC_QUERYCTRL</constant> with successive
<structfield>id</structfield> values starting from
<constant>V4L2_CID_BASE</constant> up to and exclusive
-<constant>V4L2_CID_BASE_LASTP1</constant>. Drivers may return
+<constant>V4L2_CID_LASTP1</constant>. Drivers may return
<errorcode>EINVAL</errorcode> if a control in this range is not
supported. Further applications can enumerate private controls, which
are not defined in this specification, by starting at
@@ -89,9 +98,23 @@ prematurely end the enumeration).</para></footnote></para>
<para>When the application ORs <structfield>id</structfield> with
<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver returns the
-next supported control, or <errorcode>EINVAL</errorcode> if there is
-none. Drivers which do not support this flag yet always return
-<errorcode>EINVAL</errorcode>.</para>
+next supported non-compound control, or <errorcode>EINVAL</errorcode>
+if there is none. In addition, the <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant>
+flag can be specified to enumerate all compound controls (i.e. controls
+with type &ge; <constant>V4L2_CTRL_COMPOUND_TYPES</constant>). Specify both
+<constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> and
+<constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> in order to enumerate
+all controls, compound or not. Drivers which do not support these flags yet
+always return <errorcode>EINVAL</errorcode>.</para>
+
+ <para>The <constant>VIDIOC_QUERY_EXT_CTRL</constant> ioctl was
+introduced in order to better support controls that can use compound
+types, and to expose additional control information that cannot be
+returned in &v4l2-queryctrl; since that structure is full.</para>
+
+ <para><constant>VIDIOC_QUERY_EXT_CTRL</constant> is used in the
+same way as <constant>VIDIOC_QUERYCTRL</constant>, except that the
+<structfield>reserved</structfield> array must be zeroed as well.</para>
<para>Additional information is required for menu controls: the
names of the menu items. To query them applications set the
@@ -142,38 +165,23 @@ string. This information is intended for the user.</entry>
<entry>__s32</entry>
<entry><structfield>minimum</structfield></entry>
<entry>Minimum value, inclusive. This field gives a lower
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-lowest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant> controls.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the minimum value
-gives the minimum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
</row>
<row>
<entry>__s32</entry>
<entry><structfield>maximum</structfield></entry>
<entry>Maximum value, inclusive. This field gives an upper
-bound for <constant>V4L2_CTRL_TYPE_INTEGER</constant> controls and the
-highest valid index for <constant>V4L2_CTRL_TYPE_MENU</constant>
-controls. For <constant>V4L2_CTRL_TYPE_BITMASK</constant> controls it is the
-set of usable bits.
-For <constant>V4L2_CTRL_TYPE_STRING</constant> controls the maximum value
-gives the maximum length of the string. This length <emphasis>does not include the terminating
-zero</emphasis>. It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant> controls. Note that this is a
-signed value.</entry>
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 32-bit value.</entry>
</row>
<row>
<entry>__s32</entry>
<entry><structfield>step</structfield></entry>
- <entry><para>This field gives a step size for
-<constant>V4L2_CTRL_TYPE_INTEGER</constant> controls. For
-<constant>V4L2_CTRL_TYPE_STRING</constant> controls this field refers to
-the string length that has to be a multiple of this step size.
-It may not be valid for any other type of control, including
-<constant>V4L2_CTRL_TYPE_INTEGER64</constant>
-controls.</para><para>Generally drivers should not scale hardware
+ <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 32-bit value.
+</para><para>Generally drivers should not scale hardware
control values. It may be necessary for example when the
<structfield>name</structfield> or <structfield>id</structfield> imply
a particular unit and the hardware actually accepts only multiples of
@@ -192,10 +200,11 @@ be always positive.</para></entry>
<entry><structfield>default_value</structfield></entry>
<entry>The default value of a
<constant>V4L2_CTRL_TYPE_INTEGER</constant>,
-<constant>_BOOLEAN</constant> or <constant>_MENU</constant> control.
-Not valid for other types of controls. Drivers reset controls only
-when the driver is loaded, not later, in particular not when the
-func-open; is called.</entry>
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant> or <constant>_INTEGER_MENU</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.</entry>
</row>
<row>
<entry>__u32</entry>
@@ -213,6 +222,126 @@ the array to zero.</entry>
</tgroup>
</table>
+ <table pgwide="1" frame="none" id="v4l2-query-ext-ctrl">
+ <title>struct <structname>v4l2_query_ext_ctrl</structname></title>
+ <tgroup cols="3">
+ &cs-str;
+ <tbody valign="top">
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>id</structfield></entry>
+ <entry>Identifies the control, set by the application. See
+<xref linkend="control-id" /> for predefined IDs. When the ID is ORed
+with <constant>V4L2_CTRL_FLAG_NEXT_CTRL</constant> the driver clears the
+flag and returns the first non-compound control with a higher ID. When the
+ID is ORed with <constant>V4L2_CTRL_FLAG_NEXT_COMPOUND</constant> the driver
+clears the flag and returns the first compound control with a higher ID.
+Set both to get the first control (compound or not) with a higher ID.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>type</structfield></entry>
+ <entry>Type of control, see <xref
+ linkend="v4l2-ctrl-type" />.</entry>
+ </row>
+ <row>
+ <entry>char</entry>
+ <entry><structfield>name</structfield>[32]</entry>
+ <entry>Name of the control, a NUL-terminated ASCII
+string. This information is intended for the user.</entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>minimum</structfield></entry>
+ <entry>Minimum value, inclusive. This field gives a lower
+bound for the control. See &v4l2-ctrl-type; how the minimum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>maximum</structfield></entry>
+ <entry>Maximum value, inclusive. This field gives an upper
+bound for the control. See &v4l2-ctrl-type; how the maximum value is to
+be used for each possible control type. Note that this a signed 64-bit value.</entry>
+ </row>
+ <row>
+ <entry>__u64</entry>
+ <entry><structfield>step</structfield></entry>
+ <entry><para>This field gives a step size for the control.
+See &v4l2-ctrl-type; how the step value is to be used for each possible
+control type. Note that this an unsigned 64-bit value.
+</para><para>Generally drivers should not scale hardware
+control values. It may be necessary for example when the
+<structfield>name</structfield> or <structfield>id</structfield> imply
+a particular unit and the hardware actually accepts only multiples of
+said unit. If so, drivers must take care values are properly rounded
+when scaling, such that errors will not accumulate on repeated
+read-write cycles.</para><para>This field gives the smallest change of
+an integer control actually affecting hardware. Often the information
+is needed when the user can change controls by keyboard or GUI
+buttons, rather than a slider. When for example a hardware register
+accepts values 0-511 and the driver reports 0-65535, step should be
+128.</para></entry>
+ </row>
+ <row>
+ <entry>__s64</entry>
+ <entry><structfield>default_value</structfield></entry>
+ <entry>The default value of a
+<constant>V4L2_CTRL_TYPE_INTEGER</constant>, <constant>_INTEGER64</constant>,
+<constant>_BOOLEAN</constant>, <constant>_BITMASK</constant>,
+<constant>_MENU</constant>, <constant>_INTEGER_MENU</constant>,
+<constant>_U8</constant> or <constant>_U16</constant> control.
+Not valid for other types of controls.
+Note that drivers reset controls to their default value only when the
+driver is first loaded, never afterwards.
+</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>flags</structfield></entry>
+ <entry>Control flags, see <xref
+ linkend="control-flags" />.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>elem_size</structfield></entry>
+ <entry>The size in bytes of a single element of the array.
+Given a char pointer <constant>p</constant> to a 3-dimensional array you can find the
+position of cell <constant>(z, y, x)</constant> as follows:
+<constant>p + ((z * dims[1] + y) * dims[0] + x) * elem_size</constant>. <structfield>elem_size</structfield>
+is always valid, also when the control isn't an array. For string controls
+<structfield>elem_size</structfield> is equal to <structfield>maximum + 1</structfield>.
+</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>elems</structfield></entry>
+ <entry>The number of elements in the N-dimensional array. If this control
+is not an array, then <structfield>elems</structfield> is 1. The <structfield>elems</structfield>
+field can never be 0.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>nr_of_dims</structfield></entry>
+ <entry>The number of dimension in the N-dimensional array. If this control
+is not an array, then this field is 0.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>dims[V4L2_CTRL_MAX_DIMS]</structfield></entry>
+ <entry>The size of each dimension. The first <structfield>nr_of_dims</structfield>
+elements of this array must be non-zero, all remaining elements must be zero.</entry>
+ </row>
+ <row>
+ <entry>__u32</entry>
+ <entry><structfield>reserved</structfield>[32]</entry>
+ <entry>Reserved for future extensions. Applications and drivers
+must set the array to zero.</entry>
+ </row>
+ </tbody>
+ </tgroup>
+ </table>
+
<table pgwide="1" frame="none" id="v4l2-querymenu">
<title>struct <structname>v4l2_querymenu</structname></title>
<tgroup cols="4">
@@ -347,11 +476,14 @@ Drivers must ignore the value passed with
</row>
<row>
<entry><constant>V4L2_CTRL_TYPE_INTEGER64</constant></entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
- <entry>n/a</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
<entry>A 64-bit integer valued control. Minimum, maximum
-and step size cannot be queried.</entry>
+and step size cannot be queried using <constant>VIDIOC_QUERYCTRL</constant>.
+Only <constant>VIDIOC_QUERY_EXT_CTRL</constant> can retrieve the 64-bit
+min/max/step values, they should be interpreted as n/a when using
+<constant>VIDIOC_QUERYCTRL</constant>.</entry>
</row>
<row>
<entry><constant>V4L2_CTRL_TYPE_STRING</constant></entry>
@@ -379,6 +511,26 @@ ioctl returns the name of the control class and this control type.
Older drivers which do not support this feature return an
&EINVAL;.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_CTRL_TYPE_U8</constant></entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>An unsigned 8-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+ </row>
+ <row>
+ <entry><constant>V4L2_CTRL_TYPE_U16</constant></entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>any</entry>
+ <entry>An unsigned 16-bit valued control ranging from minimum to
+maximum inclusive. The step value indicates the increment between
+values which are actually different on the hardware.
+</entry>
+ </row>
</tbody>
</tgroup>
</table>
@@ -450,6 +602,14 @@ is in auto-gain mode. In such a case the hardware calculates the gain value base
the lighting conditions which can change over time. Note that setting a new value for
a volatile control will have no effect. The new value will just be ignored.</entry>
</row>
+ <row>
+ <entry><constant>V4L2_CTRL_FLAG_HAS_PAYLOAD</constant></entry>
+ <entry>0x0100</entry>
+ <entry>This control has a pointer type, so its value has to be accessed
+using one of the pointer fields of &v4l2-ext-control;. This flag is set for controls
+that are an array, string, or have a compound type. In all cases you have to set a
+pointer to memory containing the payload of the control.</entry>
+ </row>
</tbody>
</tgroup>
</table>
diff --git a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
index 17efa870d4d2..9f6095608837 100644
--- a/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
+++ b/Documentation/DocBook/media/v4l/vidioc-subscribe-event.xml
@@ -175,6 +175,14 @@
</entry>
</row>
<row>
+ <entry><constant>V4L2_EVENT_MOTION_DET</constant></entry>
+ <entry>5</entry>
+ <entry>
+ <para>Triggered whenever the motion detection state for one or more of the regions
+ changes. This event has a &v4l2-event-motion-det; associated with it.</para>
+ </entry>
+ </row>
+ <row>
<entry><constant>V4L2_EVENT_PRIVATE_START</constant></entry>
<entry>0x08000000</entry>
<entry>Base event number for driver-private events.</entry>
diff --git a/Documentation/devicetree/bindings/media/sunxi-ir.txt b/Documentation/devicetree/bindings/media/sunxi-ir.txt
new file mode 100644
index 000000000000..23dd5ad07b7c
--- /dev/null
+++ b/Documentation/devicetree/bindings/media/sunxi-ir.txt
@@ -0,0 +1,23 @@
+Device-Tree bindings for SUNXI IR controller found in sunXi SoC family
+
+Required properties:
+- compatible : should be "allwinner,sun4i-a10-ir";
+- clocks : list of clock specifiers, corresponding to
+ entries in clock-names property;
+- clock-names : should contain "apb" and "ir" entries;
+- interrupts : should contain IR IRQ number;
+- reg : should contain IO map address for IR.
+
+Optional properties:
+- linux,rc-map-name : Remote control map name.
+
+Example:
+
+ir0: ir@01c21800 {
+ compatible = "allwinner,sun4i-a10-ir";
+ clocks = <&apb0_gates 6>, <&ir0_clk>;
+ clock-names = "apb", "ir";
+ interrupts = <0 5 1>;
+ reg = <0x01C21800 0x40>;
+ linux,rc-map-name = "rc-rc6-mce";
+};
diff --git a/Documentation/video4linux/v4l2-controls.txt b/Documentation/video4linux/v4l2-controls.txt
index 06cf3ac83631..0f84ce8c9a7b 100644
--- a/Documentation/video4linux/v4l2-controls.txt
+++ b/Documentation/video4linux/v4l2-controls.txt
@@ -77,9 +77,9 @@ Basic usage for V4L2 and sub-device drivers
Where foo->v4l2_dev is of type struct v4l2_device.
- Finally, remove all control functions from your v4l2_ioctl_ops:
- vidioc_queryctrl, vidioc_querymenu, vidioc_g_ctrl, vidioc_s_ctrl,
- vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
+ Finally, remove all control functions from your v4l2_ioctl_ops (if any):
+ vidioc_queryctrl, vidioc_query_ext_ctrl, vidioc_querymenu, vidioc_g_ctrl,
+ vidioc_s_ctrl, vidioc_g_ext_ctrls, vidioc_try_ext_ctrls and vidioc_s_ext_ctrls.
Those are now no longer needed.
1.3.2) For sub-device drivers do this:
@@ -258,8 +258,8 @@ The new control value has already been validated, so all you need to do is
to actually update the hardware registers.
You're done! And this is sufficient for most of the drivers we have. No need
-to do any validation of control values, or implement QUERYCTRL/QUERYMENU. And
-G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
+to do any validation of control values, or implement QUERYCTRL, QUERY_EXT_CTRL
+and QUERYMENU. And G/S_CTRL as well as G/TRY/S_EXT_CTRLS are automatically supported.
==============================================================================
@@ -288,30 +288,45 @@ of v4l2_device.
Accessing Control Values
========================
-The v4l2_ctrl struct contains these two unions:
+The following union is used inside the control framework to access control
+values:
- /* The current control value. */
- union {
+union v4l2_ctrl_ptr {
+ s32 *p_s32;
+ s64 *p_s64;
+ char *p_char;
+ void *p;
+};
+
+The v4l2_ctrl struct contains these fields that can be used to access both
+current and new values:
+
+ s32 val;
+ struct {
s32 val;
- s64 val64;
- char *string;
} cur;
- /* The new control value. */
- union {
- s32 val;
- s64 val64;
- char *string;
- };
-Within the control ops you can freely use these. The val and val64 speak for
-themselves. The string pointers point to character buffers of length
+ union v4l2_ctrl_ptr p_new;
+ union v4l2_ctrl_ptr p_cur;
+
+If the control has a simple s32 type type, then:
+
+ &ctrl->val == ctrl->p_new.p_s32
+ &ctrl->cur.val == ctrl->p_cur.p_s32
+
+For all other types use ctrl->p_cur.p<something>. Basically the val
+and cur.val fields can be considered an alias since these are used so often.
+
+Within the control ops you can freely use these. The val and cur.val speak for
+themselves. The p_char pointers point to character buffers of length
ctrl->maximum + 1, and are always 0-terminated.
-In most cases 'cur' contains the current cached control value. When you create
-a new control this value is made identical to the default value. After calling
-v4l2_ctrl_handler_setup() this value is passed to the hardware. It is generally
-a good idea to call this function.
+Unless the control is marked volatile the p_cur field points to the the
+current cached control value. When you create a new control this value is made
+identical to the default value. After calling v4l2_ctrl_handler_setup() this
+value is passed to the hardware. It is generally a good idea to call this
+function.
Whenever a new value is set that new value is automatically cached. This means
that most drivers do not need to implement the g_volatile_ctrl() op. The
@@ -362,8 +377,8 @@ will result in a deadlock since these helpers lock the handler as well.
You can also take the handler lock yourself:
mutex_lock(&state->ctrl_handler.lock);
- printk(KERN_INFO "String value is '%s'\n", ctrl1->cur.string);
- printk(KERN_INFO "Integer value is '%s'\n", ctrl2->cur.val);
+ pr_info("String value is '%s'\n", ctrl1->p_cur.p_char);
+ pr_info("Integer value is '%s'\n", ctrl2->cur.val);
mutex_unlock(&state->ctrl_handler.lock);
diff --git a/Documentation/video4linux/v4l2-framework.txt b/Documentation/video4linux/v4l2-framework.txt
index 667a43361706..a11dff07ef71 100644
--- a/Documentation/video4linux/v4l2-framework.txt
+++ b/Documentation/video4linux/v4l2-framework.txt
@@ -675,11 +675,6 @@ You should also set these fields:
video_device is initialized you *do* know which parent PCI device to use and
so you set dev_device to the correct PCI device.
-- flags: optional. Set to V4L2_FL_USE_FH_PRIO if you want to let the framework
- handle the VIDIOC_G/S_PRIORITY ioctls. This requires that you use struct
- v4l2_fh. Eventually this flag will disappear once all drivers use the core
- priority handling. But for now it has to be set explicitly.
-
If you use v4l2_ioctl_ops, then you should set .unlocked_ioctl to video_ioctl2
in your v4l2_file_operations struct.
@@ -909,8 +904,7 @@ struct v4l2_fh
struct v4l2_fh provides a way to easily keep file handle specific data
that is used by the V4L2 framework. New drivers must use struct v4l2_fh
-since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY)
-if the video_device flag V4L2_FL_USE_FH_PRIO is also set.
+since it is also used to implement priority handling (VIDIOC_G/S_PRIORITY).
The users of v4l2_fh (in the V4L2 framework, not the driver) know
whether a driver uses v4l2_fh as its file->private_data pointer by
diff --git a/Documentation/video4linux/v4l2-pci-skeleton.c b/Documentation/video4linux/v4l2-pci-skeleton.c
index 46904fe49609..006721e43b2a 100644
--- a/Documentation/video4linux/v4l2-pci-skeleton.c
+++ b/Documentation/video4linux/v4l2-pci-skeleton.c
@@ -883,11 +883,6 @@ static int skeleton_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
vdev->v4l2_dev = &skel->v4l2_dev;
/* Supported SDTV standards, if any */
vdev->tvnorms = SKEL_TVNORMS;
- /* If this bit is set, then the v4l2 core will provide the support
- * for the VIDIOC_G/S_PRIORITY ioctls. This flag will eventually
- * go away once all drivers have been converted to use struct v4l2_fh.
- */
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(vdev, skel);
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
diff --git a/Documentation/zh_CN/video4linux/v4l2-framework.txt b/Documentation/zh_CN/video4linux/v4l2-framework.txt
index 0da95dbaef34..2b828e631e31 100644
--- a/Documentation/zh_CN/video4linux/v4l2-framework.txt
+++ b/Documentation/zh_CN/video4linux/v4l2-framework.txt
@@ -580,11 +580,6 @@ release()回调必须被设置,且在最后一个 video_device 用户退出之
v4l2_device 无法与特定的 PCI 设备关联,所有没有设置父设备。但当
video_device 配置后,就知道使用哪个父 PCI 设备了。
-- flags:可选。如果你要让框架处理设置 VIDIOC_G/S_PRIORITY ioctls,
- 请设置 V4L2_FL_USE_FH_PRIO。这要求你使用 v4l2_fh 结构体。
- 一旦所有驱动使用了核心的优先级处理,最终这个标志将消失。但现在它
- 必须被显式设置。
-
如果你使用 v4l2_ioctl_ops,则应该在 v4l2_file_operations 结构体中
设置 .unlocked_ioctl 指向 video_ioctl2。
@@ -789,7 +784,7 @@ v4l2_fh 结构体
-------------
v4l2_fh 结构体提供一个保存用于 V4L2 框架的文件句柄特定数据的简单方法。
-如果 video_device 的 flag 设置了 V4L2_FL_USE_FH_PRIO 标志,新驱动
+如果 video_device 标志,新驱动
必须使用 v4l2_fh 结构体,因为它也用于实现优先级处理(VIDIOC_G/S_PRIORITY)。
v4l2_fh 的用户(位于 V4l2 框架中,并非驱动)可通过测试
diff --git a/MAINTAINERS b/MAINTAINERS
index d76e07798e05..8982036ffa4f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -514,6 +514,16 @@ S: Supported
F: fs/aio.c
F: include/linux/*aio*.h
+AIRSPY MEDIA DRIVER
+M: Antti Palosaari <crope@iki.fi>
+L: linux-media@vger.kernel.org
+W: http://linuxtv.org/
+W: http://palosaari.fi/linux/
+Q: http://patchwork.linuxtv.org/project/linux-media/list/
+T: git git://linuxtv.org/anttip/media_tree.git
+S: Maintained
+F: drivers/media/usb/airspy/
+
ALCATEL SPEEDTOUCH USB DRIVER
M: Duncan Sands <duncan.sands@free.fr>
L: linux-usb@vger.kernel.org
@@ -5955,9 +5965,9 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/msi3101/msi001*
+F: drivers/media/tuners/msi001*
-MSI3101 MEDIA DRIVER
+MSI2500 MEDIA DRIVER
M: Antti Palosaari <crope@iki.fi>
L: linux-media@vger.kernel.org
W: http://linuxtv.org/
@@ -5965,7 +5975,7 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/msi3101/sdr-msi3101*
+F: drivers/media/usb/msi2500/
MT9M032 APTINA SENSOR DRIVER
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
@@ -6489,11 +6499,12 @@ L: linux-omap@vger.kernel.org
S: Maintained
F: arch/arm/mach-omap2/omap_hwmod_44xx_data.c
-OMAP IMAGE SIGNAL PROCESSOR (ISP)
+OMAP IMAGING SUBSYSTEM (OMAP3 ISP and OMAP4 ISS)
M: Laurent Pinchart <laurent.pinchart@ideasonboard.com>
L: linux-media@vger.kernel.org
S: Maintained
F: drivers/media/platform/omap3isp/
+F: drivers/staging/media/omap4iss/
OMAP USB SUPPORT
M: Felipe Balbi <balbi@ti.com>
@@ -7582,7 +7593,7 @@ W: http://palosaari.fi/linux/
Q: http://patchwork.linuxtv.org/project/linux-media/list/
T: git git://linuxtv.org/anttip/media_tree.git
S: Maintained
-F: drivers/staging/media/rtl2832u_sdr/rtl2832_sdr*
+F: drivers/media/dvb-frontends/rtl2832_sdr*
RTL8180 WIRELESS DRIVER
M: "John W. Linville" <linville@tuxdriver.com>
@@ -9525,15 +9536,6 @@ L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/usb/smsc95xx.*
-USB SN9C1xx DRIVER
-M: Luca Risolia <luca.risolia@studio.unibo.it>
-L: linux-usb@vger.kernel.org
-L: linux-media@vger.kernel.org
-T: git git://linuxtv.org/media_tree.git
-W: http://www.linux-projects.org
-S: Maintained
-F: drivers/staging/media/sn9c102/
-
USB SUBSYSTEM
M: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
L: linux-usb@vger.kernel.org
diff --git a/drivers/media/Kconfig b/drivers/media/Kconfig
index 1d0758aeb8e4..f60bad491eb6 100644
--- a/drivers/media/Kconfig
+++ b/drivers/media/Kconfig
@@ -59,6 +59,13 @@ config MEDIA_RADIO_SUPPORT
support radio reception. Disabling this option will
disable support for them.
+config MEDIA_SDR_SUPPORT
+ bool "Software defined radio support"
+ ---help---
+ Enable software defined radio support.
+
+ Say Y when you have a software defined radio device.
+
config MEDIA_RC_SUPPORT
bool "Remote Controller support"
depends on INPUT
@@ -95,7 +102,7 @@ config MEDIA_CONTROLLER
config VIDEO_DEV
tristate
depends on MEDIA_SUPPORT
- depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
+ depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT || MEDIA_SDR_SUPPORT
default y
config VIDEO_V4L2_SUBDEV_API
@@ -171,10 +178,11 @@ comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
config MEDIA_SUBDRV_AUTOSELECT
bool "Autoselect ancillary drivers (tuners, sensors, i2c, frontends)"
- depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT
+ depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_CAMERA_SUPPORT || MEDIA_SDR_SUPPORT
depends on HAS_IOMEM
select I2C
select I2C_MUX
+ select SPI
default y
help
By default, a media driver auto-selects all possible ancillary
diff --git a/drivers/media/common/saa7146/saa7146_fops.c b/drivers/media/common/saa7146/saa7146_fops.c
index eda01bc68ab2..d9e1d6395ed9 100644
--- a/drivers/media/common/saa7146/saa7146_fops.c
+++ b/drivers/media/common/saa7146/saa7146_fops.c
@@ -533,13 +533,12 @@ int saa7146_vv_init(struct saa7146_dev* dev, struct saa7146_ext_vv *ext_vv)
if (dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
saa7146_vbi_uops.init(dev,vv);
- fmt = &vv->ov_fb.fmt;
- fmt->width = vv->standard->h_max_out;
- fmt->height = vv->standard->v_max_out;
- fmt->pixelformat = V4L2_PIX_FMT_RGB565;
- fmt->bytesperline = 2 * fmt->width;
- fmt->sizeimage = fmt->bytesperline * fmt->height;
- fmt->colorspace = V4L2_COLORSPACE_SRGB;
+ vv->ov_fb.fmt.width = vv->standard->h_max_out;
+ vv->ov_fb.fmt.height = vv->standard->v_max_out;
+ vv->ov_fb.fmt.pixelformat = V4L2_PIX_FMT_RGB565;
+ vv->ov_fb.fmt.bytesperline = 2 * vv->ov_fb.fmt.width;
+ vv->ov_fb.fmt.sizeimage = vv->ov_fb.fmt.bytesperline * vv->ov_fb.fmt.height;
+ vv->ov_fb.fmt.colorspace = V4L2_COLORSPACE_SRGB;
fmt = &vv->video_fmt;
fmt->width = 384;
@@ -613,7 +612,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
vfd->lock = &dev->v4l2_lock;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->tvnorms = 0;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
for (i = 0; i < dev->ext_vv_data->num_stds; i++)
vfd->tvnorms |= dev->ext_vv_data->stds[i].id;
strlcpy(vfd->name, name, sizeof(vfd->name));
diff --git a/drivers/media/dvb-core/dvb-usb-ids.h b/drivers/media/dvb-core/dvb-usb-ids.h
index 11d2bea23b02..f8e31509f12e 100644
--- a/drivers/media/dvb-core/dvb-usb-ids.h
+++ b/drivers/media/dvb-core/dvb-usb-ids.h
@@ -244,6 +244,7 @@
#define USB_PID_TECHNOTREND_CONNECT_S2400 0x3006
#define USB_PID_TECHNOTREND_CONNECT_S2400_8KEEPROM 0x3009
#define USB_PID_TECHNOTREND_CONNECT_CT3650 0x300d
+#define USB_PID_TECHNOTREND_TVSTICK_CT2_4400 0x3014
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY 0x005a
#define USB_PID_TERRATEC_CINERGY_DT_XS_DIVERSITY_2 0x0081
#define USB_PID_TERRATEC_CINERGY_HT_USB_XE 0x0058
diff --git a/drivers/media/dvb-core/dvb_frontend.c b/drivers/media/dvb-core/dvb_frontend.c
index 6ce435ac866f..6cc2631d8f0e 100644
--- a/drivers/media/dvb-core/dvb_frontend.c
+++ b/drivers/media/dvb-core/dvb_frontend.c
@@ -2666,20 +2666,20 @@ void dvb_frontend_detach(struct dvb_frontend* fe)
if (fe->ops.release_sec) {
fe->ops.release_sec(fe);
- symbol_put_addr(fe->ops.release_sec);
+ dvb_detach(fe->ops.release_sec);
}
if (fe->ops.tuner_ops.release) {
fe->ops.tuner_ops.release(fe);
- symbol_put_addr(fe->ops.tuner_ops.release);
+ dvb_detach(fe->ops.tuner_ops.release);
}
if (fe->ops.analog_ops.release) {
fe->ops.analog_ops.release(fe);
- symbol_put_addr(fe->ops.analog_ops.release);
+ dvb_detach(fe->ops.analog_ops.release);
}
ptr = (void*)fe->ops.release;
if (ptr) {
fe->ops.release(fe);
- symbol_put_addr(ptr);
+ dvb_detach(ptr);
}
}
#else
diff --git a/drivers/media/dvb-core/dvbdev.h b/drivers/media/dvb-core/dvbdev.h
index 93a9470d3f0c..f96b28e7fc95 100644
--- a/drivers/media/dvb-core/dvbdev.h
+++ b/drivers/media/dvb-core/dvbdev.h
@@ -136,11 +136,15 @@ extern int dvb_usercopy(struct file *file, unsigned int cmd, unsigned long arg,
__r; \
})
+#define dvb_detach(FUNC) symbol_put_addr(FUNC)
+
#else
#define dvb_attach(FUNCTION, ARGS...) ({ \
FUNCTION(ARGS); \
})
+#define dvb_detach(FUNC) {}
+
#endif
#endif /* #ifndef _DVBDEV_H_ */
diff --git a/drivers/media/dvb-frontends/Kconfig b/drivers/media/dvb-frontends/Kconfig
index 1469d44acb22..78a95a682553 100644
--- a/drivers/media/dvb-frontends/Kconfig
+++ b/drivers/media/dvb-frontends/Kconfig
@@ -446,6 +446,15 @@ config DVB_RTL2832
help
Say Y when you want to support this frontend.
+config DVB_RTL2832_SDR
+ tristate "Realtek RTL2832 SDR"
+ depends on DVB_CORE && I2C && I2C_MUX && VIDEO_V4L2 && MEDIA_SDR_SUPPORT
+ select DVB_RTL2832
+ select VIDEOBUF2_VMALLOC
+ default m if !MEDIA_SUBDRV_AUTOSELECT
+ help
+ Say Y when you want to support this SDR module.
+
config DVB_SI2168
tristate "Silicon Labs Si2168"
depends on DVB_CORE && I2C && I2C_MUX
diff --git a/drivers/media/dvb-frontends/Makefile b/drivers/media/dvb-frontends/Makefile
index dda0bee36f29..655e3c8ac173 100644
--- a/drivers/media/dvb-frontends/Makefile
+++ b/drivers/media/dvb-frontends/Makefile
@@ -5,6 +5,11 @@
ccflags-y += -I$(srctree)/drivers/media/dvb-core/
ccflags-y += -I$(srctree)/drivers/media/tuners/
+# FIXME: RTL2832 SDR driver uses power management directly from USB IF driver
+ifdef CONFIG_DVB_RTL2832_SDR
+ ccflags-y += -I$(srctree)/drivers/media/usb/dvb-usb-v2
+endif
+
stb0899-objs := stb0899_drv.o stb0899_algo.o
stv0900-objs := stv0900_core.o stv0900_sw.o
drxd-objs := drxd_firm.o drxd_hard.o
@@ -104,6 +109,7 @@ obj-$(CONFIG_DVB_A8293) += a8293.o
obj-$(CONFIG_DVB_TDA10071) += tda10071.o
obj-$(CONFIG_DVB_RTL2830) += rtl2830.o
obj-$(CONFIG_DVB_RTL2832) += rtl2832.o
+obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
obj-$(CONFIG_DVB_M88RS2000) += m88rs2000.o
obj-$(CONFIG_DVB_AF9033) += af9033.o
diff --git a/drivers/media/dvb-frontends/au8522_decoder.c b/drivers/media/dvb-frontends/au8522_decoder.c
index 23a0d05ba426..33aa9410b624 100644
--- a/drivers/media/dvb-frontends/au8522_decoder.c
+++ b/drivers/media/dvb-frontends/au8522_decoder.c
@@ -220,7 +220,7 @@ static void setup_vbi(struct au8522_state *state, int aud_input)
}
-static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
+static void setup_decoder_defaults(struct au8522_state *state, bool is_svideo)
{
int i;
int filter_coef_type;
@@ -237,13 +237,10 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
/* Other decoder registers */
au8522_writereg(state, AU8522_TVDEC_INT_MASK_REG010H, 0x00);
- if (input_mode == 0x23) {
- /* S-Video input mapping */
+ if (is_svideo)
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x04);
- } else {
- /* All other modes (CVBS/ATVRF etc.) */
+ else
au8522_writereg(state, AU8522_VIDEO_MODE_REG011H, 0x00);
- }
au8522_writereg(state, AU8522_TVDEC_PGA_REG012H,
AU8522_TVDEC_PGA_REG012H_CVBS);
@@ -251,12 +248,23 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_MODE_REG015H_CVBS);
au8522_writereg(state, AU8522_TVDED_DBG_MODE_REG060H,
AU8522_TVDED_DBG_MODE_REG060H_CVBS);
- au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
- AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
- au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
- AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+
+ if (state->std == V4L2_STD_PAL_M) {
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO);
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+ AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M);
+ } else {
+ /* NTSC */
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL1_REG061H,
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492 |
+ AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN);
+ au8522_writereg(state, AU8522_TVDEC_FORMAT_CTRL2_REG062H,
+ AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC);
+ }
au8522_writereg(state, AU8522_TVDEC_VCR_DET_LLIM_REG063H,
AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS);
au8522_writereg(state, AU8522_TVDEC_VCR_DET_HLIM_REG064H,
@@ -275,8 +283,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
AU8522_TVDEC_COMB_HDIF_THR2_REG06AH_CVBS);
au8522_writereg(state, AU8522_TVDEC_COMB_HDIF_THR3_REG06BH,
AU8522_TVDEC_COMB_HDIF_THR3_REG06BH_CVBS);
- if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
- input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+ if (is_svideo) {
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH,
AU8522_TVDEC_COMB_DCDIF_THR1_REG06CH_SVIDEO);
au8522_writereg(state, AU8522_TVDEC_COMB_DCDIF_THR2_REG06DH,
@@ -317,8 +324,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
setup_vbi(state, 0);
- if (input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13 ||
- input_mode == AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24) {
+ if (is_svideo) {
/* Despite what the table says, for the HVR-950q we still need
to be in CVBS mode for the S-Video input (reason unknown). */
/* filter_coef_type = 3; */
@@ -346,7 +352,7 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
au8522_writereg(state, AU8522_REG436H, 0x3c);
}
-static void au8522_setup_cvbs_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_mode(struct au8522_state *state, u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -358,16 +364,16 @@ static void au8522_setup_cvbs_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
- setup_decoder_defaults(state, AU8522_INPUT_CONTROL_REG081H_CVBS_CH1);
+ setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
-static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
+static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state,
+ u8 input_mode)
{
/* here we're going to try the pre-programmed route */
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
@@ -384,24 +390,22 @@ static void au8522_setup_cvbs_tuner_mode(struct au8522_state *state)
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x10);
/* Set input mode to CVBS on channel 4 with SIF audio input enabled */
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
- setup_decoder_defaults(state,
- AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF);
+ setup_decoder_defaults(state, false);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
}
-static void au8522_setup_svideo_mode(struct au8522_state *state)
+static void au8522_setup_svideo_mode(struct au8522_state *state,
+ u8 input_mode)
{
au8522_writereg(state, AU8522_MODULE_CLOCK_CONTROL_REG0A3H,
AU8522_MODULE_CLOCK_CONTROL_REG0A3H_SVIDEO);
/* Set input to Y on Channe1, C on Channel 3 */
- au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H,
- AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+ au8522_writereg(state, AU8522_INPUT_CONTROL_REG081H, input_mode);
/* PGA in automatic mode */
au8522_writereg(state, AU8522_PGA_CONTROL_REG082H, 0x00);
@@ -409,8 +413,7 @@ static void au8522_setup_svideo_mode(struct au8522_state *state)
/* Enable clamping control */
au8522_writereg(state, AU8522_CLAMPING_CONTROL_REG083H, 0x00);
- setup_decoder_defaults(state,
- AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13);
+ setup_decoder_defaults(state, true);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
@@ -432,8 +435,9 @@ static void disable_audio_input(struct au8522_state *state)
}
/* 0=disable, 1=SIF */
-static void set_audio_input(struct au8522_state *state, int aud_input)
+static void set_audio_input(struct au8522_state *state)
{
+ int aud_input = state->aud_input;
int i;
/* Note that this function needs to be used in conjunction with setting
@@ -465,8 +469,9 @@ static void set_audio_input(struct au8522_state *state, int aud_input)
au8522_writereg(state, AU8522_I2C_CONTROL_REG0_REG090H, 0x84);
msleep(150);
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x00);
- msleep(1);
- au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H, 0x9d);
+ msleep(10);
+ au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
+ AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
msleep(50);
au8522_writereg(state, AU8522_AUDIO_VOLUME_L_REG0F2H, 0x7F);
au8522_writereg(state, AU8522_AUDIO_VOLUME_R_REG0F3H, 0x7F);
@@ -539,58 +544,109 @@ static int au8522_s_register(struct v4l2_subdev *sd,
}
#endif
+static void au8522_video_set(struct au8522_state *state)
+{
+ u8 input_mode;
+
+ au8522_writereg(state, 0xa4, 1 << 5);
+
+ switch (state->vid_input) {
+ case AU8522_COMPOSITE_CH1:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH1;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH2:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH2;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH3:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH3;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_COMPOSITE_CH4:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4;
+ au8522_setup_cvbs_mode(state, input_mode);
+ break;
+ case AU8522_SVIDEO_CH13:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH13;
+ au8522_setup_svideo_mode(state, input_mode);
+ break;
+ case AU8522_SVIDEO_CH24:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_SVIDEO_CH24;
+ au8522_setup_svideo_mode(state, input_mode);
+ break;
+ default:
+ case AU8522_COMPOSITE_CH4_SIF:
+ input_mode = AU8522_INPUT_CONTROL_REG081H_CVBS_CH4_SIF;
+ au8522_setup_cvbs_tuner_mode(state, input_mode);
+ break;
+ }
+}
+
static int au8522_s_stream(struct v4l2_subdev *sd, int enable)
{
struct au8522_state *state = to_state(sd);
if (enable) {
+ /*
+ * Clear out any state associated with the digital side of the
+ * chip, so that when it gets powered back up it won't think
+ * that it is already tuned
+ */
+ state->current_frequency = 0;
+
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
0x01);
- msleep(1);
- au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
- AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H_CVBS);
+ msleep(10);
+
+ au8522_video_set(state);
+ set_audio_input(state);
+
+ state->operational_mode = AU8522_ANALOG_MODE;
} else {
/* This does not completely power down the device
(it only reduces it from around 140ma to 80ma) */
au8522_writereg(state, AU8522_SYSTEM_MODULE_CONTROL_0_REG0A4H,
1 << 5);
+ state->operational_mode = AU8522_SUSPEND_MODE;
}
return 0;
}
-static int au8522_reset(struct v4l2_subdev *sd, u32 val)
+static int au8522_s_video_routing(struct v4l2_subdev *sd,
+ u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
- state->operational_mode = AU8522_ANALOG_MODE;
-
- /* Clear out any state associated with the digital side of the
- chip, so that when it gets powered back up it won't think
- that it is already tuned */
- state->current_frequency = 0;
+ switch(input) {
+ case AU8522_COMPOSITE_CH1:
+ case AU8522_SVIDEO_CH13:
+ case AU8522_COMPOSITE_CH4_SIF:
+ state->vid_input = input;
+ break;
+ default:
+ printk(KERN_ERR "au8522 mode not currently supported\n");
+ return -EINVAL;
+ }
- au8522_writereg(state, 0xa4, 1 << 5);
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ au8522_video_set(state);
return 0;
}
-static int au8522_s_video_routing(struct v4l2_subdev *sd,
- u32 input, u32 output, u32 config)
+static int au8522_s_std(struct v4l2_subdev *sd, v4l2_std_id std)
{
struct au8522_state *state = to_state(sd);
- au8522_reset(sd, 0);
-
- if (input == AU8522_COMPOSITE_CH1) {
- au8522_setup_cvbs_mode(state);
- } else if (input == AU8522_SVIDEO_CH13) {
- au8522_setup_svideo_mode(state);
- } else if (input == AU8522_COMPOSITE_CH4_SIF) {
- au8522_setup_cvbs_tuner_mode(state);
- } else {
- printk(KERN_ERR "au8522 mode not currently supported\n");
+ if ((std & (V4L2_STD_PAL_M | V4L2_STD_NTSC_M)) == 0)
return -EINVAL;
- }
+
+ state->std = std;
+
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ au8522_video_set(state);
+
return 0;
}
@@ -598,7 +654,12 @@ static int au8522_s_audio_routing(struct v4l2_subdev *sd,
u32 input, u32 output, u32 config)
{
struct au8522_state *state = to_state(sd);
- set_audio_input(state, input);
+
+ state->aud_input = input;
+
+ if (state->operational_mode == AU8522_ANALOG_MODE)
+ set_audio_input(state);
+
return 0;
}
@@ -629,7 +690,6 @@ static int au8522_g_tuner(struct v4l2_subdev *sd, struct v4l2_tuner *vt)
static const struct v4l2_subdev_core_ops au8522_core_ops = {
.log_status = v4l2_ctrl_subdev_log_status,
- .reset = au8522_reset,
#ifdef CONFIG_VIDEO_ADV_DEBUG
.g_register = au8522_g_register,
.s_register = au8522_s_register,
@@ -647,6 +707,7 @@ static const struct v4l2_subdev_audio_ops au8522_audio_ops = {
static const struct v4l2_subdev_video_ops au8522_video_ops = {
.s_routing = au8522_s_video_routing,
.s_stream = au8522_s_stream,
+ .s_std = au8522_s_std,
};
static const struct v4l2_subdev_ops au8522_ops = {
@@ -729,6 +790,7 @@ static int au8522_probe(struct i2c_client *client,
}
state->c = client;
+ state->std = V4L2_STD_NTSC_M;
state->vid_input = AU8522_COMPOSITE_CH1;
state->aud_input = AU8522_AUDIO_NONE;
state->id = 8522;
diff --git a/drivers/media/dvb-frontends/au8522_priv.h b/drivers/media/dvb-frontends/au8522_priv.h
index aa0f16d6b610..b8aca1c84786 100644
--- a/drivers/media/dvb-frontends/au8522_priv.h
+++ b/drivers/media/dvb-frontends/au8522_priv.h
@@ -37,6 +37,7 @@
#define AU8522_ANALOG_MODE 0
#define AU8522_DIGITAL_MODE 1
+#define AU8522_SUSPEND_MODE 2
struct au8522_state {
struct i2c_client *c;
@@ -347,6 +348,7 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
/* Format control 2 */
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT 0x00
#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC 0x01
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_PAL_M 0x02
#define AU8522_INPUT_CONTROL_REG081H_ATSC 0xC4
diff --git a/drivers/media/dvb-frontends/dib0090.c b/drivers/media/dvb-frontends/dib0090.c
index 3ee22ff76315..68e2af2650d3 100644
--- a/drivers/media/dvb-frontends/dib0090.c
+++ b/drivers/media/dvb-frontends/dib0090.c
@@ -2557,10 +2557,19 @@ static int dib0090_set_params(struct dvb_frontend *fe)
do {
ret = dib0090_tune(fe);
- if (ret != FE_CALLBACK_TIME_NEVER)
- msleep(ret / 10);
- else
+ if (ret == FE_CALLBACK_TIME_NEVER)
break;
+
+ /*
+ * Despite dib0090_tune returns time at a 0.1 ms range,
+ * the actual sleep time depends on CONFIG_HZ. The worse case
+ * is when CONFIG_HZ=100. In such case, the minimum granularity
+ * is 10ms. On some real field tests, the tuner sometimes don't
+ * lock when this timer is lower than 10ms. So, enforce a 10ms
+ * granularity and use usleep_range() instead of msleep().
+ */
+ ret = 10 * (ret + 99)/100;
+ usleep_range(ret * 1000, (ret + 1) * 1000);
} while (state->tune_state != CT_TUNER_STOP);
return 0;
diff --git a/drivers/media/dvb-frontends/dib7000p.c b/drivers/media/dvb-frontends/dib7000p.c
index effb87f773b0..661760d60232 100644
--- a/drivers/media/dvb-frontends/dib7000p.c
+++ b/drivers/media/dvb-frontends/dib7000p.c
@@ -11,6 +11,7 @@
#include <linux/slab.h>
#include <linux/i2c.h>
#include <linux/mutex.h>
+#include <asm/div64.h>
#include "dvb_math.h"
#include "dvb_frontend.h"
@@ -72,6 +73,12 @@ struct dib7000p_state {
struct mutex i2c_buffer_lock;
u8 input_mode_mpeg;
+
+ /* for DVBv5 stats */
+ s64 old_ucb;
+ unsigned long per_jiffies_stats;
+ unsigned long ber_jiffies_stats;
+ unsigned long get_stats_time;
};
enum dib7000p_power_mode {
@@ -401,7 +408,7 @@ static int dib7000p_sad_calib(struct dib7000p_state *state)
return 0;
}
-int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
+static int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
{
struct dib7000p_state *state = demod->demodulator_priv;
if (value > 4095)
@@ -409,9 +416,8 @@ int dib7000p_set_wbd_ref(struct dvb_frontend *demod, u16 value)
state->wbd_ref = value;
return dib7000p_write_word(state, 105, (dib7000p_read_word(state, 105) & 0xf000) | value);
}
-EXPORT_SYMBOL(dib7000p_set_wbd_ref);
-int dib7000p_get_agc_values(struct dvb_frontend *fe,
+static int dib7000p_get_agc_values(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
{
struct dib7000p_state *state = fe->demodulator_priv;
@@ -427,14 +433,12 @@ int dib7000p_get_agc_values(struct dvb_frontend *fe,
return 0;
}
-EXPORT_SYMBOL(dib7000p_get_agc_values);
-int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
+static int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
{
struct dib7000p_state *state = fe->demodulator_priv;
return dib7000p_write_word(state, 108, v);
}
-EXPORT_SYMBOL(dib7000p_set_agc1_min);
static void dib7000p_reset_pll(struct dib7000p_state *state)
{
@@ -478,7 +482,7 @@ static u32 dib7000p_get_internal_freq(struct dib7000p_state *state)
return internal;
}
-int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
+static int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg_1857, reg_1856 = dib7000p_read_word(state, 1856);
@@ -513,7 +517,6 @@ int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config
}
return -EIO;
}
-EXPORT_SYMBOL(dib7000p_update_pll);
static int dib7000p_reset_gpio(struct dib7000p_state *st)
{
@@ -546,12 +549,11 @@ static int dib7000p_cfg_gpio(struct dib7000p_state *st, u8 num, u8 dir, u8 val)
return 0;
}
-int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
+static int dib7000p_set_gpio(struct dvb_frontend *demod, u8 num, u8 dir, u8 val)
{
struct dib7000p_state *state = demod->demodulator_priv;
return dib7000p_cfg_gpio(state, num, dir, val);
}
-EXPORT_SYMBOL(dib7000p_set_gpio);
static u16 dib7000p_defaults[] = {
// auto search configuration
@@ -636,6 +638,8 @@ static u16 dib7000p_defaults[] = {
0,
};
+static void dib7000p_reset_stats(struct dvb_frontend *fe);
+
static int dib7000p_demod_reset(struct dib7000p_state *state)
{
dib7000p_set_power_mode(state, DIB7000P_POWER_ALL);
@@ -934,7 +938,7 @@ static void dib7000p_update_timf(struct dib7000p_state *state)
}
-u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
+static u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
{
struct dib7000p_state *state = fe->demodulator_priv;
switch (op) {
@@ -950,7 +954,6 @@ u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
dib7000p_set_bandwidth(state, state->current_bandwidth);
return state->timf;
}
-EXPORT_SYMBOL(dib7000p_ctrl_timf);
static void dib7000p_set_channel(struct dib7000p_state *state,
struct dtv_frontend_properties *ch, u8 seq)
@@ -1360,6 +1363,9 @@ static int dib7000p_tune(struct dvb_frontend *demod)
dib7000p_spur_protect(state, ch->frequency / 1000, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
dib7000p_set_bandwidth(state, BANDWIDTH_TO_KHZ(ch->bandwidth_hz));
+
+ dib7000p_reset_stats(demod);
+
return 0;
}
@@ -1552,6 +1558,8 @@ static int dib7000p_set_frontend(struct dvb_frontend *fe)
return ret;
}
+static int dib7000p_get_stats(struct dvb_frontend *fe, fe_status_t stat);
+
static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
{
struct dib7000p_state *state = fe->demodulator_priv;
@@ -1570,6 +1578,8 @@ static int dib7000p_read_status(struct dvb_frontend *fe, fe_status_t * stat)
if ((lock & 0x0038) == 0x38)
*stat |= FE_HAS_LOCK;
+ dib7000p_get_stats(fe, *stat);
+
return 0;
}
@@ -1595,7 +1605,7 @@ static int dib7000p_read_signal_strength(struct dvb_frontend *fe, u16 * strength
return 0;
}
-static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
+static u32 dib7000p_get_snr(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val;
@@ -1625,10 +1635,351 @@ static int dib7000p_read_snr(struct dvb_frontend *fe, u16 * snr)
else
result -= intlog10(2) * 10 * noise_exp - 100;
+ return result;
+}
+
+static int dib7000p_read_snr(struct dvb_frontend *fe, u16 *snr)
+{
+ u32 result;
+
+ result = dib7000p_get_snr(fe);
+
*snr = result / ((1 << 24) / 10);
return 0;
}
+static void dib7000p_reset_stats(struct dvb_frontend *demod)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ u32 ucb;
+
+ memset(&c->strength, 0, sizeof(c->strength));
+ memset(&c->cnr, 0, sizeof(c->cnr));
+ memset(&c->post_bit_error, 0, sizeof(c->post_bit_error));
+ memset(&c->post_bit_count, 0, sizeof(c->post_bit_count));
+ memset(&c->block_error, 0, sizeof(c->block_error));
+
+ c->strength.len = 1;
+ c->cnr.len = 1;
+ c->block_error.len = 1;
+ c->block_count.len = 1;
+ c->post_bit_error.len = 1;
+ c->post_bit_count.len = 1;
+
+ c->strength.stat[0].scale = FE_SCALE_DECIBEL;
+ c->strength.stat[0].uvalue = 0;
+
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+
+ dib7000p_read_unc_blocks(demod, &ucb);
+
+ state->old_ucb = ucb;
+ state->ber_jiffies_stats = 0;
+ state->per_jiffies_stats = 0;
+}
+
+struct linear_segments {
+ unsigned x;
+ signed y;
+};
+
+/*
+ * Table to estimate signal strength in dBm.
+ * This table should be empirically determinated by measuring the signal
+ * strength generated by a RF generator directly connected into
+ * a device.
+ * This table was determinated by measuring the signal strength generated
+ * by a DTA-2111 RF generator directly connected into a dib7000p device
+ * (a Hauppauge Nova-TD stick), using a good quality 3 meters length
+ * RC6 cable and good RC6 connectors, connected directly to antenna 1.
+ * As the minimum output power of DTA-2111 is -31dBm, a 16 dBm attenuator
+ * were used, for the lower power values.
+ * The real value can actually be on other devices, or even at the
+ * second antena input, depending on several factors, like if LNA
+ * is enabled or not, if diversity is enabled, type of connectors, etc.
+ * Yet, it is better to use this measure in dB than a random non-linear
+ * percentage value, especially for antenna adjustments.
+ * On my tests, the precision of the measure using this table is about
+ * 0.5 dB, with sounds reasonable enough to adjust antennas.
+ */
+#define DB_OFFSET 131000
+
+static struct linear_segments strength_to_db_table[] = {
+ { 63630, DB_OFFSET - 20500},
+ { 62273, DB_OFFSET - 21000},
+ { 60162, DB_OFFSET - 22000},
+ { 58730, DB_OFFSET - 23000},
+ { 58294, DB_OFFSET - 24000},
+ { 57778, DB_OFFSET - 25000},
+ { 57320, DB_OFFSET - 26000},
+ { 56779, DB_OFFSET - 27000},
+ { 56293, DB_OFFSET - 28000},
+ { 55724, DB_OFFSET - 29000},
+ { 55145, DB_OFFSET - 30000},
+ { 54680, DB_OFFSET - 31000},
+ { 54293, DB_OFFSET - 32000},
+ { 53813, DB_OFFSET - 33000},
+ { 53427, DB_OFFSET - 34000},
+ { 52981, DB_OFFSET - 35000},
+
+ { 52636, DB_OFFSET - 36000},
+ { 52014, DB_OFFSET - 37000},
+ { 51674, DB_OFFSET - 38000},
+ { 50692, DB_OFFSET - 39000},
+ { 49824, DB_OFFSET - 40000},
+ { 49052, DB_OFFSET - 41000},
+ { 48436, DB_OFFSET - 42000},
+ { 47836, DB_OFFSET - 43000},
+ { 47368, DB_OFFSET - 44000},
+ { 46468, DB_OFFSET - 45000},
+ { 45597, DB_OFFSET - 46000},
+ { 44586, DB_OFFSET - 47000},
+ { 43667, DB_OFFSET - 48000},
+ { 42673, DB_OFFSET - 49000},
+ { 41816, DB_OFFSET - 50000},
+ { 40876, DB_OFFSET - 51000},
+ { 0, 0},
+};
+
+static u32 interpolate_value(u32 value, struct linear_segments *segments,
+ unsigned len)
+{
+ u64 tmp64;
+ u32 dx;
+ s32 dy;
+ int i, ret;
+
+ if (value >= segments[0].x)
+ return segments[0].y;
+ if (value < segments[len-1].x)
+ return segments[len-1].y;
+
+ for (i = 1; i < len - 1; i++) {
+ /* If value is identical, no need to interpolate */
+ if (value == segments[i].x)
+ return segments[i].y;
+ if (value > segments[i].x)
+ break;
+ }
+
+ /* Linear interpolation between the two (x,y) points */
+ dy = segments[i - 1].y - segments[i].y;
+ dx = segments[i - 1].x - segments[i].x;
+
+ tmp64 = value - segments[i].x;
+ tmp64 *= dy;
+ do_div(tmp64, dx);
+ ret = segments[i].y + tmp64;
+
+ return ret;
+}
+
+/* FIXME: may require changes - this one was borrowed from dib8000 */
+static u32 dib7000p_get_time_us(struct dvb_frontend *demod, int layer)
+{
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ u64 time_us, tmp64;
+ u32 tmp, denom;
+ int guard, rate_num, rate_denum = 1, bits_per_symbol;
+ int interleaving = 0, fft_div;
+
+ switch (c->guard_interval) {
+ case GUARD_INTERVAL_1_4:
+ guard = 4;
+ break;
+ case GUARD_INTERVAL_1_8:
+ guard = 8;
+ break;
+ case GUARD_INTERVAL_1_16:
+ guard = 16;
+ break;
+ default:
+ case GUARD_INTERVAL_1_32:
+ guard = 32;
+ break;
+ }
+
+ switch (c->transmission_mode) {
+ case TRANSMISSION_MODE_2K:
+ fft_div = 4;
+ break;
+ case TRANSMISSION_MODE_4K:
+ fft_div = 2;
+ break;
+ default:
+ case TRANSMISSION_MODE_8K:
+ fft_div = 1;
+ break;
+ }
+
+ switch (c->modulation) {
+ case DQPSK:
+ case QPSK:
+ bits_per_symbol = 2;
+ break;
+ case QAM_16:
+ bits_per_symbol = 4;
+ break;
+ default:
+ case QAM_64:
+ bits_per_symbol = 6;
+ break;
+ }
+
+ switch ((c->hierarchy == 0 || 1 == 1) ? c->code_rate_HP : c->code_rate_LP) {
+ case FEC_1_2:
+ rate_num = 1;
+ rate_denum = 2;
+ break;
+ case FEC_2_3:
+ rate_num = 2;
+ rate_denum = 3;
+ break;
+ case FEC_3_4:
+ rate_num = 3;
+ rate_denum = 4;
+ break;
+ case FEC_5_6:
+ rate_num = 5;
+ rate_denum = 6;
+ break;
+ default:
+ case FEC_7_8:
+ rate_num = 7;
+ rate_denum = 8;
+ break;
+ }
+
+ interleaving = interleaving;
+
+ denom = bits_per_symbol * rate_num * fft_div * 384;
+
+ /* If calculus gets wrong, wait for 1s for the next stats */
+ if (!denom)
+ return 0;
+
+ /* Estimate the period for the total bit rate */
+ time_us = rate_denum * (1008 * 1562500L);
+ tmp64 = time_us;
+ do_div(tmp64, guard);
+ time_us = time_us + tmp64;
+ time_us += denom / 2;
+ do_div(time_us, denom);
+
+ tmp = 1008 * 96 * interleaving;
+ time_us += tmp + tmp / guard;
+
+ return time_us;
+}
+
+static int dib7000p_get_stats(struct dvb_frontend *demod, fe_status_t stat)
+{
+ struct dib7000p_state *state = demod->demodulator_priv;
+ struct dtv_frontend_properties *c = &demod->dtv_property_cache;
+ int i;
+ int show_per_stats = 0;
+ u32 time_us = 0, val, snr;
+ u64 blocks, ucb;
+ s32 db;
+ u16 strength;
+
+ /* Get Signal strength */
+ dib7000p_read_signal_strength(demod, &strength);
+ val = strength;
+ db = interpolate_value(val,
+ strength_to_db_table,
+ ARRAY_SIZE(strength_to_db_table)) - DB_OFFSET;
+ c->strength.stat[0].svalue = db;
+
+ /* UCB/BER/CNR measures require lock */
+ if (!(stat & FE_HAS_LOCK)) {
+ c->cnr.len = 1;
+ c->block_count.len = 1;
+ c->block_error.len = 1;
+ c->post_bit_error.len = 1;
+ c->post_bit_count.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->post_bit_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_error.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ c->block_count.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ return 0;
+ }
+
+ /* Check if time for stats was elapsed */
+ if (time_after(jiffies, state->per_jiffies_stats)) {
+ state->per_jiffies_stats = jiffies + msecs_to_jiffies(1000);
+
+ /* Get SNR */
+ snr = dib7000p_get_snr(demod);
+ if (snr)
+ snr = (1000L * snr) >> 24;
+ else
+ snr = 0;
+ c->cnr.stat[0].svalue = snr;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+
+ /* Get UCB measures */
+ dib7000p_read_unc_blocks(demod, &val);
+ ucb = val - state->old_ucb;
+ if (val < state->old_ucb)
+ ucb += 0x100000000LL;
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue = ucb;
+
+ /* Estimate the number of packets based on bitrate */
+ if (!time_us)
+ time_us = dib7000p_get_time_us(demod, -1);
+
+ if (time_us) {
+ blocks = 1250000ULL * 1000000ULL;
+ do_div(blocks, time_us * 8 * 204);
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].uvalue += blocks;
+ }
+
+ show_per_stats = 1;
+ }
+
+ /* Get post-BER measures */
+ if (time_after(jiffies, state->ber_jiffies_stats)) {
+ time_us = dib7000p_get_time_us(demod, -1);
+ state->ber_jiffies_stats = jiffies + msecs_to_jiffies((time_us + 500) / 1000);
+
+ dprintk("Next all layers stats available in %u us.", time_us);
+
+ dib7000p_read_ber(demod, &val);
+ c->post_bit_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_error.stat[0].uvalue += val;
+
+ c->post_bit_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->post_bit_count.stat[0].uvalue += 100000000;
+ }
+
+ /* Get PER measures */
+ if (show_per_stats) {
+ dib7000p_read_unc_blocks(demod, &val);
+
+ c->block_error.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_error.stat[0].uvalue += val;
+
+ time_us = dib7000p_get_time_us(demod, i);
+ if (time_us) {
+ blocks = 1250000ULL * 1000000ULL;
+ do_div(blocks, time_us * 8 * 204);
+ c->block_count.stat[0].scale = FE_SCALE_COUNTER;
+ c->block_count.stat[0].uvalue += blocks;
+ }
+ }
+ return 0;
+}
+
static int dib7000p_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
@@ -1643,7 +1994,7 @@ static void dib7000p_release(struct dvb_frontend *demod)
kfree(st);
}
-int dib7000pc_detection(struct i2c_adapter *i2c_adap)
+static int dib7000pc_detection(struct i2c_adapter *i2c_adap)
{
u8 *tx, *rx;
struct i2c_msg msg[2] = {
@@ -1688,16 +2039,14 @@ rx_memory_error:
kfree(tx);
return ret;
}
-EXPORT_SYMBOL(dib7000pc_detection);
-struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating)
{
struct dib7000p_state *st = demod->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
-EXPORT_SYMBOL(dib7000p_get_i2c_master);
-int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 val = dib7000p_read_word(state, 235) & 0xffef;
@@ -1705,17 +2054,15 @@ int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("PID filter enabled %d", onoff);
return dib7000p_write_word(state, 235, val);
}
-EXPORT_SYMBOL(dib7000p_pid_filter_ctrl);
-int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+static int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
dprintk("PID filter: index %x, PID %d, OnOff %d", id, pid, onoff);
return dib7000p_write_word(state, 241 + id, onoff ? (1 << 13) | pid : 0);
}
-EXPORT_SYMBOL(dib7000p_pid_filter);
-int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
+static int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
{
struct dib7000p_state *dpst;
int k = 0;
@@ -1774,7 +2121,6 @@ int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 defau
kfree(dpst);
return 0;
}
-EXPORT_SYMBOL(dib7000p_i2c_enumeration);
static const s32 lut_1000ln_mant[] = {
6908, 6956, 7003, 7047, 7090, 7131, 7170, 7208, 7244, 7279, 7313, 7346, 7377, 7408, 7438, 7467, 7495, 7523, 7549, 7575, 7600
@@ -2032,12 +2378,11 @@ static struct i2c_algorithm dib7090_tuner_xfer_algo = {
.functionality = dib7000p_i2c_func,
};
-struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib7000p_state *st = fe->demodulator_priv;
return &st->dib7090_tuner_adap;
}
-EXPORT_SYMBOL(dib7090_get_i2c_tuner);
static int dib7090_host_bus_drive(struct dib7000p_state *state, u8 drive)
{
@@ -2329,7 +2674,7 @@ static int dib7090_set_output_mode(struct dvb_frontend *fe, int mode)
return ret;
}
-int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 en_cur_state;
@@ -2352,15 +2697,13 @@ int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
-EXPORT_SYMBOL(dib7090_tuner_sleep);
-int dib7090_get_adc_power(struct dvb_frontend *fe)
+static int dib7090_get_adc_power(struct dvb_frontend *fe)
{
return dib7000p_get_adc_power(fe);
}
-EXPORT_SYMBOL(dib7090_get_adc_power);
-int dib7090_slave_reset(struct dvb_frontend *fe)
+static int dib7090_slave_reset(struct dvb_frontend *fe)
{
struct dib7000p_state *state = fe->demodulator_priv;
u16 reg;
@@ -2371,10 +2714,9 @@ int dib7090_slave_reset(struct dvb_frontend *fe)
dib7000p_write_word(state, 1032, 0xffff);
return 0;
}
-EXPORT_SYMBOL(dib7090_slave_reset);
static struct dvb_frontend_ops dib7000p_ops;
-struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
+static struct dvb_frontend *dib7000p_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
{
struct dvb_frontend *demod;
struct dib7000p_state *st;
@@ -2423,6 +2765,8 @@ struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr,
dib7000p_demod_reset(st);
+ dib7000p_reset_stats(demod);
+
if (st->version == SOC7090) {
dib7090_set_output_mode(demod, st->cfg.output_mode);
dib7090_set_diversity_in(demod, 0);
@@ -2434,6 +2778,31 @@ error:
kfree(st);
return NULL;
}
+
+void *dib7000p_attach(struct dib7000p_ops *ops)
+{
+ if (!ops)
+ return NULL;
+
+ ops->slave_reset = dib7090_slave_reset;
+ ops->get_adc_power = dib7090_get_adc_power;
+ ops->dib7000pc_detection = dib7000pc_detection;
+ ops->get_i2c_tuner = dib7090_get_i2c_tuner;
+ ops->tuner_sleep = dib7090_tuner_sleep;
+ ops->init = dib7000p_init;
+ ops->set_agc1_min = dib7000p_set_agc1_min;
+ ops->set_gpio = dib7000p_set_gpio;
+ ops->i2c_enumeration = dib7000p_i2c_enumeration;
+ ops->pid_filter = dib7000p_pid_filter;
+ ops->pid_filter_ctrl = dib7000p_pid_filter_ctrl;
+ ops->get_i2c_master = dib7000p_get_i2c_master;
+ ops->update_pll = dib7000p_update_pll;
+ ops->ctrl_timf = dib7000p_ctrl_timf;
+ ops->get_agc_values = dib7000p_get_agc_values;
+ ops->set_wbd_ref = dib7000p_set_wbd_ref;
+
+ return ops;
+}
EXPORT_SYMBOL(dib7000p_attach);
static struct dvb_frontend_ops dib7000p_ops = {
diff --git a/drivers/media/dvb-frontends/dib7000p.h b/drivers/media/dvb-frontends/dib7000p.h
index d08cdff59bdf..1fea0e972654 100644
--- a/drivers/media/dvb-frontends/dib7000p.h
+++ b/drivers/media/dvb-frontends/dib7000p.h
@@ -46,121 +46,34 @@ struct dib7000p_config {
#define DEFAULT_DIB7000P_I2C_ADDRESS 18
-#if IS_ENABLED(CONFIG_DVB_DIB7000P)
-extern struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
-extern struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-extern int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
-extern int dib7000p_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib7000p_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib7000pc_detection(struct i2c_adapter *i2c_adap);
-extern int dib7000p_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff);
-extern int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
-extern u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf);
-extern int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib7090_get_adc_power(struct dvb_frontend *fe);
-extern struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib7090_slave_reset(struct dvb_frontend *fe);
-extern int dib7000p_get_agc_values(struct dvb_frontend *fe,
+struct dib7000p_ops {
+ int (*set_wbd_ref)(struct dvb_frontend *demod, u16 value);
+ int (*get_agc_values)(struct dvb_frontend *fe,
u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd);
-extern int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v);
-#else
-static inline struct dvb_frontend *dib7000p_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline struct i2c_adapter *dib7000p_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline int dib7000p_i2c_enumeration(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[])
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000pc_detection(struct i2c_adapter *i2c_adap)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_pid_filter_ctrl(struct dvb_frontend *fe, uint8_t onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_update_pll(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline u32 dib7000p_ctrl_timf(struct dvb_frontend *fe, u8 op, u32 timf)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-
-static inline int dib7090_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7090_get_adc_power(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
+ int (*set_agc1_min)(struct dvb_frontend *fe, u16 v);
+ int (*update_pll)(struct dvb_frontend *fe, struct dibx000_bandwidth_config *bw);
+ int (*set_gpio)(struct dvb_frontend *demod, u8 num, u8 dir, u8 val);
+ u32 (*ctrl_timf)(struct dvb_frontend *fe, u8 op, u32 timf);
+ int (*dib7000pc_detection)(struct i2c_adapter *i2c_adap);
+ struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *demod, enum dibx000_i2c_interface intf, int gating);
+ int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+ int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+ int (*i2c_enumeration)(struct i2c_adapter *i2c, int no_of_demods, u8 default_addr, struct dib7000p_config cfg[]);
+ struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+ int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+ int (*get_adc_power)(struct dvb_frontend *fe);
+ int (*slave_reset)(struct dvb_frontend *fe);
+ struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib7000p_config *cfg);
+};
-static inline struct i2c_adapter *dib7090_get_i2c_tuner(struct dvb_frontend *fe)
+#if IS_ENABLED(CONFIG_DVB_DIB7000P)
+void *dib7000p_attach(struct dib7000p_ops *ops);
+#else
+static inline void *dib7000p_attach(struct dib7000p_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
}
-
-static inline int dib7090_slave_reset(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_get_agc_values(struct dvb_frontend *fe,
- u16 *agc_global, u16 *agc1, u16 *agc2, u16 *wbd)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib7000p_set_agc1_min(struct dvb_frontend *fe, u16 v)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
#endif
#endif
diff --git a/drivers/media/dvb-frontends/dib8000.c b/drivers/media/dvb-frontends/dib8000.c
index 1632d78a5479..61e31f2d2f71 100644
--- a/drivers/media/dvb-frontends/dib8000.c
+++ b/drivers/media/dvb-frontends/dib8000.c
@@ -115,7 +115,7 @@ struct dib8000_state {
u16 found_guard;
u8 subchannel;
u8 symbol_duration;
- u32 timeout;
+ unsigned long timeout;
u8 longest_intlv_layer;
u16 output_mode;
@@ -588,8 +588,8 @@ static int dib8000_set_adc_state(struct dib8000_state *state, enum dibx000_adc_s
break;
case DIBX000_ADC_OFF: // leave the VBG voltage on
- reg_907 |= (1 << 14) | (1 << 13) | (1 << 12);
- reg_908 |= (1 << 5) | (1 << 4) | (1 << 3) | (1 << 2);
+ reg_907 = (1 << 13) | (1 << 12);
+ reg_908 = (1 << 6) | (1 << 5) | (1 << 4) | (1 << 3) | (1 << 1);
break;
case DIBX000_VBG_ENABLE:
@@ -656,7 +656,7 @@ static int dib8000_sad_calib(struct dib8000_state *state)
return 0;
}
-int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
+static int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
{
struct dib8000_state *state = fe->demodulator_priv;
if (value > 4095)
@@ -664,7 +664,6 @@ int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
state->wbd_ref = value;
return dib8000_write_word(state, 106, value);
}
-EXPORT_SYMBOL(dib8000_set_wbd_ref);
static void dib8000_reset_pll_common(struct dib8000_state *state, const struct dibx000_bandwidth_config *bw)
{
@@ -739,7 +738,7 @@ static void dib8000_reset_pll(struct dib8000_state *state)
dib8000_reset_pll_common(state, pll);
}
-int dib8000_update_pll(struct dvb_frontend *fe,
+static int dib8000_update_pll(struct dvb_frontend *fe,
struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -815,8 +814,6 @@ int dib8000_update_pll(struct dvb_frontend *fe,
return 0;
}
-EXPORT_SYMBOL(dib8000_update_pll);
-
static int dib8000_reset_gpio(struct dib8000_state *st)
{
@@ -849,13 +846,12 @@ static int dib8000_cfg_gpio(struct dib8000_state *st, u8 num, u8 dir, u8 val)
return 0;
}
-int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
+static int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
{
struct dib8000_state *state = fe->demodulator_priv;
return dib8000_cfg_gpio(state, num, dir, val);
}
-EXPORT_SYMBOL(dib8000_set_gpio);
static const u16 dib8000_defaults[] = {
/* auto search configuration - lock0 by default waiting
* for cpil_lock; lock1 cpil_lock; lock2 tmcc_sync_lock */
@@ -1054,6 +1050,7 @@ static int dib8000_reset(struct dvb_frontend *fe)
dib8000_write_word(state, 770, 0xffff);
dib8000_write_word(state, 771, 0xffff);
dib8000_write_word(state, 772, 0xfffc);
+ dib8000_write_word(state, 898, 0x000c); /* restart sad */
if (state->revision == 0x8090)
dib8000_write_word(state, 1280, 0x0045);
else
@@ -1228,20 +1225,19 @@ static int dib8000_set_agc_config(struct dib8000_state *state, u8 band)
return 0;
}
-void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
+static void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
dib8000_set_adc_state(state, DIBX000_ADC_ON);
dib8000_set_agc_config(state, (unsigned char)(BAND_OF_FREQUENCY(fe->dtv_property_cache.frequency / 1000)));
}
-EXPORT_SYMBOL(dib8000_pwm_agc_reset);
static int dib8000_agc_soft_split(struct dib8000_state *state)
{
u16 agc, split_offset;
if (!state->current_agc || !state->current_agc->perform_agc_softsplit || state->current_agc->split.max == 0)
- return FE_CALLBACK_TIME_NEVER;
+ return 0;
// n_agc_global
agc = dib8000_read_word(state, 390);
@@ -1881,14 +1877,13 @@ static struct i2c_algorithm dib8096p_tuner_xfer_algo = {
.functionality = dib8096p_i2c_func,
};
-struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
+static struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
{
struct dib8000_state *st = fe->demodulator_priv;
return &st->dib8096p_tuner_adap;
}
-EXPORT_SYMBOL(dib8096p_get_i2c_tuner);
-int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
+static int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
struct dib8000_state *state = fe->demodulator_priv;
u16 en_cur_state;
@@ -1912,14 +1907,13 @@ int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
return 0;
}
-EXPORT_SYMBOL(dib8096p_tuner_sleep);
static const s32 lut_1000ln_mant[] =
{
908, 7003, 7090, 7170, 7244, 7313, 7377, 7438, 7495, 7549, 7600
};
-s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
+static s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
{
struct dib8000_state *state = fe->demodulator_priv;
u32 ix = 0, tmp_val = 0, exp = 0, mant = 0;
@@ -1937,9 +1931,8 @@ s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
}
return val;
}
-EXPORT_SYMBOL(dib8000_get_adc_power);
-int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
+static int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
{
struct dib8000_state *state = fe->demodulator_priv;
int val = 0;
@@ -1957,7 +1950,6 @@ int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
return val;
}
-EXPORT_SYMBOL(dib8090p_get_dc_power);
static void dib8000_update_timf(struct dib8000_state *state)
{
@@ -1968,7 +1960,7 @@ static void dib8000_update_timf(struct dib8000_state *state)
dprintk("Updated timing frequency: %d (default: %d)", state->timf, state->timf_default);
}
-u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
+static u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -1986,21 +1978,11 @@ u32 dib8000_ctrl_timf(struct dvb_frontend *fe, uint8_t op, uint32_t timf)
return state->timf;
}
-EXPORT_SYMBOL(dib8000_ctrl_timf);
static const u16 adc_target_16dB[11] = {
- (1 << 13) - 825 - 117,
- (1 << 13) - 837 - 117,
- (1 << 13) - 811 - 117,
- (1 << 13) - 766 - 117,
- (1 << 13) - 737 - 117,
- (1 << 13) - 693 - 117,
- (1 << 13) - 648 - 117,
- (1 << 13) - 619 - 117,
- (1 << 13) - 575 - 117,
- (1 << 13) - 531 - 117,
- (1 << 13) - 501 - 117
+ 7250, 7238, 7264, 7309, 7338, 7382, 7427, 7456, 7500, 7544, 7574
};
+
static const u8 permu_seg[] = { 6, 5, 7, 4, 8, 3, 9, 2, 10, 1, 11, 0, 12 };
static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 max_constellation)
@@ -2043,9 +2025,8 @@ static u16 dib8000_set_layer(struct dib8000_state *state, u8 layer_index, u16 ma
break;
}
- if ((c->layer[layer_index].interleaving > 0) && ((c->layer[layer_index].interleaving <= 3) || (c->layer[layer_index].interleaving == 4 && c->isdbt_sb_mode == 1)))
- time_intlv = c->layer[layer_index].interleaving;
- else
+ time_intlv = fls(c->layer[layer_index].interleaving);
+ if (time_intlv > 3 && !(time_intlv == 4 && c->isdbt_sb_mode == 1))
time_intlv = 0;
dib8000_write_word(state, 2 + layer_index, (constellation << 10) | ((c->layer[layer_index].segment_count & 0xf) << 6) | (cr << 3) | time_intlv);
@@ -2362,6 +2343,9 @@ static void dib8000_set_isdbt_common_channel(struct dib8000_state *state, u8 seq
int init_prbs;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
+ if (autosearching)
+ c->isdbt_partial_reception = 1;
+
/* P_mode */
dib8000_write_word(state, 10, (seq << 4));
@@ -2856,12 +2840,12 @@ static void dib8000_set_sync_wait(struct dib8000_state *state)
dib8000_write_word(state, 273, (dib8000_read_word(state, 273) & 0x000f) | (sync_wait << 4));
}
-static u32 dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
+static unsigned long dib8000_get_timeout(struct dib8000_state *state, u32 delay, enum timeout_mode mode)
{
if (mode == SYMBOL_DEPENDENT_ON)
- return systime() + (delay * state->symbol_duration);
- else
- return systime() + delay;
+ delay *= state->symbol_duration;
+
+ return jiffies + usecs_to_jiffies(delay * 100);
}
static s32 dib8000_get_status(struct dvb_frontend *fe)
@@ -2870,21 +2854,19 @@ static s32 dib8000_get_status(struct dvb_frontend *fe)
return state->status;
}
-enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
+static enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
return state->tune_state;
}
-EXPORT_SYMBOL(dib8000_get_tune_state);
-int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
+static int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
{
struct dib8000_state *state = fe->demodulator_priv;
state->tune_state = tune_state;
return 0;
}
-EXPORT_SYMBOL(dib8000_set_tune_state);
static int dib8000_tune_restart_from_demod(struct dvb_frontend *fe)
{
@@ -3015,8 +2997,8 @@ static int dib8000_tune(struct dvb_frontend *fe)
u16 locks, deeper_interleaver = 0, i;
int ret = 1; /* 1 symbol duration (in 100us unit) delay most of the time */
- u32 *timeout = &state->timeout;
- u32 now = systime();
+ unsigned long *timeout = &state->timeout;
+ unsigned long now = jiffies;
#ifdef DIB8000_AGC_FREEZE
u16 agc1, agc2;
#endif
@@ -3026,318 +3008,327 @@ static int dib8000_tune(struct dvb_frontend *fe)
#if 0
if (*tune_state < CT_DEMOD_STOP)
- dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u systime = %u", state->channel_parameters_set, *tune_state, state->autosearch_state, now);
+ dprintk("IN: context status = %d, TUNE_STATE %d autosearch step = %u jiffies = %lu",
+ state->channel_parameters_set, *tune_state, state->autosearch_state, now);
#endif
switch (*tune_state) {
case CT_DEMOD_START: /* 30 */
- dib8000_reset_stats(fe);
+ dib8000_reset_stats(fe);
- if (state->revision == 0x8090)
- dib8090p_init_sdram(state);
- state->status = FE_STATUS_TUNE_PENDING;
- state->channel_parameters_set = is_manual_mode(c);
+ if (state->revision == 0x8090)
+ dib8090p_init_sdram(state);
+ state->status = FE_STATUS_TUNE_PENDING;
+ state->channel_parameters_set = is_manual_mode(c);
- dprintk("Tuning channel on %s search mode",
- state->channel_parameters_set ? "manual" : "auto");
+ dprintk("Tuning channel on %s search mode",
+ state->channel_parameters_set ? "manual" : "auto");
- dib8000_viterbi_state(state, 0); /* force chan dec in restart */
+ dib8000_viterbi_state(state, 0); /* force chan dec in restart */
- /* Layer monitor */
- dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
+ /* Layer monitor */
+ dib8000_write_word(state, 285, dib8000_read_word(state, 285) & 0x60);
- dib8000_set_frequency_offset(state);
- dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
+ dib8000_set_frequency_offset(state);
+ dib8000_set_bandwidth(fe, c->bandwidth_hz / 1000);
- if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
+ if (state->channel_parameters_set == 0) { /* The channel struct is unknown, search it ! */
#ifdef DIB8000_AGC_FREEZE
- if (state->revision != 0x8090) {
- state->agc1_max = dib8000_read_word(state, 108);
- state->agc1_min = dib8000_read_word(state, 109);
- state->agc2_max = dib8000_read_word(state, 110);
- state->agc2_min = dib8000_read_word(state, 111);
- agc1 = dib8000_read_word(state, 388);
- agc2 = dib8000_read_word(state, 389);
- dib8000_write_word(state, 108, agc1);
- dib8000_write_word(state, 109, agc1);
- dib8000_write_word(state, 110, agc2);
- dib8000_write_word(state, 111, agc2);
- }
-#endif
- state->autosearch_state = AS_SEARCHING_FFT;
- state->found_nfft = TRANSMISSION_MODE_AUTO;
- state->found_guard = GUARD_INTERVAL_AUTO;
- *tune_state = CT_DEMOD_SEARCH_NEXT;
- } else { /* we already know the channel struct so TUNE only ! */
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STEP_3;
+ if (state->revision != 0x8090) {
+ state->agc1_max = dib8000_read_word(state, 108);
+ state->agc1_min = dib8000_read_word(state, 109);
+ state->agc2_max = dib8000_read_word(state, 110);
+ state->agc2_min = dib8000_read_word(state, 111);
+ agc1 = dib8000_read_word(state, 388);
+ agc2 = dib8000_read_word(state, 389);
+ dib8000_write_word(state, 108, agc1);
+ dib8000_write_word(state, 109, agc1);
+ dib8000_write_word(state, 110, agc2);
+ dib8000_write_word(state, 111, agc2);
}
- state->symbol_duration = dib8000_get_symbol_duration(state);
- break;
+#endif
+ state->autosearch_state = AS_SEARCHING_FFT;
+ state->found_nfft = TRANSMISSION_MODE_AUTO;
+ state->found_guard = GUARD_INTERVAL_AUTO;
+ *tune_state = CT_DEMOD_SEARCH_NEXT;
+ } else { /* we already know the channel struct so TUNE only ! */
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STEP_3;
+ }
+ state->symbol_duration = dib8000_get_symbol_duration(state);
+ break;
case CT_DEMOD_SEARCH_NEXT: /* 51 */
- dib8000_autosearch_start(fe);
- if (state->revision == 0x8090)
- ret = 50;
- else
- ret = 15;
- *tune_state = CT_DEMOD_STEP_1;
- break;
+ dib8000_autosearch_start(fe);
+ if (state->revision == 0x8090)
+ ret = 50;
+ else
+ ret = 15;
+ *tune_state = CT_DEMOD_STEP_1;
+ break;
case CT_DEMOD_STEP_1: /* 31 */
- switch (dib8000_autosearch_irq(fe)) {
- case 1: /* fail */
- state->status = FE_STATUS_TUNE_FAILED;
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STOP; /* else we are done here */
- break;
- case 2: /* Succes */
- state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
- *tune_state = CT_DEMOD_STEP_3;
- if (state->autosearch_state == AS_SEARCHING_GUARD)
- *tune_state = CT_DEMOD_STEP_2;
- else
- state->autosearch_state = AS_DONE;
- break;
- case 3: /* Autosearch FFT max correlation endded */
- *tune_state = CT_DEMOD_STEP_2;
- break;
- }
+ switch (dib8000_autosearch_irq(fe)) {
+ case 1: /* fail */
+ state->status = FE_STATUS_TUNE_FAILED;
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STOP; /* else we are done here */
+ break;
+ case 2: /* Succes */
+ state->status = FE_STATUS_FFT_SUCCESS; /* signal to the upper layer, that there was a channel found and the parameters can be read */
+ *tune_state = CT_DEMOD_STEP_3;
+ if (state->autosearch_state == AS_SEARCHING_GUARD)
+ *tune_state = CT_DEMOD_STEP_2;
+ else
+ state->autosearch_state = AS_DONE;
break;
+ case 3: /* Autosearch FFT max correlation endded */
+ *tune_state = CT_DEMOD_STEP_2;
+ break;
+ }
+ break;
case CT_DEMOD_STEP_2:
- switch (state->autosearch_state) {
- case AS_SEARCHING_FFT:
- /* searching for the correct FFT */
- if (state->revision == 0x8090) {
- corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
- corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
- corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
- } else {
- corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
- corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
- corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
- }
- /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
+ switch (state->autosearch_state) {
+ case AS_SEARCHING_FFT:
+ /* searching for the correct FFT */
+ if (state->revision == 0x8090) {
+ corm[2] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+ corm[1] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+ corm[0] = (dib8000_read_word(state, 600) << 16) | (dib8000_read_word(state, 601));
+ } else {
+ corm[2] = (dib8000_read_word(state, 594) << 16) | (dib8000_read_word(state, 595));
+ corm[1] = (dib8000_read_word(state, 596) << 16) | (dib8000_read_word(state, 597));
+ corm[0] = (dib8000_read_word(state, 598) << 16) | (dib8000_read_word(state, 599));
+ }
+ /* dprintk("corm fft: %u %u %u", corm[0], corm[1], corm[2]); */
- max_value = 0;
- for (find_index = 1 ; find_index < 3 ; find_index++) {
- if (corm[max_value] < corm[find_index])
- max_value = find_index ;
- }
+ max_value = 0;
+ for (find_index = 1 ; find_index < 3 ; find_index++) {
+ if (corm[max_value] < corm[find_index])
+ max_value = find_index ;
+ }
- switch (max_value) {
- case 0:
- state->found_nfft = TRANSMISSION_MODE_2K;
- break;
- case 1:
- state->found_nfft = TRANSMISSION_MODE_4K;
- break;
- case 2:
- default:
- state->found_nfft = TRANSMISSION_MODE_8K;
- break;
- }
- /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
-
- *tune_state = CT_DEMOD_SEARCH_NEXT;
- state->autosearch_state = AS_SEARCHING_GUARD;
- if (state->revision == 0x8090)
- ret = 50;
- else
- ret = 10;
- break;
- case AS_SEARCHING_GUARD:
- /* searching for the correct guard interval */
- if (state->revision == 0x8090)
- state->found_guard = dib8000_read_word(state, 572) & 0x3;
- else
- state->found_guard = dib8000_read_word(state, 570) & 0x3;
- /* dprintk("guard interval found=%i", state->found_guard); */
-
- *tune_state = CT_DEMOD_STEP_3;
- break;
+ switch (max_value) {
+ case 0:
+ state->found_nfft = TRANSMISSION_MODE_2K;
+ break;
+ case 1:
+ state->found_nfft = TRANSMISSION_MODE_4K;
+ break;
+ case 2:
default:
- /* the demod should never be in this state */
- state->status = FE_STATUS_TUNE_FAILED;
- state->autosearch_state = AS_DONE;
- *tune_state = CT_DEMOD_STOP; /* else we are done here */
- break;
+ state->found_nfft = TRANSMISSION_MODE_8K;
+ break;
}
+ /* dprintk("Autosearch FFT has found Mode %d", max_value + 1); */
+
+ *tune_state = CT_DEMOD_SEARCH_NEXT;
+ state->autosearch_state = AS_SEARCHING_GUARD;
+ if (state->revision == 0x8090)
+ ret = 50;
+ else
+ ret = 10;
break;
+ case AS_SEARCHING_GUARD:
+ /* searching for the correct guard interval */
+ if (state->revision == 0x8090)
+ state->found_guard = dib8000_read_word(state, 572) & 0x3;
+ else
+ state->found_guard = dib8000_read_word(state, 570) & 0x3;
+ /* dprintk("guard interval found=%i", state->found_guard); */
- case CT_DEMOD_STEP_3: /* 33 */
- state->symbol_duration = dib8000_get_symbol_duration(state);
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
- dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
- *tune_state = CT_DEMOD_STEP_4;
+ *tune_state = CT_DEMOD_STEP_3;
break;
+ default:
+ /* the demod should never be in this state */
+ state->status = FE_STATUS_TUNE_FAILED;
+ state->autosearch_state = AS_DONE;
+ *tune_state = CT_DEMOD_STOP; /* else we are done here */
+ break;
+ }
+ break;
+
+ case CT_DEMOD_STEP_3: /* 33 */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_1);
+ dib8000_set_isdbt_common_channel(state, 0, 0);/* setting the known channel parameters here */
+ *tune_state = CT_DEMOD_STEP_4;
+ break;
case CT_DEMOD_STEP_4: /* (34) */
- dib8000_demod_restart(state);
+ dib8000_demod_restart(state);
- dib8000_set_sync_wait(state);
- dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
+ dib8000_set_sync_wait(state);
+ dib8000_set_diversity_in(state->fe[0], state->diversity_onoff);
- locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
- /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
- *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
- *tune_state = CT_DEMOD_STEP_5;
- break;
+ locks = (dib8000_read_word(state, 180) >> 6) & 0x3f; /* P_coff_winlen ? */
+ /* coff should lock over P_coff_winlen ofdm symbols : give 3 times this length to lock */
+ *timeout = dib8000_get_timeout(state, 2 * locks, SYMBOL_DEPENDENT_ON);
+ *tune_state = CT_DEMOD_STEP_5;
+ break;
case CT_DEMOD_STEP_5: /* (35) */
- locks = dib8000_read_lock(fe);
- if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
- dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
- if (!state->differential_constellation) {
- /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
- *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
- *tune_state = CT_DEMOD_STEP_7;
- } else {
- *tune_state = CT_DEMOD_STEP_8;
- }
- } else if (now > *timeout) {
- *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ locks = dib8000_read_lock(fe);
+ if (locks & (0x3 << 11)) { /* coff-lock and off_cpil_lock achieved */
+ dib8000_update_timf(state); /* we achieved a coff_cpil_lock - it's time to update the timf */
+ if (!state->differential_constellation) {
+ /* 2 times lmod4_win_len + 10 symbols (pipe delay after coff + nb to compute a 1st correlation) */
+ *timeout = dib8000_get_timeout(state, (20 * ((dib8000_read_word(state, 188)>>5)&0x1f)), SYMBOL_DEPENDENT_ON);
+ *tune_state = CT_DEMOD_STEP_7;
+ } else {
+ *tune_state = CT_DEMOD_STEP_8;
}
- break;
+ } else if (time_after(now, *timeout)) {
+ *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ }
+ break;
case CT_DEMOD_STEP_6: /* (36) if there is an input (diversity) */
- if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
- /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
- if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
- *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
- else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
- *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
- dib8000_viterbi_state(state, 1); /* start viterbi chandec */
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
- state->status = FE_STATUS_TUNE_FAILED;
- }
- } else {
+ if ((state->fe[1] != NULL) && (state->output_mode != OUTMODE_DIVERSITY)) {
+ /* if there is a diversity fe in input and this fe is has not already failled : wait here until this this fe has succedeed or failled */
+ if (dib8000_get_status(state->fe[1]) <= FE_STATUS_STD_SUCCESS) /* Something is locked on the input fe */
+ *tune_state = CT_DEMOD_STEP_8; /* go for mpeg */
+ else if (dib8000_get_status(state->fe[1]) >= FE_STATUS_TUNE_TIME_TOO_SHORT) { /* fe in input failled also, break the current one */
+ *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
dib8000_viterbi_state(state, 1); /* start viterbi chandec */
dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
- *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
state->status = FE_STATUS_TUNE_FAILED;
}
- break;
+ } else {
+ dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+ *tune_state = CT_DEMOD_STOP; /* else we are done here ; step 8 will close the loops and exit */
+ state->status = FE_STATUS_TUNE_FAILED;
+ }
+ break;
case CT_DEMOD_STEP_7: /* 37 */
- locks = dib8000_read_lock(fe);
- if (locks & (1<<10)) { /* lmod4_lock */
- ret = 14; /* wait for 14 symbols */
- *tune_state = CT_DEMOD_STEP_8;
- } else if (now > *timeout)
- *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
- break;
+ locks = dib8000_read_lock(fe);
+ if (locks & (1<<10)) { /* lmod4_lock */
+ ret = 14; /* wait for 14 symbols */
+ *tune_state = CT_DEMOD_STEP_8;
+ } else if (time_after(now, *timeout))
+ *tune_state = CT_DEMOD_STEP_6; /* goto check for diversity input connection */
+ break;
case CT_DEMOD_STEP_8: /* 38 */
- dib8000_viterbi_state(state, 1); /* start viterbi chandec */
- dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
-
- /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation) {
- state->subchannel = 0;
- *tune_state = CT_DEMOD_STEP_11;
- } else {
- *tune_state = CT_DEMOD_STEP_9;
- state->status = FE_STATUS_LOCKED;
- }
- break;
+ dib8000_viterbi_state(state, 1); /* start viterbi chandec */
+ dib8000_set_isdbt_loop_params(state, LOOP_TUNE_2);
+
+ /* mpeg will never lock on this condition because init_prbs is not set : search for it !*/
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation) {
+ state->subchannel = 0;
+ *tune_state = CT_DEMOD_STEP_11;
+ } else {
+ *tune_state = CT_DEMOD_STEP_9;
+ state->status = FE_STATUS_LOCKED;
+ }
+ break;
case CT_DEMOD_STEP_9: /* 39 */
- if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
- /* defines timeout for mpeg lock depending on interleaver length of longest layer */
- for (i = 0; i < 3; i++) {
- if (c->layer[i].interleaving >= deeper_interleaver) {
- dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
- if (c->layer[i].segment_count > 0) { /* valid layer */
- deeper_interleaver = c->layer[0].interleaving;
- state->longest_intlv_layer = i;
- }
+ if ((state->revision == 0x8090) || ((dib8000_read_word(state, 1291) >> 9) & 0x1)) { /* fe capable of deinterleaving : esram */
+ /* defines timeout for mpeg lock depending on interleaver length of longest layer */
+ for (i = 0; i < 3; i++) {
+ if (c->layer[i].interleaving >= deeper_interleaver) {
+ dprintk("layer%i: time interleaver = %d ", i, c->layer[i].interleaving);
+ if (c->layer[i].segment_count > 0) { /* valid layer */
+ deeper_interleaver = c->layer[0].interleaving;
+ state->longest_intlv_layer = i;
}
}
+ }
- if (deeper_interleaver == 0)
- locks = 2; /* locks is the tmp local variable name */
- else if (deeper_interleaver == 3)
- locks = 8;
- else
- locks = 2 * deeper_interleaver;
+ if (deeper_interleaver == 0)
+ locks = 2; /* locks is the tmp local variable name */
+ else if (deeper_interleaver == 3)
+ locks = 8;
+ else
+ locks = 2 * deeper_interleaver;
- if (state->diversity_onoff != 0) /* because of diversity sync */
- locks *= 2;
+ if (state->diversity_onoff != 0) /* because of diversity sync */
+ locks *= 2;
- *timeout = now + (2000 * locks); /* give the mpeg lock 800ms if sram is present */
- dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %d", deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
+ *timeout = now + msecs_to_jiffies(200 * locks); /* give the mpeg lock 800ms if sram is present */
+ dprintk("Deeper interleaver mode = %d on layer %d : timeout mult factor = %d => will use timeout = %ld",
+ deeper_interleaver, state->longest_intlv_layer, locks, *timeout);
- *tune_state = CT_DEMOD_STEP_10;
- } else
- *tune_state = CT_DEMOD_STOP;
- break;
+ *tune_state = CT_DEMOD_STEP_10;
+ } else
+ *tune_state = CT_DEMOD_STOP;
+ break;
case CT_DEMOD_STEP_10: /* 40 */
- locks = dib8000_read_lock(fe);
- if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
- dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation)
- /* signal to the upper layer, that there was a channel found and the parameters can be read */
- state->status = FE_STATUS_DEMOD_SUCCESS;
- else
+ locks = dib8000_read_lock(fe);
+ if (locks&(1<<(7-state->longest_intlv_layer))) { /* mpeg lock : check the longest one */
+ dprintk("ISDB-T layer locks: Layer A %s, Layer B %s, Layer C %s",
+ c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation)
+ /* signal to the upper layer, that there was a channel found and the parameters can be read */
+ state->status = FE_STATUS_DEMOD_SUCCESS;
+ else
+ state->status = FE_STATUS_DATA_LOCKED;
+ *tune_state = CT_DEMOD_STOP;
+ } else if (time_after(now, *timeout)) {
+ if (c->isdbt_sb_mode
+ && c->isdbt_sb_subchannel < 14
+ && !state->differential_constellation) { /* continue to try init prbs autosearch */
+ state->subchannel += 3;
+ *tune_state = CT_DEMOD_STEP_11;
+ } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
+ if (locks & (0x7 << 5)) {
+ dprintk("Not all ISDB-T layers locked in %d ms: Layer A %s, Layer B %s, Layer C %s",
+ jiffies_to_msecs(now - *timeout),
+ c->layer[0].segment_count ? (locks >> 7) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[1].segment_count ? (locks >> 6) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled",
+ c->layer[2].segment_count ? (locks >> 5) & 0x1 ? "locked" : "NOT LOCKED" : "not enabled");
+
state->status = FE_STATUS_DATA_LOCKED;
+ } else
+ state->status = FE_STATUS_TUNE_FAILED;
*tune_state = CT_DEMOD_STOP;
- } else if (now > *timeout) {
- if (c->isdbt_sb_mode
- && c->isdbt_sb_subchannel < 14
- && !state->differential_constellation) { /* continue to try init prbs autosearch */
- state->subchannel += 3;
- *tune_state = CT_DEMOD_STEP_11;
- } else { /* we are done mpeg of the longest interleaver xas not locking but let's try if an other layer has locked in the same time */
- if (locks & (0x7<<5)) {
- dprintk("Mpeg locks [ L0 : %d | L1 : %d | L2 : %d ]", (locks>>7)&0x1, (locks>>6)&0x1, (locks>>5)&0x1);
- state->status = FE_STATUS_DATA_LOCKED;
- } else
- state->status = FE_STATUS_TUNE_FAILED;
- *tune_state = CT_DEMOD_STOP;
- }
}
- break;
+ }
+ break;
case CT_DEMOD_STEP_11: /* 41 : init prbs autosearch */
- if (state->subchannel <= 41) {
- dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
- *tune_state = CT_DEMOD_STEP_9;
- } else {
- *tune_state = CT_DEMOD_STOP;
- state->status = FE_STATUS_TUNE_FAILED;
- }
- break;
+ if (state->subchannel <= 41) {
+ dib8000_set_subchannel_prbs(state, dib8000_get_init_prbs(state, state->subchannel));
+ *tune_state = CT_DEMOD_STEP_9;
+ } else {
+ *tune_state = CT_DEMOD_STOP;
+ state->status = FE_STATUS_TUNE_FAILED;
+ }
+ break;
default:
- break;
+ break;
}
/* tuning is finished - cleanup the demod */
switch (*tune_state) {
case CT_DEMOD_STOP: /* (42) */
#ifdef DIB8000_AGC_FREEZE
- if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
- dib8000_write_word(state, 108, state->agc1_max);
- dib8000_write_word(state, 109, state->agc1_min);
- dib8000_write_word(state, 110, state->agc2_max);
- dib8000_write_word(state, 111, state->agc2_min);
- state->agc1_max = 0;
- state->agc1_min = 0;
- state->agc2_max = 0;
- state->agc2_min = 0;
- }
+ if ((state->revision != 0x8090) && (state->agc1_max != 0)) {
+ dib8000_write_word(state, 108, state->agc1_max);
+ dib8000_write_word(state, 109, state->agc1_min);
+ dib8000_write_word(state, 110, state->agc2_max);
+ dib8000_write_word(state, 111, state->agc2_min);
+ state->agc1_max = 0;
+ state->agc1_min = 0;
+ state->agc2_max = 0;
+ state->agc2_min = 0;
+ }
#endif
- ret = FE_CALLBACK_TIME_NEVER;
- break;
+ ret = 0;
+ break;
default:
- break;
+ break;
}
if ((ret > 0) && (*tune_state > CT_DEMOD_STEP_3))
@@ -3408,7 +3399,7 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
if (!(stat & FE_HAS_SYNC))
return 0;
- dprintk("TMCC lock");
+ dprintk("dib8000_get_frontend: TMCC lock");
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
state->fe[index_frontend]->ops.read_status(state->fe[index_frontend], &stat);
if (stat&FE_HAS_SYNC) {
@@ -3444,91 +3435,117 @@ static int dib8000_get_frontend(struct dvb_frontend *fe)
switch ((val & 0x30) >> 4) {
case 1:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_2K;
+ dprintk("dib8000_get_frontend: transmission mode 2K");
+ break;
+ case 2:
+ fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_4K;
+ dprintk("dib8000_get_frontend: transmission mode 4K");
break;
case 3:
default:
fe->dtv_property_cache.transmission_mode = TRANSMISSION_MODE_8K;
+ dprintk("dib8000_get_frontend: transmission mode 8K");
break;
}
switch (val & 0x3) {
case 0:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_32;
- dprintk("dib8000_get_frontend GI = 1/32 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/32 ");
break;
case 1:
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_16;
- dprintk("dib8000_get_frontend GI = 1/16 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/16 ");
break;
case 2:
- dprintk("dib8000_get_frontend GI = 1/8 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/8 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_8;
break;
case 3:
- dprintk("dib8000_get_frontend GI = 1/4 ");
+ dprintk("dib8000_get_frontend: Guard Interval = 1/4 ");
fe->dtv_property_cache.guard_interval = GUARD_INTERVAL_1_4;
break;
}
val = dib8000_read_word(state, 505);
fe->dtv_property_cache.isdbt_partial_reception = val & 1;
- dprintk("dib8000_get_frontend : partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
+ dprintk("dib8000_get_frontend: partial_reception = %d ", fe->dtv_property_cache.isdbt_partial_reception);
for (i = 0; i < 3; i++) {
- val = dib8000_read_word(state, 493 + i);
- fe->dtv_property_cache.layer[i].segment_count = val & 0x0F;
- dprintk("dib8000_get_frontend : Layer %d segments = %d ", i, fe->dtv_property_cache.layer[i].segment_count);
+ int show;
+
+ val = dib8000_read_word(state, 493 + i) & 0x0f;
+ fe->dtv_property_cache.layer[i].segment_count = val;
+
+ if (val == 0 || val > 13)
+ show = 0;
+ else
+ show = 1;
+
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d segments = %d ",
+ i, fe->dtv_property_cache.layer[i].segment_count);
val = dib8000_read_word(state, 499 + i) & 0x3;
/* Interleaving can be 0, 1, 2 or 4 */
if (val == 3)
val = 4;
fe->dtv_property_cache.layer[i].interleaving = val;
- dprintk("dib8000_get_frontend : Layer %d time_intlv = %d ",
- i, fe->dtv_property_cache.layer[i].interleaving);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d time_intlv = %d ",
+ i, fe->dtv_property_cache.layer[i].interleaving);
val = dib8000_read_word(state, 481 + i);
switch (val & 0x7) {
case 1:
fe->dtv_property_cache.layer[i].fec = FEC_1_2;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 1/2 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 1/2 ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].fec = FEC_2_3;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 2/3 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 2/3 ", i);
break;
case 3:
fe->dtv_property_cache.layer[i].fec = FEC_3_4;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 3/4 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 3/4 ", i);
break;
case 5:
fe->dtv_property_cache.layer[i].fec = FEC_5_6;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 5/6 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 5/6 ", i);
break;
default:
fe->dtv_property_cache.layer[i].fec = FEC_7_8;
- dprintk("dib8000_get_frontend : Layer %d Code Rate = 7/8 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d Code Rate = 7/8 ", i);
break;
}
val = dib8000_read_word(state, 487 + i);
switch (val & 0x3) {
case 0:
- dprintk("dib8000_get_frontend : Layer %d DQPSK ", i);
fe->dtv_property_cache.layer[i].modulation = DQPSK;
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d DQPSK ", i);
break;
case 1:
fe->dtv_property_cache.layer[i].modulation = QPSK;
- dprintk("dib8000_get_frontend : Layer %d QPSK ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QPSK ", i);
break;
case 2:
fe->dtv_property_cache.layer[i].modulation = QAM_16;
- dprintk("dib8000_get_frontend : Layer %d QAM16 ", i);
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QAM16 ", i);
break;
case 3:
default:
- dprintk("dib8000_get_frontend : Layer %d QAM64 ", i);
fe->dtv_property_cache.layer[i].modulation = QAM_64;
+ if (show)
+ dprintk("dib8000_get_frontend: Layer %d QAM64 ", i);
break;
}
}
@@ -3554,9 +3571,9 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
struct dtv_frontend_properties *c = &state->fe[0]->dtv_property_cache;
- int l, i, active, time, time_slave = FE_CALLBACK_TIME_NEVER;
+ int l, i, active, time, time_slave = 0;
u8 exit_condition, index_frontend;
- u32 delay, callback_time;
+ unsigned long delay, callback_time;
if (c->frequency == 0) {
dprintk("dib8000: must at least specify frequency ");
@@ -3608,15 +3625,24 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
time = dib8000_agc_startup(state->fe[0]);
for (index_frontend = 1; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
time_slave = dib8000_agc_startup(state->fe[index_frontend]);
- if (time == FE_CALLBACK_TIME_NEVER)
+ if (time == 0)
time = time_slave;
- else if ((time_slave != FE_CALLBACK_TIME_NEVER) && (time_slave > time))
+ else if ((time_slave != 0) && (time_slave > time))
time = time_slave;
}
- if (time != FE_CALLBACK_TIME_NEVER)
- msleep(time / 10);
- else
+ if (time == 0)
break;
+
+ /*
+ * Despite dib8000_agc_startup returns time at a 0.1 ms range,
+ * the actual sleep time depends on CONFIG_HZ. The worse case
+ * is when CONFIG_HZ=100. In such case, the minimum granularity
+ * is 10ms. On some real field tests, the tuner sometimes don't
+ * lock when this timer is lower than 10ms. So, enforce a 10ms
+ * granularity.
+ */
+ time = 10 * (time + 99)/100;
+ usleep_range(time * 1000, (time + 1) * 1000);
exit_condition = 1;
for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
if (dib8000_get_tune_state(state->fe[index_frontend]) != CT_AGC_STOP) {
@@ -3631,11 +3657,14 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
active = 1;
do {
- callback_time = FE_CALLBACK_TIME_NEVER;
+ callback_time = 0;
for (index_frontend = 0; (index_frontend < MAX_NUMBER_OF_FRONTENDS) && (state->fe[index_frontend] != NULL); index_frontend++) {
delay = dib8000_tune(state->fe[index_frontend]);
- if (delay != FE_CALLBACK_TIME_NEVER)
- delay += systime();
+ if (delay != 0) {
+ delay = jiffies + usecs_to_jiffies(100 * delay);
+ if (!callback_time || delay < callback_time)
+ callback_time = delay;
+ }
/* we are in autosearch */
if (state->channel_parameters_set == 0) { /* searching */
@@ -3646,6 +3675,7 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
for (l = 0; (l < MAX_NUMBER_OF_FRONTENDS) && (state->fe[l] != NULL); l++) {
if (l != index_frontend) { /* and for all frontend except the successful one */
+ dprintk("Restarting frontend %d\n", l);
dib8000_tune_restart_from_demod(state->fe[l]);
state->fe[l]->dtv_property_cache.isdbt_sb_mode = state->fe[index_frontend]->dtv_property_cache.isdbt_sb_mode;
@@ -3664,8 +3694,6 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
}
}
}
- if (delay < callback_time)
- callback_time = delay;
}
/* tuning is done when the master frontend is done (failed or success) */
if (dib8000_get_status(state->fe[0]) == FE_STATUS_TUNE_FAILED ||
@@ -3681,12 +3709,12 @@ static int dib8000_set_frontend(struct dvb_frontend *fe)
dprintk("tuning done with status %d", dib8000_get_status(state->fe[0]));
}
- if ((active == 1) && (callback_time == FE_CALLBACK_TIME_NEVER)) {
+ if ((active == 1) && (callback_time == 0)) {
dprintk("strange callback time something went wrong");
active = 0;
}
- while ((active == 1) && (systime() < callback_time))
+ while ((active == 1) && (time_before(jiffies, callback_time)))
msleep(100);
} while (active);
@@ -4201,7 +4229,7 @@ static int dib8000_get_stats(struct dvb_frontend *fe, fe_status_t stat)
return 0;
}
-int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
+static int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
{
struct dib8000_state *state = fe->demodulator_priv;
u8 index_frontend = 1;
@@ -4217,9 +4245,8 @@ int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_
dprintk("too many slave frontend");
return -ENOMEM;
}
-EXPORT_SYMBOL(dib8000_set_slave_frontend);
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
+static int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
{
struct dib8000_state *state = fe->demodulator_priv;
u8 index_frontend = 1;
@@ -4235,9 +4262,8 @@ int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
dprintk("no frontend to be removed");
return -ENODEV;
}
-EXPORT_SYMBOL(dib8000_remove_slave_frontend);
-struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
{
struct dib8000_state *state = fe->demodulator_priv;
@@ -4245,10 +4271,8 @@ struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int sla
return NULL;
return state->fe[slave_index];
}
-EXPORT_SYMBOL(dib8000_get_slave_frontend);
-
-int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+static int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p)
{
int k = 0, ret = 0;
@@ -4325,7 +4349,6 @@ error_memory_read:
return ret;
}
-EXPORT_SYMBOL(dib8000_i2c_enumeration);
static int dib8000_fe_get_tune_settings(struct dvb_frontend *fe, struct dvb_frontend_tune_settings *tune)
{
tune->min_delay_ms = 1000;
@@ -4348,15 +4371,13 @@ static void dib8000_release(struct dvb_frontend *fe)
kfree(st);
}
-struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
+static struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating)
{
struct dib8000_state *st = fe->demodulator_priv;
return dibx000_get_i2c_adapter(&st->i2c_master, intf, gating);
}
-EXPORT_SYMBOL(dib8000_get_i2c_master);
-
-int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
+static int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
{
struct dib8000_state *st = fe->demodulator_priv;
u16 val = dib8000_read_word(st, 299) & 0xffef;
@@ -4365,15 +4386,13 @@ int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
dprintk("pid filter enabled %d", onoff);
return dib8000_write_word(st, 299, val);
}
-EXPORT_SYMBOL(dib8000_pid_filter_ctrl);
-int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
+static int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
{
struct dib8000_state *st = fe->demodulator_priv;
dprintk("Index %x, PID %d, OnOff %d", id, pid, onoff);
return dib8000_write_word(st, 305 + id, onoff ? (1 << 13) | pid : 0);
}
-EXPORT_SYMBOL(dib8000_pid_filter);
static const struct dvb_frontend_ops dib8000_ops = {
.delsys = { SYS_ISDBT },
@@ -4405,12 +4424,12 @@ static const struct dvb_frontend_ops dib8000_ops = {
.read_ucblocks = dib8000_read_unc_blocks,
};
-struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
+static struct dvb_frontend *dib8000_init(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
{
struct dvb_frontend *fe;
struct dib8000_state *state;
- dprintk("dib8000_attach");
+ dprintk("dib8000_init");
state = kzalloc(sizeof(struct dib8000_state), GFP_KERNEL);
if (state == NULL)
@@ -4467,6 +4486,33 @@ error:
return NULL;
}
+void *dib8000_attach(struct dib8000_ops *ops)
+{
+ if (!ops)
+ return NULL;
+
+ ops->pwm_agc_reset = dib8000_pwm_agc_reset;
+ ops->get_dc_power = dib8090p_get_dc_power;
+ ops->set_gpio = dib8000_set_gpio;
+ ops->get_slave_frontend = dib8000_get_slave_frontend;
+ ops->set_tune_state = dib8000_set_tune_state;
+ ops->pid_filter_ctrl = dib8000_pid_filter_ctrl;
+ ops->remove_slave_frontend = dib8000_remove_slave_frontend;
+ ops->get_adc_power = dib8000_get_adc_power;
+ ops->update_pll = dib8000_update_pll;
+ ops->tuner_sleep = dib8096p_tuner_sleep;
+ ops->get_tune_state = dib8000_get_tune_state;
+ ops->get_i2c_tuner = dib8096p_get_i2c_tuner;
+ ops->set_slave_frontend = dib8000_set_slave_frontend;
+ ops->pid_filter = dib8000_pid_filter;
+ ops->ctrl_timf = dib8000_ctrl_timf;
+ ops->init = dib8000_init;
+ ops->get_i2c_master = dib8000_get_i2c_master;
+ ops->i2c_enumeration = dib8000_i2c_enumeration;
+ ops->set_wbd_ref = dib8000_set_wbd_ref;
+
+ return ops;
+}
EXPORT_SYMBOL(dib8000_attach);
MODULE_AUTHOR("Olivier Grenie <Olivier.Grenie@dibcom.fr, " "Patrick Boettcher <pboettcher@dibcom.fr>");
diff --git a/drivers/media/dvb-frontends/dib8000.h b/drivers/media/dvb-frontends/dib8000.h
index b8c11e52c512..84cc10383dcd 100644
--- a/drivers/media/dvb-frontends/dib8000.h
+++ b/drivers/media/dvb-frontends/dib8000.h
@@ -39,134 +39,34 @@ struct dib8000_config {
#define DEFAULT_DIB8000_I2C_ADDRESS 18
-#if IS_ENABLED(CONFIG_DVB_DIB8000)
-extern struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
-extern struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *, enum dibx000_i2c_interface, int);
-
-extern int dib8000_i2c_enumeration(struct i2c_adapter *host, int no_of_demods,
+struct dib8000_ops {
+ int (*set_wbd_ref)(struct dvb_frontend *fe, u16 value);
+ int (*update_pll)(struct dvb_frontend *fe,
+ struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
+ int (*set_gpio)(struct dvb_frontend *fe, u8 num, u8 dir, u8 val);
+ void (*pwm_agc_reset)(struct dvb_frontend *fe);
+ struct i2c_adapter *(*get_i2c_tuner)(struct dvb_frontend *fe);
+ int (*tuner_sleep)(struct dvb_frontend *fe, int onoff);
+ s32 (*get_adc_power)(struct dvb_frontend *fe, u8 mode);
+ int (*get_dc_power)(struct dvb_frontend *fe, u8 IQ);
+ u32 (*ctrl_timf)(struct dvb_frontend *fe, uint8_t op, uint32_t timf);
+ enum frontend_tune_state (*get_tune_state)(struct dvb_frontend *fe);
+ int (*set_tune_state)(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
+ int (*set_slave_frontend)(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
+ int (*remove_slave_frontend)(struct dvb_frontend *fe);
+ struct dvb_frontend *(*get_slave_frontend)(struct dvb_frontend *fe, int slave_index);
+ int (*i2c_enumeration)(struct i2c_adapter *host, int no_of_demods,
u8 default_addr, u8 first_addr, u8 is_dib8096p);
+ struct i2c_adapter *(*get_i2c_master)(struct dvb_frontend *fe, enum dibx000_i2c_interface intf, int gating);
+ int (*pid_filter_ctrl)(struct dvb_frontend *fe, u8 onoff);
+ int (*pid_filter)(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff);
+ struct dvb_frontend *(*init)(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg);
+};
-extern int dib8000_set_gpio(struct dvb_frontend *, u8 num, u8 dir, u8 val);
-extern int dib8000_set_wbd_ref(struct dvb_frontend *, u16 value);
-extern int dib8000_pid_filter_ctrl(struct dvb_frontend *, u8 onoff);
-extern int dib8000_pid_filter(struct dvb_frontend *, u8 id, u16 pid, u8 onoff);
-extern int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state);
-extern enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe);
-extern void dib8000_pwm_agc_reset(struct dvb_frontend *fe);
-extern s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode);
-extern struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe);
-extern int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff);
-extern int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ);
-extern u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
- uint8_t op, uint32_t timf);
-extern int dib8000_update_pll(struct dvb_frontend *fe,
- struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio);
-extern int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave);
-extern int dib8000_remove_slave_frontend(struct dvb_frontend *fe);
-extern struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index);
+#if IS_ENABLED(CONFIG_DVB_DIB8000)
+void *dib8000_attach(struct dib8000_ops *ops);
#else
-static inline struct dvb_frontend *dib8000_attach(struct i2c_adapter *i2c_adap, u8 i2c_addr, struct dib8000_config *cfg)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline struct i2c_adapter *dib8000_get_i2c_master(struct dvb_frontend *fe, enum dibx000_i2c_interface i, int x)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-
-static inline int dib8000_i2c_enumeration(struct i2c_adapter *host,
- int no_of_demods, u8 default_addr, u8 first_addr,
- u8 is_dib8096p)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_set_gpio(struct dvb_frontend *fe, u8 num, u8 dir, u8 val)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_set_wbd_ref(struct dvb_frontend *fe, u16 value)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_pid_filter_ctrl(struct dvb_frontend *fe, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline int dib8000_pid_filter(struct dvb_frontend *fe, u8 id, u16 pid, u8 onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline int dib8000_set_tune_state(struct dvb_frontend *fe, enum frontend_tune_state tune_state)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline enum frontend_tune_state dib8000_get_tune_state(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return CT_SHUTDOWN;
-}
-static inline void dib8000_pwm_agc_reset(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
-}
-static inline struct i2c_adapter *dib8096p_get_i2c_tuner(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return NULL;
-}
-static inline int dib8096p_tuner_sleep(struct dvb_frontend *fe, int onoff)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline s32 dib8000_get_adc_power(struct dvb_frontend *fe, u8 mode)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline int dib8090p_get_dc_power(struct dvb_frontend *fe, u8 IQ)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline u32 dib8000_ctrl_timf(struct dvb_frontend *fe,
- uint8_t op, uint32_t timf)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return 0;
-}
-static inline int dib8000_update_pll(struct dvb_frontend *fe,
- struct dibx000_bandwidth_config *pll, u32 bw, u8 ratio)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-static inline int dib8000_set_slave_frontend(struct dvb_frontend *fe, struct dvb_frontend *fe_slave)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-int dib8000_remove_slave_frontend(struct dvb_frontend *fe)
-{
- printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
- return -ENODEV;
-}
-
-static inline struct dvb_frontend *dib8000_get_slave_frontend(struct dvb_frontend *fe, int slave_index)
+static inline int dib8000_attach(struct dib8000_ops *ops)
{
printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
return NULL;
diff --git a/drivers/media/dvb-frontends/drx39xyj/drxj.c b/drivers/media/dvb-frontends/drx39xyj/drxj.c
index 9482954fd453..3795f65564f8 100644
--- a/drivers/media/dvb-frontends/drx39xyj/drxj.c
+++ b/drivers/media/dvb-frontends/drx39xyj/drxj.c
@@ -12272,22 +12272,20 @@ struct dvb_frontend *drx39xxj_attach(struct i2c_adapter *i2c)
if (demod == NULL)
goto error;
- demod_addr = kmalloc(sizeof(struct i2c_device_addr), GFP_KERNEL);
+ demod_addr = kmemdup(&drxj_default_addr_g,
+ sizeof(struct i2c_device_addr), GFP_KERNEL);
if (demod_addr == NULL)
goto error;
- memcpy(demod_addr, &drxj_default_addr_g,
- sizeof(struct i2c_device_addr));
- demod_comm_attr = kmalloc(sizeof(struct drx_common_attr), GFP_KERNEL);
+ demod_comm_attr = kmemdup(&drxj_default_comm_attr_g,
+ sizeof(struct drx_common_attr), GFP_KERNEL);
if (demod_comm_attr == NULL)
goto error;
- memcpy(demod_comm_attr, &drxj_default_comm_attr_g,
- sizeof(struct drx_common_attr));
- demod_ext_attr = kmalloc(sizeof(struct drxj_data), GFP_KERNEL);
+ demod_ext_attr = kmemdup(&drxj_data_g, sizeof(struct drxj_data),
+ GFP_KERNEL);
if (demod_ext_attr == NULL)
goto error;
- memcpy(demod_ext_attr, &drxj_data_g, sizeof(struct drxj_data));
/* setup the state */
state->i2c = i2c;
diff --git a/drivers/media/dvb-frontends/drxd.h b/drivers/media/dvb-frontends/drxd.h
index 5f1d6b5f1685..d998e4d5a7fc 100644
--- a/drivers/media/dvb-frontends/drxd.h
+++ b/drivers/media/dvb-frontends/drxd.h
@@ -69,5 +69,4 @@ struct dvb_frontend *drxd_attach(const struct drxd_config *config,
}
#endif
-extern int drxd_config_i2c(struct dvb_frontend *, int);
#endif
diff --git a/drivers/media/dvb-frontends/drxd_hard.c b/drivers/media/dvb-frontends/drxd_hard.c
index 5b87ece69414..ae2276db77bc 100644
--- a/drivers/media/dvb-frontends/drxd_hard.c
+++ b/drivers/media/dvb-frontends/drxd_hard.c
@@ -2840,7 +2840,7 @@ static int drxd_init(struct dvb_frontend *fe)
return err;
}
-int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
+static int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
{
struct drxd_state *state = fe->demodulator_priv;
@@ -2849,7 +2849,6 @@ int drxd_config_i2c(struct dvb_frontend *fe, int onoff)
return DRX_ConfigureI2CBridge(state, onoff);
}
-EXPORT_SYMBOL(drxd_config_i2c);
static int drxd_get_tune_settings(struct dvb_frontend *fe,
struct dvb_frontend_tune_settings *sets)
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c b/drivers/media/dvb-frontends/rtl2832_sdr.c
index 093df6b6ae35..023e0f49c786 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.c
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.c
@@ -35,6 +35,10 @@
#include <linux/jiffies.h>
#include <linux/math64.h>
+static bool rtl2832_sdr_emulated_fmt;
+module_param_named(emulated_formats, rtl2832_sdr_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
#define MAX_BULK_BUFS (10)
#define BULK_BUFFER_SIZE (128 * 512)
@@ -80,15 +84,18 @@ static const struct v4l2_frequency_band bands_fm[] = {
struct rtl2832_sdr_format {
char *name;
u32 pixelformat;
+ u32 buffersize;
};
static struct rtl2832_sdr_format formats[] = {
{
- .name = "IQ U8",
- .pixelformat = V4L2_SDR_FMT_CU8,
+ .name = "Complex U8",
+ .pixelformat = V4L2_SDR_FMT_CU8,
+ .buffersize = BULK_BUFFER_SIZE,
}, {
- .name = "IQ U16LE (emulated)",
+ .name = "Complex U16LE (emulated)",
.pixelformat = V4L2_SDR_FMT_CU16LE,
+ .buffersize = BULK_BUFFER_SIZE * 2,
},
};
@@ -139,6 +146,8 @@ struct rtl2832_sdr_state {
unsigned int f_adc, f_tuner;
u32 pixelformat;
+ u32 buffersize;
+ unsigned int num_formats;
/* Controls */
struct v4l2_ctrl_handler hdl;
@@ -348,6 +357,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
/* convert u8 to u16 */
unsigned int i;
u16 *u16dst = dst;
+
for (i = 0; i < src_len; i++)
*u16dst++ = (src[i] << 8) | (src[i] >> 0);
dst_len = 2 * src_len;
@@ -359,6 +369,7 @@ static unsigned int rtl2832_sdr_convert_stream(struct rtl2832_sdr_state *s,
if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
#define MSECS 10000UL
unsigned int samples = s->sample - s->sample_measured;
+
s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
s->sample_measured = s->sample;
dev_dbg(&s->udev->dev,
@@ -560,11 +571,13 @@ static int rtl2832_sdr_alloc_urbs(struct rtl2832_sdr_state *s)
static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
{
unsigned long flags = 0;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
spin_lock_irqsave(&s->queued_bufs_lock, flags);
while (!list_empty(&s->queued_bufs)) {
struct rtl2832_sdr_frame_buf *buf;
+
buf = list_entry(s->queued_bufs.next,
struct rtl2832_sdr_frame_buf, list);
list_del(&buf->list);
@@ -577,6 +590,7 @@ static void rtl2832_sdr_cleanup_queued_bufs(struct rtl2832_sdr_state *s)
static void rtl2832_sdr_release_sec(struct dvb_frontend *fe)
{
struct rtl2832_sdr_state *s = fe->sec_priv;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->vb_queue_lock);
@@ -598,6 +612,7 @@ static int rtl2832_sdr_querycap(struct file *file, void *fh,
struct v4l2_capability *cap)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
@@ -615,14 +630,14 @@ static int rtl2832_sdr_queue_setup(struct vb2_queue *vq,
unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
/* Need at least 8 buffers */
if (vq->num_buffers + *nbuffers < 8)
*nbuffers = 8 - vq->num_buffers;
*nplanes = 1;
- /* 2 = max 16-bit sample returned */
- sizes[0] = PAGE_ALIGN(BULK_BUFFER_SIZE * 2);
+ sizes[0] = PAGE_ALIGN(s->buffersize);
dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
__func__, *nbuffers, sizes[0]);
return 0;
@@ -665,6 +680,7 @@ static int rtl2832_sdr_set_adc(struct rtl2832_sdr_state *s)
u8 buf[4], u8tmp1, u8tmp2;
u64 u64tmp;
u32 u32tmp;
+
dev_dbg(&s->udev->dev, "%s: f_adc=%u\n", __func__, s->f_adc);
if (!test_bit(POWER_ON, &s->flags))
@@ -935,7 +951,8 @@ static int rtl2832_sdr_set_tuner_freq(struct rtl2832_sdr_state *s)
/*
* bandwidth (Hz)
*/
- bandwidth_auto = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
+ bandwidth_auto = v4l2_ctrl_find(&s->hdl,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO);
bandwidth = v4l2_ctrl_find(&s->hdl, V4L2_CID_RF_TUNER_BANDWIDTH);
if (v4l2_ctrl_g_ctrl(bandwidth_auto)) {
c->bandwidth_hz = s->f_adc;
@@ -987,6 +1004,7 @@ static int rtl2832_sdr_start_streaming(struct vb2_queue *vq, unsigned int count)
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
int ret;
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
if (!s->udev)
@@ -1035,6 +1053,7 @@ err:
static void rtl2832_sdr_stop_streaming(struct vb2_queue *vq)
{
struct rtl2832_sdr_state *s = vb2_get_drv_priv(vq);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
mutex_lock(&s->v4l2_lock);
@@ -1068,6 +1087,7 @@ static int rtl2832_sdr_g_tuner(struct file *file, void *priv,
struct v4l2_tuner *v)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: index=%d type=%d\n",
__func__, v->index, v->type);
@@ -1094,6 +1114,7 @@ static int rtl2832_sdr_s_tuner(struct file *file, void *priv,
const struct v4l2_tuner *v)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
if (v->index > 1)
@@ -1105,6 +1126,7 @@ static int rtl2832_sdr_enum_freq_bands(struct file *file, void *priv,
struct v4l2_frequency_band *band)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
__func__, band->tuner, band->type, band->index);
@@ -1130,6 +1152,7 @@ static int rtl2832_sdr_g_frequency(struct file *file, void *priv,
{
struct rtl2832_sdr_state *s = video_drvdata(file);
int ret = 0;
+
dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
__func__, f->tuner, f->type);
@@ -1193,9 +1216,10 @@ static int rtl2832_sdr_enum_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
- if (f->index >= NUM_FORMATS)
+ if (f->index >= s->num_formats)
return -EINVAL;
strlcpy(f->description, formats[f->index].name, sizeof(f->description));
@@ -1208,9 +1232,12 @@ static int rtl2832_sdr_g_fmt_sdr_cap(struct file *file, void *priv,
struct v4l2_format *f)
{
struct rtl2832_sdr_state *s = video_drvdata(file);
+
dev_dbg(&s->udev->dev, "%s:\n", __func__);
f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
return 0;
@@ -1222,6 +1249,7 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
struct rtl2832_sdr_state *s = video_drvdata(file);
struct vb2_queue *q = &s->vb_queue;
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
@@ -1229,15 +1257,19 @@ static int rtl2832_sdr_s_fmt_sdr_cap(struct file *file, void *priv,
return -EBUSY;
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
+ for (i = 0; i < s->num_formats; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- s->pixelformat = f->fmt.sdr.pixelformat;
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
}
}
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1247,16 +1279,20 @@ static int rtl2832_sdr_try_fmt_sdr_cap(struct file *file, void *priv,
{
struct rtl2832_sdr_state *s = video_drvdata(file);
int i;
+
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&f->fmt.sdr.pixelformat);
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
+ for (i = 0; i < s->num_formats; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
+ }
}
f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1316,8 +1352,9 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
struct dvb_frontend *fe = s->fe;
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
+
dev_dbg(&s->udev->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
__func__, ctrl->id, ctrl->name, ctrl->val,
ctrl->minimum, ctrl->maximum, ctrl->step);
@@ -1327,14 +1364,16 @@ static int rtl2832_sdr_s_ctrl(struct v4l2_ctrl *ctrl)
/* TODO: these controls should be moved to tuner drivers */
if (s->bandwidth_auto->val) {
/* Round towards the closest legal value */
- s32 val = s->f_adc + s->bandwidth->step / 2;
+ s32 val = s->f_adc + div_u64(s->bandwidth->step, 2);
u32 offset;
- val = clamp(val, s->bandwidth->minimum, s->bandwidth->maximum);
+
+ val = clamp_t(s32, val, s->bandwidth->minimum,
+ s->bandwidth->maximum);
offset = val - s->bandwidth->minimum;
- offset = s->bandwidth->step * (offset / s->bandwidth->step);
+ offset = s->bandwidth->step *
+ div_u64(offset, s->bandwidth->step);
s->bandwidth->val = s->bandwidth->minimum + offset;
}
-
c->bandwidth_hz = s->bandwidth->val;
if (!test_bit(POWER_ON, &s->flags))
@@ -1390,7 +1429,11 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->cfg = cfg;
s->f_adc = bands_adc[0].rangelow;
s->f_tuner = bands_fm[0].rangelow;
- s->pixelformat = V4L2_SDR_FMT_CU8;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ s->num_formats = NUM_FORMATS;
+ if (rtl2832_sdr_emulated_fmt == false)
+ s->num_formats -= 1;
mutex_init(&s->v4l2_lock);
mutex_init(&s->vb_queue_lock);
@@ -1420,15 +1463,24 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
break;
case RTL2832_TUNER_R820T:
v4l2_ctrl_handler_init(&s->hdl, 2);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 0, 8000000, 100000, 0);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH,
+ 0, 8000000, 100000, 0);
v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
break;
case RTL2832_TUNER_FC0012:
case RTL2832_TUNER_FC0013:
v4l2_ctrl_handler_init(&s->hdl, 2);
- s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH_AUTO, 0, 1, 1, 1);
- s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops, V4L2_CID_RF_TUNER_BANDWIDTH, 6000000, 8000000, 1000000, 6000000);
+ s->bandwidth_auto = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH_AUTO,
+ 0, 1, 1, 1);
+ s->bandwidth = v4l2_ctrl_new_std(&s->hdl, ops,
+ V4L2_CID_RF_TUNER_BANDWIDTH,
+ 6000000, 8000000, 1000000,
+ 6000000);
v4l2_ctrl_auto_cluster(2, &s->bandwidth_auto, 0, false);
break;
default:
@@ -1448,7 +1500,6 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
s->vdev = rtl2832_sdr_template;
s->vdev.queue = &s->vb_queue;
s->vdev.queue->lock = &s->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
video_set_drvdata(&s->vdev, s);
/* Register the v4l2_device structure */
@@ -1480,6 +1531,9 @@ struct dvb_frontend *rtl2832_sdr_attach(struct dvb_frontend *fe,
dev_info(&s->i2c->dev, "%s: Realtek RTL2832 SDR attached\n",
KBUILD_MODNAME);
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
return fe;
err_unregister_v4l2_dev:
diff --git a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h b/drivers/media/dvb-frontends/rtl2832_sdr.h
index b865fadf184f..b865fadf184f 100644
--- a/drivers/staging/media/rtl2832u_sdr/rtl2832_sdr.h
+++ b/drivers/media/dvb-frontends/rtl2832_sdr.h
diff --git a/drivers/media/dvb-frontends/si2168.c b/drivers/media/dvb-frontends/si2168.c
index 2e3cdcfa0a67..41bdbc4d9f6c 100644
--- a/drivers/media/dvb-frontends/si2168.c
+++ b/drivers/media/dvb-frontends/si2168.c
@@ -95,20 +95,17 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
switch (c->delivery_system) {
case SYS_DVBT:
- cmd.args[0] = 0xa0;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\xa0\x01", 2);
cmd.wlen = 2;
cmd.rlen = 13;
break;
case SYS_DVBC_ANNEX_A:
- cmd.args[0] = 0x90;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x90\x01", 2);
cmd.wlen = 2;
cmd.rlen = 9;
break;
case SYS_DVBT2:
- cmd.args[0] = 0x50;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x50\x01", 2);
cmd.wlen = 2;
cmd.rlen = 14;
break;
@@ -144,6 +141,15 @@ static int si2168_read_status(struct dvb_frontend *fe, fe_status_t *status)
s->fe_status = *status;
+ if (*status & FE_HAS_LOCK) {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_DECIBEL;
+ c->cnr.stat[0].svalue = cmd.args[3] * 1000 / 4;
+ } else {
+ c->cnr.len = 1;
+ c->cnr.stat[0].scale = FE_SCALE_NOT_AVAILABLE;
+ }
+
dev_dbg(&s->client->dev, "%s: status=%02x args=%*ph\n",
__func__, *status, cmd.rlen, cmd.args);
@@ -243,51 +249,23 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x04\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x03\x10\x17\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x02\x10\x15\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
memcpy(cmd.args, "\x14\x00\x0c\x10\x12\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x06\x10\x24\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x0b\x10\x88\x13", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x07\x10\x00\x24", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
@@ -295,124 +273,66 @@ static int si2168_set_frontend(struct dvb_frontend *fe)
memcpy(cmd.args, "\x14\x00\x0a\x10\x00\x00", 6);
cmd.args[4] = delivery_system | bandwidth;
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x04\x10\x15\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x05\x10\xa1\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
+ /* set DVB-C symbol rate */
+ if (c->delivery_system == SYS_DVBC_ANNEX_A) {
+ memcpy(cmd.args, "\x14\x00\x02\x11", 4);
+ cmd.args[4] = (c->symbol_rate / 1000) & 0xff;
+ cmd.args[5] = ((c->symbol_rate / 1000) >> 8) & 0xff;
+ cmd.wlen = 6;
+ cmd.rlen = 4;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+ }
memcpy(cmd.args, "\x14\x00\x0f\x10\x10\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x0d\x10\xd0\x02", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x01\x10\x00\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x09\x10\xe3\x18", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
memcpy(cmd.args, "\x14\x00\x08\x10\xd7\x15", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x04\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x03\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x08\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x07\x03\x01\x02", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x06\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x05\x03\x00\x00", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x40", 6);
- cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x10\x16\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- memcpy(cmd.args, "\x14\x00\x01\x12\x00\x00", 6);
+ memcpy(cmd.args, "\x14\x00\x01\x03\x0c\x00", 6);
cmd.wlen = 6;
- cmd.rlen = 1;
+ cmd.rlen = 4;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0x85;
+ memcpy(cmd.args, "\x85", 1);
cmd.wlen = 1;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@@ -432,59 +352,75 @@ static int si2168_init(struct dvb_frontend *fe)
struct si2168 *s = fe->demodulator_priv;
int ret, len, remaining;
const struct firmware *fw = NULL;
- u8 *fw_file = SI2168_FIRMWARE;
+ u8 *fw_file;
const unsigned int i2c_wr_max = 8;
struct si2168_cmd cmd;
+ unsigned int chip_id;
dev_dbg(&s->client->dev, "%s:\n", __func__);
- cmd.args[0] = 0x13;
- cmd.wlen = 1;
- cmd.rlen = 0;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x12;
- cmd.args[2] = 0x00;
- cmd.args[3] = 0x0c;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x0d;
- cmd.args[6] = 0x16;
- cmd.args[7] = 0x00;
- cmd.args[8] = 0x00;
- cmd.args[9] = 0x00;
- cmd.args[10] = 0x00;
- cmd.args[11] = 0x00;
- cmd.args[12] = 0x00;
+ memcpy(cmd.args, "\xc0\x12\x00\x0c\x00\x0d\x16\x00\x00\x00\x00\x00\x00", 13);
cmd.wlen = 13;
cmd.rlen = 0;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x06;
- cmd.args[2] = 0x01;
- cmd.args[3] = 0x0f;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x20;
- cmd.args[6] = 0x20;
- cmd.args[7] = 0x01;
+ memcpy(cmd.args, "\xc0\x06\x01\x0f\x00\x20\x20\x01", 8);
cmd.wlen = 8;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
- cmd.args[0] = 0x02;
+ /* query chip revision */
+ memcpy(cmd.args, "\x02", 1);
cmd.wlen = 1;
cmd.rlen = 13;
ret = si2168_cmd_execute(s, &cmd);
if (ret)
goto err;
+ cmd.args[0] = 0x05;
+ cmd.args[1] = 0x00;
+ cmd.args[2] = 0xaa;
+ cmd.args[3] = 0x4d;
+ cmd.args[4] = 0x56;
+ cmd.args[5] = 0x40;
+ cmd.args[6] = 0x00;
+ cmd.args[7] = 0x00;
+ cmd.wlen = 8;
+ cmd.rlen = 1;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
+ chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+ cmd.args[4] << 0;
+
+ #define SI2168_A20 ('A' << 24 | 68 << 16 | '2' << 8 | '0' << 0)
+ #define SI2168_A30 ('A' << 24 | 68 << 16 | '3' << 8 | '0' << 0)
+ #define SI2168_B40 ('B' << 24 | 68 << 16 | '4' << 8 | '0' << 0)
+
+ switch (chip_id) {
+ case SI2168_A20:
+ fw_file = SI2168_A20_FIRMWARE;
+ break;
+ case SI2168_A30:
+ fw_file = SI2168_A30_FIRMWARE;
+ break;
+ case SI2168_B40:
+ fw_file = SI2168_B40_FIRMWARE;
+ break;
+ default:
+ dev_err(&s->client->dev,
+ "%s: unkown chip version Si21%d-%c%c%c\n",
+ KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+ cmd.args[3], cmd.args[4]);
+ ret = -EINVAL;
+ goto err;
+ }
+
/* cold state - try to download firmware */
dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
KBUILD_MODNAME, si2168_ops.info.name);
@@ -492,9 +428,22 @@ static int si2168_init(struct dvb_frontend *fe)
/* request the firmware, this will block and timeout */
ret = request_firmware(&fw, fw_file, &s->client->dev);
if (ret) {
- dev_err(&s->client->dev, "%s: firmare file '%s' not found\n",
- KBUILD_MODNAME, fw_file);
- goto err;
+ /* fallback mechanism to handle old name for Si2168 B40 fw */
+ if (chip_id == SI2168_B40) {
+ fw_file = SI2168_B40_FIRMWARE_FALLBACK;
+ ret = request_firmware(&fw, fw_file, &s->client->dev);
+ }
+
+ if (ret == 0) {
+ dev_notice(&s->client->dev,
+ "%s: please install firmware file '%s'\n",
+ KBUILD_MODNAME, SI2168_B40_FIRMWARE);
+ } else {
+ dev_err(&s->client->dev,
+ "%s: firmware file '%s' not found\n",
+ KBUILD_MODNAME, fw_file);
+ goto err;
+ }
}
dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
@@ -520,8 +469,7 @@ static int si2168_init(struct dvb_frontend *fe)
release_firmware(fw);
fw = NULL;
- cmd.args[0] = 0x01;
- cmd.args[1] = 0x01;
+ memcpy(cmd.args, "\x01\x01", 2);
cmd.wlen = 2;
cmd.rlen = 1;
ret = si2168_cmd_execute(s, &cmd);
@@ -545,12 +493,24 @@ err:
static int si2168_sleep(struct dvb_frontend *fe)
{
struct si2168 *s = fe->demodulator_priv;
+ int ret;
+ struct si2168_cmd cmd;
dev_dbg(&s->client->dev, "%s:\n", __func__);
s->active = false;
+ memcpy(cmd.args, "\x13", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 0;
+ ret = si2168_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
return 0;
+err:
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2168_get_tune_settings(struct dvb_frontend *fe,
@@ -660,7 +620,6 @@ static int si2168_probe(struct i2c_client *client,
struct si2168_config *config = client->dev.platform_data;
struct si2168 *s;
int ret;
- struct si2168_cmd cmd;
dev_dbg(&client->dev, "%s:\n", __func__);
@@ -674,18 +633,13 @@ static int si2168_probe(struct i2c_client *client,
s->client = client;
mutex_init(&s->i2c_mutex);
- /* check if the demod is there */
- cmd.wlen = 0;
- cmd.rlen = 1;
- ret = si2168_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
/* create mux i2c adapter for tuner */
s->adapter = i2c_add_mux_adapter(client->adapter, &client->dev, s,
0, 0, 0, si2168_select, si2168_deselect);
- if (s->adapter == NULL)
+ if (s->adapter == NULL) {
+ ret = -ENODEV;
goto err;
+ }
/* create dvb_frontend */
memcpy(&s->fe.ops, &si2168_ops, sizeof(struct dvb_frontend_ops));
@@ -743,4 +697,6 @@ module_i2c_driver(si2168_driver);
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_DESCRIPTION("Silicon Labs Si2168 DVB-T/T2/C demodulator driver");
MODULE_LICENSE("GPL");
-MODULE_FIRMWARE(SI2168_FIRMWARE);
+MODULE_FIRMWARE(SI2168_A20_FIRMWARE);
+MODULE_FIRMWARE(SI2168_A30_FIRMWARE);
+MODULE_FIRMWARE(SI2168_B40_FIRMWARE);
diff --git a/drivers/media/dvb-frontends/si2168_priv.h b/drivers/media/dvb-frontends/si2168_priv.h
index 53f7f06ae343..ebbf502ec313 100644
--- a/drivers/media/dvb-frontends/si2168_priv.h
+++ b/drivers/media/dvb-frontends/si2168_priv.h
@@ -22,7 +22,10 @@
#include <linux/firmware.h>
#include <linux/i2c-mux.h>
-#define SI2168_FIRMWARE "dvb-demod-si2168-02.fw"
+#define SI2168_A20_FIRMWARE "dvb-demod-si2168-a20-01.fw"
+#define SI2168_A30_FIRMWARE "dvb-demod-si2168-a30-01.fw"
+#define SI2168_B40_FIRMWARE "dvb-demod-si2168-b40-01.fw"
+#define SI2168_B40_FIRMWARE_FALLBACK "dvb-demod-si2168-02.fw"
/* state struct */
struct si2168 {
@@ -36,9 +39,9 @@ struct si2168 {
};
/* firmare command struct */
-#define SI2157_ARGLEN 30
+#define SI2168_ARGLEN 30
struct si2168_cmd {
- u8 args[SI2157_ARGLEN];
+ u8 args[SI2168_ARGLEN];
unsigned wlen;
unsigned rlen;
};
diff --git a/drivers/media/dvb-frontends/tda18271c2dd_maps.h b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
index b87661b9df14..f3bca5c237d7 100644
--- a/drivers/media/dvb-frontends/tda18271c2dd_maps.h
+++ b/drivers/media/dvb-frontends/tda18271c2dd_maps.h
@@ -5,7 +5,7 @@ enum HF_S {
HF_DVBC_8MHZ, HF_DVBC
};
-struct SStandardParam m_StandardTable[] = {
+static struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_None */
{ 6000000, 7000000, 0x1D, 0x2C }, /* HF_B, */
{ 6900000, 8000000, 0x1E, 0x2C }, /* HF_DK, */
@@ -27,7 +27,7 @@ struct SStandardParam m_StandardTable[] = {
{ 0, 0, 0x00, 0x00 }, /* HF_DVBC (Unused) */
};
-struct SMap m_BP_Filter_Map[] = {
+static struct SMap m_BP_Filter_Map[] = {
{ 62000000, 0x00 },
{ 84000000, 0x01 },
{ 100000000, 0x02 },
@@ -799,14 +799,14 @@ static struct SRFBandMap m_RF_Band_Map[7] = {
{ 865000000, 489500000, 697500000, 842000000},
};
-u8 m_Thermometer_Map_1[16] = {
+static u8 m_Thermometer_Map_1[16] = {
60, 62, 66, 64,
74, 72, 68, 70,
90, 88, 84, 86,
76, 78, 82, 80,
};
-u8 m_Thermometer_Map_2[16] = {
+static u8 m_Thermometer_Map_2[16] = {
92, 94, 98, 96,
106, 104, 100, 102,
122, 120, 116, 118,
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 441053be7f55..f40b4cf6107a 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -551,6 +551,7 @@ config VIDEO_MT9V032
tristate "Micron MT9V032 sensor support"
depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on MEDIA_CAMERA_SUPPORT
+ select REGMAP_I2C
---help---
This is a Video4Linux2 sensor-level driver for the Micron
MT9V032 752x480 CMOS sensor.
diff --git a/drivers/media/i2c/adv7180.c b/drivers/media/i2c/adv7180.c
index ac1cdbe251a3..821178dcb08e 100644
--- a/drivers/media/i2c/adv7180.c
+++ b/drivers/media/i2c/adv7180.c
@@ -663,7 +663,6 @@ static int adv7180_remove(struct i2c_client *client)
if (state->irq > 0)
free_irq(client->irq, state);
- v4l2_device_unregister_subdev(sd);
adv7180_exit_controls(state);
mutex_destroy(&state->mutex);
return 0;
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
index 1778d320272e..d4fa213ba74a 100644
--- a/drivers/media/i2c/adv7604.c
+++ b/drivers/media/i2c/adv7604.c
@@ -2588,8 +2588,11 @@ static const struct adv7604_reg_seq adv7604_recommended_settings_hdmi[] = {
};
static const struct adv7604_reg_seq adv7611_recommended_settings_hdmi[] = {
+ /* ADV7611 Register Settings Recommendations Rev 1.5, May 2014 */
{ ADV7604_REG(ADV7604_PAGE_CP, 0x6c), 0x00 },
- { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x0c },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x9b), 0x03 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x6f), 0x08 },
+ { ADV7604_REG(ADV7604_PAGE_HDMI, 0x85), 0x1f },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x87), 0x70 },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x57), 0xda },
{ ADV7604_REG(ADV7604_PAGE_HDMI, 0x58), 0x01 },
diff --git a/drivers/media/i2c/mt9v032.c b/drivers/media/i2c/mt9v032.c
index 40172b8d8ea2..d044bce312e0 100644
--- a/drivers/media/i2c/mt9v032.c
+++ b/drivers/media/i2c/mt9v032.c
@@ -1,5 +1,5 @@
/*
- * Driver for MT9V032 CMOS Image Sensor from Micron
+ * Driver for MT9V022, MT9V024, MT9V032, and MT9V034 CMOS Image Sensors
*
* Copyright (C) 2010, Laurent Pinchart <laurent.pinchart@ideasonboard.com>
*
@@ -17,6 +17,7 @@
#include <linux/i2c.h>
#include <linux/log2.h>
#include <linux/mutex.h>
+#include <linux/regmap.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include <linux/v4l2-mediabus.h>
@@ -87,6 +88,7 @@
#define MT9V032_READ_MODE_COLUMN_FLIP (1 << 5)
#define MT9V032_READ_MODE_DARK_COLUMNS (1 << 6)
#define MT9V032_READ_MODE_DARK_ROWS (1 << 7)
+#define MT9V032_READ_MODE_RESERVED 0x0300
#define MT9V032_PIXEL_OPERATION_MODE 0x0f
#define MT9V034_PIXEL_OPERATION_MODE_HDR (1 << 0)
#define MT9V034_PIXEL_OPERATION_MODE_COLOR (1 << 1)
@@ -133,8 +135,12 @@
#define MT9V032_THERMAL_INFO 0xc1
enum mt9v032_model {
- MT9V032_MODEL_V032_COLOR,
- MT9V032_MODEL_V032_MONO,
+ MT9V032_MODEL_V022_COLOR, /* MT9V022IX7ATC */
+ MT9V032_MODEL_V022_MONO, /* MT9V022IX7ATM */
+ MT9V032_MODEL_V024_COLOR, /* MT9V024IA7XTC */
+ MT9V032_MODEL_V024_MONO, /* MT9V024IA7XTM */
+ MT9V032_MODEL_V032_COLOR, /* MT9V032C12STM */
+ MT9V032_MODEL_V032_MONO, /* MT9V032C12STC */
MT9V032_MODEL_V034_COLOR,
MT9V032_MODEL_V034_MONO,
};
@@ -160,14 +166,14 @@ struct mt9v032_model_info {
};
static const struct mt9v032_model_version mt9v032_versions[] = {
- { MT9V032_CHIP_ID_REV1, "MT9V032 rev1/2" },
- { MT9V032_CHIP_ID_REV3, "MT9V032 rev3" },
- { MT9V034_CHIP_ID_REV1, "MT9V034 rev1" },
+ { MT9V032_CHIP_ID_REV1, "MT9V022/MT9V032 rev1/2" },
+ { MT9V032_CHIP_ID_REV3, "MT9V022/MT9V032 rev3" },
+ { MT9V034_CHIP_ID_REV1, "MT9V024/MT9V034 rev1" },
};
static const struct mt9v032_model_data mt9v032_model_data[] = {
{
- /* MT9V032 revisions 1/2/3 */
+ /* MT9V022, MT9V032 revisions 1/2/3 */
.min_row_time = 660,
.min_hblank = MT9V032_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V032_VERTICAL_BLANKING_MIN,
@@ -176,7 +182,7 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
.max_shutter = MT9V032_TOTAL_SHUTTER_WIDTH_MAX,
.pclk_reg = MT9V032_PIXEL_CLOCK,
}, {
- /* MT9V034 */
+ /* MT9V024, MT9V034 */
.min_row_time = 690,
.min_hblank = MT9V034_HORIZONTAL_BLANKING_MIN,
.min_vblank = MT9V034_VERTICAL_BLANKING_MIN,
@@ -188,6 +194,22 @@ static const struct mt9v032_model_data mt9v032_model_data[] = {
};
static const struct mt9v032_model_info mt9v032_models[] = {
+ [MT9V032_MODEL_V022_COLOR] = {
+ .data = &mt9v032_model_data[0],
+ .color = true,
+ },
+ [MT9V032_MODEL_V022_MONO] = {
+ .data = &mt9v032_model_data[0],
+ .color = false,
+ },
+ [MT9V032_MODEL_V024_COLOR] = {
+ .data = &mt9v032_model_data[1],
+ .color = true,
+ },
+ [MT9V032_MODEL_V024_MONO] = {
+ .data = &mt9v032_model_data[1],
+ .color = false,
+ },
[MT9V032_MODEL_V032_COLOR] = {
.data = &mt9v032_model_data[0],
.color = true,
@@ -224,6 +246,7 @@ struct mt9v032 {
struct mutex power_lock;
int power_count;
+ struct regmap *regmap;
struct clk *clk;
struct mt9v032_platform_data *pdata;
@@ -231,7 +254,6 @@ struct mt9v032 {
const struct mt9v032_model_version *version;
u32 sysclk;
- u16 chip_control;
u16 aec_agc;
u16 hblank;
struct {
@@ -245,40 +267,10 @@ static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
return container_of(sd, struct mt9v032, subdev);
}
-static int mt9v032_read(struct i2c_client *client, const u8 reg)
-{
- s32 data = i2c_smbus_read_word_swapped(client, reg);
- dev_dbg(&client->dev, "%s: read 0x%04x from 0x%02x\n", __func__,
- data, reg);
- return data;
-}
-
-static int mt9v032_write(struct i2c_client *client, const u8 reg,
- const u16 data)
-{
- dev_dbg(&client->dev, "%s: writing 0x%04x to 0x%02x\n", __func__,
- data, reg);
- return i2c_smbus_write_word_swapped(client, reg, data);
-}
-
-static int mt9v032_set_chip_control(struct mt9v032 *mt9v032, u16 clear, u16 set)
-{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
- u16 value = (mt9v032->chip_control & ~clear) | set;
- int ret;
-
- ret = mt9v032_write(client, MT9V032_CHIP_CONTROL, value);
- if (ret < 0)
- return ret;
-
- mt9v032->chip_control = value;
- return 0;
-}
-
static int
mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
u16 value = mt9v032->aec_agc;
int ret;
@@ -287,7 +279,7 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
else
value &= ~which;
- ret = mt9v032_write(client, MT9V032_AEC_AGC_ENABLE, value);
+ ret = regmap_write(map, MT9V032_AEC_AGC_ENABLE, value);
if (ret < 0)
return ret;
@@ -298,23 +290,23 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
static int
mt9v032_update_hblank(struct mt9v032 *mt9v032)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
struct v4l2_rect *crop = &mt9v032->crop;
unsigned int min_hblank = mt9v032->model->data->min_hblank;
unsigned int hblank;
if (mt9v032->version->version == MT9V034_CHIP_ID_REV1)
min_hblank += (mt9v032->hratio - 1) * 10;
- min_hblank = max_t(unsigned int, (int)mt9v032->model->data->min_row_time - crop->width,
- (int)min_hblank);
+ min_hblank = max_t(int, mt9v032->model->data->min_row_time - crop->width,
+ min_hblank);
hblank = max_t(unsigned int, mt9v032->hblank, min_hblank);
- return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING, hblank);
+ return regmap_write(mt9v032->regmap, MT9V032_HORIZONTAL_BLANKING,
+ hblank);
}
static int mt9v032_power_on(struct mt9v032 *mt9v032)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
int ret;
ret = clk_set_rate(mt9v032->clk, mt9v032->sysclk);
@@ -328,15 +320,15 @@ static int mt9v032_power_on(struct mt9v032 *mt9v032)
udelay(1);
/* Reset the chip and stop data read out */
- ret = mt9v032_write(client, MT9V032_RESET, 1);
+ ret = regmap_write(map, MT9V032_RESET, 1);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_RESET, 0);
+ ret = regmap_write(map, MT9V032_RESET, 0);
if (ret < 0)
return ret;
- return mt9v032_write(client, MT9V032_CHIP_CONTROL, 0);
+ return regmap_write(map, MT9V032_CHIP_CONTROL, 0);
}
static void mt9v032_power_off(struct mt9v032 *mt9v032)
@@ -346,7 +338,7 @@ static void mt9v032_power_off(struct mt9v032 *mt9v032)
static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
{
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
int ret;
if (!on) {
@@ -360,14 +352,14 @@ static int __mt9v032_set_power(struct mt9v032 *mt9v032, bool on)
/* Configure the pixel clock polarity */
if (mt9v032->pdata && mt9v032->pdata->clk_pol) {
- ret = mt9v032_write(client, mt9v032->model->data->pclk_reg,
+ ret = regmap_write(map, mt9v032->model->data->pclk_reg,
MT9V032_PIXEL_CLOCK_INV_PXL_CLK);
if (ret < 0)
return ret;
}
/* Disable the noise correction algorithm and restore the controls. */
- ret = mt9v032_write(client, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
+ ret = regmap_write(map, MT9V032_ROW_NOISE_CORR_CONTROL, 0);
if (ret < 0)
return ret;
@@ -411,38 +403,39 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
const u16 mode = MT9V032_CHIP_CONTROL_MASTER_MODE
| MT9V032_CHIP_CONTROL_DOUT_ENABLE
| MT9V032_CHIP_CONTROL_SEQUENTIAL;
- struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
struct v4l2_rect *crop = &mt9v032->crop;
+ struct regmap *map = mt9v032->regmap;
unsigned int hbin;
unsigned int vbin;
int ret;
if (!enable)
- return mt9v032_set_chip_control(mt9v032, mode, 0);
+ return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, 0);
/* Configure the window size and row/column bin */
hbin = fls(mt9v032->hratio) - 1;
vbin = fls(mt9v032->vratio) - 1;
- ret = mt9v032_write(client, MT9V032_READ_MODE,
- hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
- vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
+ ret = regmap_update_bits(map, MT9V032_READ_MODE,
+ ~MT9V032_READ_MODE_RESERVED,
+ hbin << MT9V032_READ_MODE_COLUMN_BIN_SHIFT |
+ vbin << MT9V032_READ_MODE_ROW_BIN_SHIFT);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_COLUMN_START, crop->left);
+ ret = regmap_write(map, MT9V032_COLUMN_START, crop->left);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_ROW_START, crop->top);
+ ret = regmap_write(map, MT9V032_ROW_START, crop->top);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_WINDOW_WIDTH, crop->width);
+ ret = regmap_write(map, MT9V032_WINDOW_WIDTH, crop->width);
if (ret < 0)
return ret;
- ret = mt9v032_write(client, MT9V032_WINDOW_HEIGHT, crop->height);
+ ret = regmap_write(map, MT9V032_WINDOW_HEIGHT, crop->height);
if (ret < 0)
return ret;
@@ -451,7 +444,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
return ret;
/* Switch to master "normal" mode */
- return mt9v032_set_chip_control(mt9v032, 0, mode);
+ return regmap_update_bits(map, MT9V032_CHIP_CONTROL, mode, mode);
}
static int mt9v032_enum_mbus_code(struct v4l2_subdev *subdev,
@@ -633,7 +626,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct mt9v032 *mt9v032 =
container_of(ctrl->handler, struct mt9v032, ctrls);
- struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+ struct regmap *map = mt9v032->regmap;
u32 freq;
u16 data;
@@ -643,23 +636,23 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
case V4L2_CID_GAIN:
- return mt9v032_write(client, MT9V032_ANALOG_GAIN, ctrl->val);
+ return regmap_write(map, MT9V032_ANALOG_GAIN, ctrl->val);
case V4L2_CID_EXPOSURE_AUTO:
return mt9v032_update_aec_agc(mt9v032, MT9V032_AEC_ENABLE,
!ctrl->val);
case V4L2_CID_EXPOSURE:
- return mt9v032_write(client, MT9V032_TOTAL_SHUTTER_WIDTH,
- ctrl->val);
+ return regmap_write(map, MT9V032_TOTAL_SHUTTER_WIDTH,
+ ctrl->val);
case V4L2_CID_HBLANK:
mt9v032->hblank = ctrl->val;
return mt9v032_update_hblank(mt9v032);
case V4L2_CID_VBLANK:
- return mt9v032_write(client, MT9V032_VERTICAL_BLANKING,
- ctrl->val);
+ return regmap_write(map, MT9V032_VERTICAL_BLANKING,
+ ctrl->val);
case V4L2_CID_PIXEL_RATE:
case V4L2_CID_LINK_FREQ:
@@ -667,7 +660,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
break;
freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
- mt9v032->pixel_rate->val64 = freq;
+ *mt9v032->pixel_rate->p_new.p_s64 = freq;
mt9v032->sysclk = freq;
break;
@@ -696,7 +689,7 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
| MT9V032_TEST_PATTERN_FLIP;
break;
}
- return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
+ return regmap_write(map, MT9V032_TEST_PATTERN, data);
}
return 0;
@@ -764,7 +757,7 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
struct i2c_client *client = v4l2_get_subdevdata(subdev);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
unsigned int i;
- s32 version;
+ u32 version;
int ret;
dev_info(&client->dev, "Probing MT9V032 at address 0x%02x\n",
@@ -777,10 +770,10 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
}
/* Read and check the sensor version */
- version = mt9v032_read(client, MT9V032_CHIP_VERSION);
- if (version < 0) {
+ ret = regmap_read(mt9v032->regmap, MT9V032_CHIP_VERSION, &version);
+ if (ret < 0) {
dev_err(&client->dev, "Failed reading chip version\n");
- return version;
+ return ret;
}
for (i = 0; i < ARRAY_SIZE(mt9v032_versions); ++i) {
@@ -867,6 +860,13 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
.close = mt9v032_close,
};
+static const struct regmap_config mt9v032_regmap_config = {
+ .reg_bits = 8,
+ .val_bits = 16,
+ .max_register = 0xff,
+ .cache_type = REGCACHE_RBTREE,
+};
+
/* -----------------------------------------------------------------------------
* Driver initialization and probing
*/
@@ -890,6 +890,10 @@ static int mt9v032_probe(struct i2c_client *client,
if (!mt9v032)
return -ENOMEM;
+ mt9v032->regmap = devm_regmap_init_i2c(client, &mt9v032_regmap_config);
+ if (IS_ERR(mt9v032->regmap))
+ return PTR_ERR(mt9v032->regmap);
+
mt9v032->clk = devm_clk_get(&client->dev, NULL);
if (IS_ERR(mt9v032->clk))
return PTR_ERR(mt9v032->clk);
@@ -931,7 +935,7 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pixel_rate =
v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (pdata && pdata->link_freqs) {
unsigned int def = 0;
@@ -984,10 +988,19 @@ static int mt9v032_probe(struct i2c_client *client,
mt9v032->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_init(&mt9v032->subdev.entity, 1, &mt9v032->pad, 0);
+ if (ret < 0)
+ goto err;
+ mt9v032->subdev.dev = &client->dev;
+ ret = v4l2_async_register_subdev(&mt9v032->subdev);
if (ret < 0)
- v4l2_ctrl_handler_free(&mt9v032->ctrls);
+ goto err;
+ return 0;
+
+err:
+ media_entity_cleanup(&mt9v032->subdev.entity);
+ v4l2_ctrl_handler_free(&mt9v032->ctrls);
return ret;
}
@@ -996,6 +1009,7 @@ static int mt9v032_remove(struct i2c_client *client)
struct v4l2_subdev *subdev = i2c_get_clientdata(client);
struct mt9v032 *mt9v032 = to_mt9v032(subdev);
+ v4l2_async_unregister_subdev(subdev);
v4l2_ctrl_handler_free(&mt9v032->ctrls);
v4l2_device_unregister_subdev(subdev);
media_entity_cleanup(&subdev->entity);
@@ -1004,6 +1018,10 @@ static int mt9v032_remove(struct i2c_client *client)
}
static const struct i2c_device_id mt9v032_id[] = {
+ { "mt9v022", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_COLOR] },
+ { "mt9v022m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V022_MONO] },
+ { "mt9v024", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_COLOR] },
+ { "mt9v024m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V024_MONO] },
{ "mt9v032", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_COLOR] },
{ "mt9v032m", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V032_MONO] },
{ "mt9v034", (kernel_ulong_t)&mt9v032_models[MT9V032_MODEL_V034_COLOR] },
diff --git a/drivers/media/i2c/noon010pc30.c b/drivers/media/i2c/noon010pc30.c
index 271d0b7967a6..7eae48766e2b 100644
--- a/drivers/media/i2c/noon010pc30.c
+++ b/drivers/media/i2c/noon010pc30.c
@@ -554,6 +554,7 @@ static int noon010_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
nf = noon010_try_fmt(sd, &fmt->format);
noon010_try_frame_size(&fmt->format, &size);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+ fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
index 2750de634270..1fcc76fd1bbf 100644
--- a/drivers/media/i2c/s5k4ecgx.c
+++ b/drivers/media/i2c/s5k4ecgx.c
@@ -594,6 +594,7 @@ static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
pf = s5k4ecgx_try_fmt(sd, &fmt->format);
s5k4ecgx_try_frame_size(&fmt->format, &fsize);
fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+ fmt->format.field = V4L2_FIELD_NONE;
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
if (fh) {
diff --git a/drivers/media/i2c/s5k5baf.c b/drivers/media/i2c/s5k5baf.c
index 2d768ef67cc5..564f05f2c9ef 100644
--- a/drivers/media/i2c/s5k5baf.c
+++ b/drivers/media/i2c/s5k5baf.c
@@ -1313,6 +1313,8 @@ static int s5k5baf_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
const struct s5k5baf_pixfmt *pixfmt;
int ret = 0;
+ mf->field = V4L2_FIELD_NONE;
+
if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
*v4l2_subdev_get_try_format(fh, fmt->pad) = *mf;
return 0;
diff --git a/drivers/media/i2c/s5k6a3.c b/drivers/media/i2c/s5k6a3.c
index 7bc2271ca009..c11a40850ed1 100644
--- a/drivers/media/i2c/s5k6a3.c
+++ b/drivers/media/i2c/s5k6a3.c
@@ -115,6 +115,7 @@ static void s5k6a3_try_format(struct v4l2_mbus_framefmt *mf)
fmt = find_sensor_format(mf);
mf->code = fmt->code;
+ mf->field = V4L2_FIELD_NONE;
v4l_bound_align_image(&mf->width, S5K6A3_SENSOR_MIN_WIDTH,
S5K6A3_SENSOR_MAX_WIDTH, 0,
&mf->height, S5K6A3_SENSOR_MIN_HEIGHT,
diff --git a/drivers/media/i2c/smiapp/smiapp-core.c b/drivers/media/i2c/smiapp/smiapp-core.c
index 06fb03291d59..1eaf975d3612 100644
--- a/drivers/media/i2c/smiapp/smiapp-core.c
+++ b/drivers/media/i2c/smiapp/smiapp-core.c
@@ -297,8 +297,8 @@ static int smiapp_pll_update(struct smiapp_sensor *sensor)
if (rval < 0)
return rval;
- sensor->pixel_rate_parray->cur.val64 = pll->vt_pix_clk_freq_hz;
- sensor->pixel_rate_csi->cur.val64 = pll->pixel_rate_csi;
+ *sensor->pixel_rate_parray->p_cur.p_s64 = pll->vt_pix_clk_freq_hz;
+ *sensor->pixel_rate_csi->p_cur.p_s64 = pll->pixel_rate_csi;
return 0;
}
@@ -533,7 +533,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_parray = v4l2_ctrl_new_std(
&sensor->pixel_array->ctrl_handler, &smiapp_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->pixel_array->ctrl_handler.error) {
dev_err(&client->dev,
@@ -562,7 +562,7 @@ static int smiapp_init_controls(struct smiapp_sensor *sensor)
sensor->pixel_rate_csi = v4l2_ctrl_new_std(
&sensor->src->ctrl_handler, &smiapp_ctrl_ops,
- V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+ V4L2_CID_PIXEL_RATE, 1, INT_MAX, 1, 1);
if (sensor->src->ctrl_handler.error) {
dev_err(&client->dev,
@@ -1554,6 +1554,7 @@ static int __smiapp_get_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width = r->width;
fmt->format.height = r->height;
+ fmt->format.field = V4L2_FIELD_NONE;
}
return 0;
@@ -1687,6 +1688,7 @@ static int smiapp_set_format(struct v4l2_subdev *subdev,
fmt->format.code = __smiapp_get_mbus_code(subdev, fmt->pad);
fmt->format.width &= ~1;
fmt->format.height &= ~1;
+ fmt->format.field = V4L2_FIELD_NONE;
fmt->format.width =
clamp(fmt->format.width,
@@ -2544,9 +2546,9 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
}
snprintf(this->sd.name,
- sizeof(this->sd.name), "%s %d-%4.4x %s",
- sensor->minfo.name, i2c_adapter_id(client->adapter),
- client->addr, _this->name);
+ sizeof(this->sd.name), "%s %s %d-%4.4x",
+ sensor->minfo.name, _this->name,
+ i2c_adapter_id(client->adapter), client->addr);
this->sink_fmt.width =
sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
@@ -2674,6 +2676,7 @@ static int smiapp_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
try_fmt->width = sensor->limits[SMIAPP_LIMIT_X_ADDR_MAX] + 1;
try_fmt->height = sensor->limits[SMIAPP_LIMIT_Y_ADDR_MAX] + 1;
try_fmt->code = mbus_code;
+ try_fmt->field = V4L2_FIELD_NONE;
try_crop->top = 0;
try_crop->left = 0;
diff --git a/drivers/media/i2c/soc_camera/mt9m001.c b/drivers/media/i2c/soc_camera/mt9m001.c
index df97033fa6ef..dbd8c142d6ef 100644
--- a/drivers/media/i2c/soc_camera/mt9m001.c
+++ b/drivers/media/i2c/soc_camera/mt9m001.c
@@ -403,7 +403,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
- data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+ data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9M001_GLOBAL_GAIN, data);
@@ -413,7 +413,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
/* Pack it into 1.125..15 variable step, register values 9..67 */
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
- unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+ unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
111 + range / 2) / range + 9;
if (gain <= 32)
@@ -434,7 +434,7 @@ static int mt9m001_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned long range = exp->maximum - exp->minimum;
- unsigned long shutter = ((exp->val - exp->minimum) * 1048 +
+ unsigned long shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
dev_dbg(&client->dev,
diff --git a/drivers/media/i2c/soc_camera/mt9t031.c b/drivers/media/i2c/soc_camera/mt9t031.c
index ee7bb0ffcecb..f8358c4071a9 100644
--- a/drivers/media/i2c/soc_camera/mt9t031.c
+++ b/drivers/media/i2c/soc_camera/mt9t031.c
@@ -474,7 +474,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
if (ctrl->val <= ctrl->default_value) {
/* Pack it into 0..1 step 0.125, register values 0..8 */
unsigned long range = ctrl->default_value - ctrl->minimum;
- data = ((ctrl->val - ctrl->minimum) * 8 + range / 2) / range;
+ data = ((ctrl->val - (s32)ctrl->minimum) * 8 + range / 2) / range;
dev_dbg(&client->dev, "Setting gain %d\n", data);
data = reg_write(client, MT9T031_GLOBAL_GAIN, data);
@@ -485,7 +485,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
/* We assume qctrl->maximum - qctrl->default_value - 1 > 0 */
unsigned long range = ctrl->maximum - ctrl->default_value - 1;
/* calculated gain: map 65..127 to 9..1024 step 0.125 */
- unsigned long gain = ((ctrl->val - ctrl->default_value - 1) *
+ unsigned long gain = ((ctrl->val - (s32)ctrl->default_value - 1) *
1015 + range / 2) / range + 9;
if (gain <= 32) /* calculated gain 9..32 -> 9..32 */
@@ -507,7 +507,7 @@ static int mt9t031_s_ctrl(struct v4l2_ctrl *ctrl)
case V4L2_CID_EXPOSURE_AUTO:
if (ctrl->val == V4L2_EXPOSURE_MANUAL) {
unsigned int range = exp->maximum - exp->minimum;
- unsigned int shutter = ((exp->val - exp->minimum) * 1048 +
+ unsigned int shutter = ((exp->val - (s32)exp->minimum) * 1048 +
range / 2) / range + 1;
u32 old;
diff --git a/drivers/media/i2c/soc_camera/mt9v022.c b/drivers/media/i2c/soc_camera/mt9v022.c
index f9f95f815b1a..99022c8d76eb 100644
--- a/drivers/media/i2c/soc_camera/mt9v022.c
+++ b/drivers/media/i2c/soc_camera/mt9v022.c
@@ -583,7 +583,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
/* mt9v022 has minimum == default */
unsigned long range = gain->maximum - gain->minimum;
/* Valid values 16 to 64, 32 to 64 must be even. */
- unsigned long gain_val = ((gain->val - gain->minimum) *
+ unsigned long gain_val = ((gain->val - (s32)gain->minimum) *
48 + range / 2) / range + 16;
if (gain_val >= 32)
@@ -608,7 +608,7 @@ static int mt9v022_s_ctrl(struct v4l2_ctrl *ctrl)
} else {
struct v4l2_ctrl *exp = mt9v022->exposure;
unsigned long range = exp->maximum - exp->minimum;
- unsigned long shutter = ((exp->val - exp->minimum) *
+ unsigned long shutter = ((exp->val - (s32)exp->minimum) *
479 + range / 2) / range + 1;
/*
diff --git a/drivers/media/media-device.c b/drivers/media/media-device.c
index 88b97c9e64ac..73a432934bd8 100644
--- a/drivers/media/media-device.c
+++ b/drivers/media/media-device.c
@@ -106,8 +106,6 @@ static long media_device_enum_entities(struct media_device *mdev,
if (ent->name) {
strncpy(u_ent.name, ent->name, sizeof(u_ent.name));
u_ent.name[sizeof(u_ent.name) - 1] = '\0';
- } else {
- memset(u_ent.name, 0, sizeof(u_ent.name));
}
u_ent.type = ent->type;
u_ent.revision = ent->revision;
diff --git a/drivers/media/parport/bw-qcam.c b/drivers/media/parport/bw-qcam.c
index 416507a83668..67b9da1dc43f 100644
--- a/drivers/media/parport/bw-qcam.c
+++ b/drivers/media/parport/bw-qcam.c
@@ -759,7 +759,6 @@ static int qcam_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
- pix->priv = 0;
return 0;
}
@@ -785,7 +784,6 @@ static int qcam_try_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format
pix->sizeimage = pix->width * pix->height;
/* Just a guess */
pix->colorspace = V4L2_COLORSPACE_SRGB;
- pix->priv = 0;
return 0;
}
@@ -990,7 +988,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.fops = &qcam_fops;
qcam->vdev.lock = &qcam->lock;
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
- set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
qcam->vdev.release = video_device_release_empty;
video_set_drvdata(&qcam->vdev, qcam);
diff --git a/drivers/media/parport/c-qcam.c b/drivers/media/parport/c-qcam.c
index ec51e1f12e82..b9010bd3ed3e 100644
--- a/drivers/media/parport/c-qcam.c
+++ b/drivers/media/parport/c-qcam.c
@@ -761,7 +761,6 @@ static struct qcam *qcam_init(struct parport *port)
qcam->vdev.ioctl_ops = &qcam_ioctl_ops;
qcam->vdev.release = video_device_release_empty;
qcam->vdev.ctrl_handler = &qcam->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &qcam->vdev.flags);
video_set_drvdata(&qcam->vdev, qcam);
mutex_init(&qcam->lock);
diff --git a/drivers/media/parport/pms.c b/drivers/media/parport/pms.c
index 66c957a02ba7..9bc105b3db1b 100644
--- a/drivers/media/parport/pms.c
+++ b/drivers/media/parport/pms.c
@@ -1091,7 +1091,6 @@ static int pms_probe(struct device *pdev, unsigned int card)
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
dev->vdev.tvnorms = V4L2_STD_NTSC | V4L2_STD_PAL | V4L2_STD_SECAM;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
dev->std = V4L2_STD_NTSC_M;
dev->height = 240;
diff --git a/drivers/media/parport/w9966.c b/drivers/media/parport/w9966.c
index db2a6003a1c3..f7502f3a6a3c 100644
--- a/drivers/media/parport/w9966.c
+++ b/drivers/media/parport/w9966.c
@@ -883,7 +883,6 @@ static int w9966_init(struct w9966 *cam, struct parport *port)
cam->vdev.ioctl_ops = &w9966_ioctl_ops;
cam->vdev.release = video_device_release_empty;
cam->vdev.ctrl_handler = &cam->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
video_set_drvdata(&cam->vdev, cam);
mutex_init(&cam->lock);
diff --git a/drivers/media/pci/bt8xx/bttv-driver.c b/drivers/media/pci/bt8xx/bttv-driver.c
index da780f42b121..970e542d3a51 100644
--- a/drivers/media/pci/bt8xx/bttv-driver.c
+++ b/drivers/media/pci/bt8xx/bttv-driver.c
@@ -3886,7 +3886,6 @@ static struct video_device *vdev_init(struct bttv *btv,
vfd->v4l2_dev = &btv->c.v4l2_dev;
vfd->release = video_device_release;
vfd->debug = bttv_debug;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, btv);
snprintf(vfd->name, sizeof(vfd->name), "BT%d%s %s (%s)",
btv->id, (btv->id==848 && btv->revision==0x12) ? "A" : "",
diff --git a/drivers/media/pci/cx18/cx18-alsa.h b/drivers/media/pci/cx18/cx18-alsa.h
index 447da374c9e8..2718be28bf5f 100644
--- a/drivers/media/pci/cx18/cx18-alsa.h
+++ b/drivers/media/pci/cx18/cx18-alsa.h
@@ -49,7 +49,6 @@ static inline void snd_cx18_unlock(struct snd_cx18_card *cxsc)
}
#define CX18_ALSA_DBGFLG_WARN (1 << 0)
-#define CX18_ALSA_DBGFLG_WARN (1 << 0)
#define CX18_ALSA_DBGFLG_INFO (1 << 1)
#define CX18_ALSA_DEBUG(x, type, fmt, args...) \
diff --git a/drivers/media/pci/cx18/cx18-ioctl.c b/drivers/media/pci/cx18/cx18-ioctl.c
index fefb2cd35838..6f2b59042b73 100644
--- a/drivers/media/pci/cx18/cx18-ioctl.c
+++ b/drivers/media/pci/cx18/cx18-ioctl.c
@@ -156,7 +156,6 @@ static int cx18_g_fmt_vid_cap(struct file *file, void *fh,
pixfmt->height = cx->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == CX18_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = s->pixelformat;
pixfmt->sizeimage = s->vb_bytes_per_frame;
diff --git a/drivers/media/pci/cx18/cx18-streams.c b/drivers/media/pci/cx18/cx18-streams.c
index 843c62b2f482..f3541b5156ce 100644
--- a/drivers/media/pci/cx18/cx18-streams.c
+++ b/drivers/media/pci/cx18/cx18-streams.c
@@ -375,7 +375,6 @@ static int cx18_prep_dev(struct cx18 *cx, int type)
s->video_dev->release = video_device_release;
s->video_dev->tvnorms = V4L2_STD_ALL;
s->video_dev->lock = &cx->serialize_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->video_dev->flags);
cx18_set_funcs(s->video_dev);
return 0;
}
diff --git a/drivers/media/pci/cx23885/cx23885-cards.c b/drivers/media/pci/cx23885/cx23885-cards.c
index 79f20c8c842e..972306704e55 100644
--- a/drivers/media/pci/cx23885/cx23885-cards.c
+++ b/drivers/media/pci/cx23885/cx23885-cards.c
@@ -649,7 +649,26 @@ struct cx23885_board cx23885_boards[] = {
CX25840_NONE1_CH3,
.amux = CX25840_AUDIO6,
} },
- }
+ },
+ [CX23885_BOARD_HAUPPAUGE_IMPACTVCBE] = {
+ .name = "Hauppauge ImpactVCB-e",
+ .tuner_type = TUNER_ABSENT,
+ .porta = CX23885_ANALOG_VIDEO,
+ .input = {{
+ .type = CX23885_VMUX_COMPOSITE1,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN6_CH1,
+ .amux = CX25840_AUDIO7,
+ }, {
+ .type = CX23885_VMUX_SVIDEO,
+ .vmux = CX25840_VIN7_CH3 |
+ CX25840_VIN4_CH2 |
+ CX25840_VIN8_CH1 |
+ CX25840_SVIDEO_ON,
+ .amux = CX25840_AUDIO7,
+ } },
+ },
};
const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -897,6 +916,10 @@ struct cx23885_subid cx23885_subids[] = {
.subvendor = 0x1461,
.subdevice = 0xd939,
.card = CX23885_BOARD_AVERMEDIA_HC81R,
+ }, {
+ .subvendor = 0x0070,
+ .subdevice = 0x7133,
+ .card = CX23885_BOARD_HAUPPAUGE_IMPACTVCBE,
},
};
const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -977,6 +1000,9 @@ static void hauppauge_eeprom(struct cx23885_dev *dev, u8 *eeprom_data)
case 71009:
/* WinTV-HVR1200 (PCIe, Retail, full height)
* DVB-T and basic analog */
+ case 71100:
+ /* WinTV-ImpactVCB-e (PCIe, Retail, half height)
+ * Basic analog */
case 71359:
/* WinTV-HVR1200 (PCIe, OEM, half height)
* DVB-T and basic analog */
@@ -1701,6 +1727,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1850:
case CX23885_BOARD_HAUPPAUGE_HVR1290:
case CX23885_BOARD_HAUPPAUGE_HVR4400:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
if (dev->i2c_bus[0].i2c_rc == 0)
hauppauge_eeprom(dev, eeprom+0xc0);
break;
@@ -1807,6 +1834,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
case CX23885_BOARD_HAUPPAUGE_HVR1200:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_HAUPPAUGE_HVR1400:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
case CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H_XC4000:
@@ -1835,6 +1863,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1250:
case CX23885_BOARD_HAUPPAUGE_HVR1800:
+ case CX23885_BOARD_HAUPPAUGE_IMPACTVCBE:
case CX23885_BOARD_HAUPPAUGE_HVR1800lp:
case CX23885_BOARD_HAUPPAUGE_HVR1700:
case CX23885_BOARD_LEADTEK_WINFAST_PXDVR3200_H:
diff --git a/drivers/media/pci/cx23885/cx23885-dvb.c b/drivers/media/pci/cx23885/cx23885-dvb.c
index 4be01b3bd4f5..d037459f3d14 100644
--- a/drivers/media/pci/cx23885/cx23885-dvb.c
+++ b/drivers/media/pci/cx23885/cx23885-dvb.c
@@ -748,6 +748,7 @@ static int netup_altera_fpga_rw(void *device, int flag, int data, int read)
static int dvb_register(struct cx23885_tsport *port)
{
+ struct dib7000p_ops dib7000p_ops;
struct cx23885_dev *dev = port->dev;
struct cx23885_i2c *i2c_bus = NULL, *i2c_bus2 = NULL;
struct videobuf_dvb_frontend *fe0, *fe1 = NULL;
@@ -925,8 +926,11 @@ static int dvb_register(struct cx23885_tsport *port)
break;
case CX23885_BOARD_HAUPPAUGE_HVR1400:
i2c_bus = &dev->i2c_bus[0];
- fe0->dvb.frontend = dvb_attach(dib7000p_attach,
- &i2c_bus->i2c_adap,
+
+ if (!dvb_attach(dib7000p_attach, &dib7000p_ops))
+ return -ENODEV;
+
+ fe0->dvb.frontend = dib7000p_ops.init(&i2c_bus->i2c_adap,
0x12, &hauppauge_hvr1400_dib7000_config);
if (fe0->dvb.frontend != NULL) {
struct dvb_frontend *fe;
diff --git a/drivers/media/pci/cx23885/cx23885-video.c b/drivers/media/pci/cx23885/cx23885-video.c
index e0a59523cf3c..71e3ec3d8a3d 100644
--- a/drivers/media/pci/cx23885/cx23885-video.c
+++ b/drivers/media/pci/cx23885/cx23885-video.c
@@ -507,6 +507,7 @@ static int cx23885_video_mux(struct cx23885_dev *dev, unsigned int input)
if ((dev->board == CX23885_BOARD_HAUPPAUGE_HVR1800) ||
(dev->board == CX23885_BOARD_MPX885) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1250) ||
+ (dev->board == CX23885_BOARD_HAUPPAUGE_IMPACTVCBE) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1255_22111) ||
(dev->board == CX23885_BOARD_HAUPPAUGE_HVR1850) ||
diff --git a/drivers/media/pci/cx23885/cx23885.h b/drivers/media/pci/cx23885/cx23885.h
index 0fa4048ab872..6a4b20e5fcac 100644
--- a/drivers/media/pci/cx23885/cx23885.h
+++ b/drivers/media/pci/cx23885/cx23885.h
@@ -96,6 +96,7 @@
#define CX23885_BOARD_TBS_6981 40
#define CX23885_BOARD_TBS_6980 41
#define CX23885_BOARD_LEADTEK_WINFAST_PXPVR2200 42
+#define CX23885_BOARD_HAUPPAUGE_IMPACTVCBE 43
#define GPIO_0 0x00000001
#define GPIO_1 0x00000002
diff --git a/drivers/media/pci/cx25821/cx25821-video.c b/drivers/media/pci/cx25821/cx25821-video.c
index d270819fd875..3a419f134584 100644
--- a/drivers/media/pci/cx25821/cx25821-video.c
+++ b/drivers/media/pci/cx25821/cx25821-video.c
@@ -576,7 +576,6 @@ static int cx25821_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (chan->width * chan->fmt->depth) >> 3;
f->fmt.pix.sizeimage = chan->height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -615,7 +614,6 @@ static int cx25821_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -867,7 +865,6 @@ static int cx25821_vidioc_try_fmt_vid_out(struct file *file, void *priv,
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1109,7 +1106,6 @@ int cx25821_video_register(struct cx25821_dev *dev)
else
vdev->vfl_dir = VFL_DIR_TX;
vdev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
snprintf(vdev->name, sizeof(vdev->name), "%s #%d", dev->name, i);
video_set_drvdata(vdev, chan);
diff --git a/drivers/media/pci/cx88/cx88-core.c b/drivers/media/pci/cx88/cx88-core.c
index e061c88b697e..71630238027b 100644
--- a/drivers/media/pci/cx88/cx88-core.c
+++ b/drivers/media/pci/cx88/cx88-core.c
@@ -1045,7 +1045,6 @@ struct video_device *cx88_vdev_init(struct cx88_core *core,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
core->name, type, core->board.name);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
return vfd;
}
diff --git a/drivers/media/pci/ivtv/ivtv-controls.c b/drivers/media/pci/ivtv/ivtv-controls.c
index c60424601cb9..2b0ab26e11e8 100644
--- a/drivers/media/pci/ivtv/ivtv-controls.c
+++ b/drivers/media/pci/ivtv/ivtv-controls.c
@@ -135,8 +135,8 @@ static int ivtv_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
/* V4L2_CID_MPEG_VIDEO_DEC_PTS and V4L2_CID_MPEG_VIDEO_DEC_FRAME
control cluster */
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
- return ivtv_g_pts_frame(itv, &itv->ctrl_pts->val64,
- &itv->ctrl_frame->val64);
+ return ivtv_g_pts_frame(itv, itv->ctrl_pts->p_new.p_s64,
+ itv->ctrl_frame->p_new.p_s64);
}
return 0;
}
diff --git a/drivers/media/pci/ivtv/ivtv-ioctl.c b/drivers/media/pci/ivtv/ivtv-ioctl.c
index b3667a00db3a..3e0cb77d5930 100644
--- a/drivers/media/pci/ivtv/ivtv-ioctl.c
+++ b/drivers/media/pci/ivtv/ivtv-ioctl.c
@@ -351,7 +351,6 @@ static int ivtv_g_fmt_vid_cap(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->cxhdl.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == IVTV_ENC_STREAM_TYPE_YUV) {
pixfmt->pixelformat = V4L2_PIX_FMT_HM12;
/* YUV size is (Y=(h*720) + UV=(h*(720/2))) */
@@ -418,7 +417,6 @@ static int ivtv_g_fmt_vid_out(struct file *file, void *fh, struct v4l2_format *f
pixfmt->height = itv->main_rect.height;
pixfmt->colorspace = V4L2_COLORSPACE_SMPTE170M;
pixfmt->field = V4L2_FIELD_INTERLACED;
- pixfmt->priv = 0;
if (id->type == IVTV_DEC_STREAM_TYPE_YUV) {
switch (itv->yuv_info.lace_mode & IVTV_YUV_MODE_MASK) {
case IVTV_YUV_MODE_INTERLACED:
@@ -1384,7 +1382,6 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
fb->fmt.bytesperline = fb->fmt.width;
fb->fmt.colorspace = V4L2_COLORSPACE_SMPTE170M;
fb->fmt.field = V4L2_FIELD_INTERLACED;
- fb->fmt.priv = 0;
if (fb->fmt.pixelformat != V4L2_PIX_FMT_PAL8)
fb->fmt.bytesperline *= 2;
if (fb->fmt.pixelformat == V4L2_PIX_FMT_RGB32 ||
diff --git a/drivers/media/pci/ivtv/ivtv-streams.c b/drivers/media/pci/ivtv/ivtv-streams.c
index 70dad588a677..f0a1cc472313 100644
--- a/drivers/media/pci/ivtv/ivtv-streams.c
+++ b/drivers/media/pci/ivtv/ivtv-streams.c
@@ -251,7 +251,6 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
v4l2_disable_ioctl(s->vdev, VIDIOC_G_TUNER);
v4l2_disable_ioctl(s->vdev, VIDIOC_S_STD);
}
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev->flags);
ivtv_set_funcs(s->vdev);
return 0;
}
diff --git a/drivers/media/pci/meye/meye.c b/drivers/media/pci/meye/meye.c
index 54d5c821007c..aeae54708811 100644
--- a/drivers/media/pci/meye/meye.c
+++ b/drivers/media/pci/meye/meye.c
@@ -1166,7 +1166,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1232,7 +1231,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *fh,
f->fmt.pix.sizeimage = f->fmt.pix.height *
f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1749,7 +1747,6 @@ static int meye_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)
v4l2_ctrl_handler_setup(&meye.hdl);
meye.vdev->ctrl_handler = &meye.hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &meye.vdev->flags);
if (video_register_device(meye.vdev, VFL_TYPE_GRABBER,
video_nr) < 0) {
diff --git a/drivers/media/pci/ngene/ngene-core.c b/drivers/media/pci/ngene/ngene-core.c
index 970e83308525..826228c3800e 100644
--- a/drivers/media/pci/ngene/ngene-core.c
+++ b/drivers/media/pci/ngene/ngene-core.c
@@ -910,7 +910,6 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
{
dma_addr_t tmp;
u32 i, j;
- int status = 0;
u32 SCListMemSize = pRingBuffer->NumBuffers
* ((Buffer2Length != 0) ? (NUM_SCATTER_GATHER_ENTRIES * 2) :
NUM_SCATTER_GATHER_ENTRIES)
@@ -1010,14 +1009,12 @@ static int AllocateRingBuffers(struct pci_dev *pci_dev,
}
- return status;
+ return 0;
}
static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
struct SRingBufferDescriptor *pRingBuffer)
{
- int status = 0;
-
/* Copy pointer to scatter gather list in TSRingbuffer
structure for buffer 2
Load number of buffer
@@ -1038,7 +1035,7 @@ static int FillTSIdleBuffer(struct SRingBufferDescriptor *pIdleBuffer,
pIdleBuffer->Head->ngeneBuffer.Number_of_entries_1;
Cur = Cur->Next;
}
- return status;
+ return 0;
}
static u32 RingBufferSizes[MAX_STREAM] = {
diff --git a/drivers/media/pci/saa7134/saa7134-core.c b/drivers/media/pci/saa7134/saa7134-core.c
index be19a051a492..9ff03a69ced4 100644
--- a/drivers/media/pci/saa7134/saa7134-core.c
+++ b/drivers/media/pci/saa7134/saa7134-core.c
@@ -811,7 +811,6 @@ static struct video_device *vdev_init(struct saa7134_dev *dev,
vfd->release = video_device_release;
snprintf(vfd->name, sizeof(vfd->name), "%s %s (%s)",
dev->name, type, saa7134_boards[dev->board].name);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, dev);
return vfd;
}
diff --git a/drivers/media/pci/saa7134/saa7134-empress.c b/drivers/media/pci/saa7134/saa7134-empress.c
index 0006d6bf8c18..e4ea85fd1b23 100644
--- a/drivers/media/pci/saa7134/saa7134-empress.c
+++ b/drivers/media/pci/saa7134/saa7134-empress.c
@@ -130,7 +130,6 @@ static int empress_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -148,7 +147,6 @@ static int empress_s_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -166,7 +164,6 @@ static int empress_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = TS_PACKET_SIZE * dev->ts.nr_packets;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -270,7 +267,6 @@ static int empress_init(struct saa7134_dev *dev)
snprintf(dev->empress_dev->name, sizeof(dev->empress_dev->name),
"%s empress (%s)", dev->name,
saa7134_boards[dev->board].name);
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->empress_dev->flags);
v4l2_ctrl_handler_init(hdl, 21);
v4l2_ctrl_add_handler(hdl, &dev->ctrl_handler, empress_ctrl_filter);
if (dev->empress_sd)
diff --git a/drivers/media/pci/saa7134/saa7134-video.c b/drivers/media/pci/saa7134/saa7134-video.c
index d37599980768..0cfa2ca6a32a 100644
--- a/drivers/media/pci/saa7134/saa7134-video.c
+++ b/drivers/media/pci/saa7134/saa7134-video.c
@@ -1235,7 +1235,6 @@ static int saa7134_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1315,7 +1314,6 @@ static int saa7134_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
diff --git a/drivers/media/pci/saa7164/saa7164-dvb.c b/drivers/media/pci/saa7164/saa7164-dvb.c
index 5c5cc3ebf9bd..16ae71592e8c 100644
--- a/drivers/media/pci/saa7164/saa7164-dvb.c
+++ b/drivers/media/pci/saa7164/saa7164-dvb.c
@@ -242,16 +242,14 @@ static int saa7164_dvb_start_feed(struct dvb_demux_feed *feed)
if (!demux->dmx.frontend)
return -EINVAL;
- if (dvb) {
- mutex_lock(&dvb->lock);
- if (dvb->feeding++ == 0) {
- /* Start transport */
- ret = saa7164_dvb_start_port(port);
- }
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
+ mutex_lock(&dvb->lock);
+ if (dvb->feeding++ == 0) {
+ /* Start transport */
+ ret = saa7164_dvb_start_port(port);
}
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
return ret;
}
@@ -266,16 +264,14 @@ static int saa7164_dvb_stop_feed(struct dvb_demux_feed *feed)
dprintk(DBGLVL_DVB, "%s(port=%d)\n", __func__, port->nr);
- if (dvb) {
- mutex_lock(&dvb->lock);
- if (--dvb->feeding == 0) {
- /* Stop transport */
- ret = saa7164_dvb_stop_streaming(port);
- }
- mutex_unlock(&dvb->lock);
- dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
- __func__, port->nr, dvb->feeding);
+ mutex_lock(&dvb->lock);
+ if (--dvb->feeding == 0) {
+ /* Stop transport */
+ ret = saa7164_dvb_stop_streaming(port);
}
+ mutex_unlock(&dvb->lock);
+ dprintk(DBGLVL_DVB, "%s(port=%d) now feeding = %d\n",
+ __func__, port->nr, dvb->feeding);
return ret;
}
diff --git a/drivers/media/pci/sta2x11/sta2x11_vip.c b/drivers/media/pci/sta2x11/sta2x11_vip.c
index d2abd3b5c2bf..365bd21301ba 100644
--- a/drivers/media/pci/sta2x11/sta2x11_vip.c
+++ b/drivers/media/pci/sta2x11/sta2x11_vip.c
@@ -640,7 +640,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.width * 2 * f->fmt.pix.height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1093,7 +1092,6 @@ static int sta2x11_vip_init_one(struct pci_dev *pdev,
vip->video_dev = &video_dev_template;
vip->video_dev->v4l2_dev = &vip->v4l2_dev;
vip->video_dev->queue = &vip->vb_vidq;
- set_bit(V4L2_FL_USE_FH_PRIO, &vip->video_dev->flags);
video_set_drvdata(vip->video_dev, vip);
ret = video_register_device(vip->video_dev, VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/pci/zoran/zr36050.h b/drivers/media/pci/zoran/zr36050.h
index 9f52f0cdde50..ea083adda045 100644
--- a/drivers/media/pci/zoran/zr36050.h
+++ b/drivers/media/pci/zoran/zr36050.h
@@ -126,7 +126,6 @@ struct zr36050 {
/* zr36050 mode register bits */
#define ZR050_MO_COMP 0x80
-#define ZR050_MO_COMP 0x80
#define ZR050_MO_ATP 0x40
#define ZR050_MO_PASS2 0x20
#define ZR050_MO_TLM 0x10
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
index 8108c698b548..49e8c0a0e1e5 100644
--- a/drivers/media/platform/Kconfig
+++ b/drivers/media/platform/Kconfig
@@ -96,6 +96,7 @@ config VIDEO_OMAP3
depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3
select ARM_DMA_USE_IOMMU
select OMAP_IOMMU
+ select VIDEOBUF2_DMA_CONTIG
---help---
Driver for an OMAP 3 camera controller.
diff --git a/drivers/media/platform/arv.c b/drivers/media/platform/arv.c
index e9410e41ae0c..03c5098499c4 100644
--- a/drivers/media/platform/arv.c
+++ b/drivers/media/platform/arv.c
@@ -773,7 +773,6 @@ static int __init ar_init(void)
ar->vdev.fops = &ar_fops;
ar->vdev.ioctl_ops = &ar_ioctl_ops;
ar->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &ar->vdev.flags);
video_set_drvdata(&ar->vdev, ar);
if (vga) {
diff --git a/drivers/media/platform/blackfin/bfin_capture.c b/drivers/media/platform/blackfin/bfin_capture.c
index 16e4b1c525c4..6ef986657dda 100644
--- a/drivers/media/platform/blackfin/bfin_capture.c
+++ b/drivers/media/platform/blackfin/bfin_capture.c
@@ -966,7 +966,6 @@ static int bcap_probe(struct platform_device *pdev)
vfd->ioctl_ops = &bcap_ioctl_ops;
vfd->tvnorms = 0;
vfd->v4l2_dev = &bcap_dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
strncpy(vfd->name, CAPTURE_DRV_NAME, sizeof(vfd->name));
bcap_dev->video_dev = vfd;
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
index b1783791d426..31a1848f3674 100644
--- a/drivers/media/platform/coda.c
+++ b/drivers/media/platform/coda.c
@@ -135,9 +135,7 @@ struct coda_dev {
struct coda_aux_buf tempbuf;
struct coda_aux_buf workbuf;
struct gen_pool *iram_pool;
- long unsigned int iram_vaddr;
- long unsigned int iram_paddr;
- unsigned long iram_size;
+ struct coda_aux_buf iram;
spinlock_t irqlock;
struct mutex dev_mutex;
@@ -175,6 +173,8 @@ struct coda_iram_info {
phys_addr_t buf_btp_use;
phys_addr_t search_ram_paddr;
int search_ram_size;
+ int remaining;
+ phys_addr_t next_paddr;
};
struct coda_ctx {
@@ -209,6 +209,7 @@ struct coda_ctx {
struct coda_aux_buf psbuf;
struct coda_aux_buf slicebuf;
struct coda_aux_buf internal_frames[CODA_MAX_FRAMEBUFFERS];
+ u32 frame_types[CODA_MAX_FRAMEBUFFERS];
struct coda_aux_buf workbuf;
int num_internal_frames;
int idx;
@@ -613,8 +614,6 @@ static int coda_try_fmt(struct coda_ctx *ctx, struct coda_codec *codec,
BUG();
}
- f->fmt.pix.priv = 0;
-
return 0;
}
@@ -1526,10 +1525,10 @@ static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_d
for (i = 0; i < ctx->num_internal_frames; i++) {
size_t size;
- size = q_data->sizeimage;
+ size = ysize + ysize / 2;
if (ctx->codec->src_fourcc == V4L2_PIX_FMT_H264 &&
dev->devtype->product != CODA_DX6)
- ctx->internal_frames[i].size += ysize/4;
+ size += ysize / 4;
ret = coda_alloc_context_buf(ctx, &ctx->internal_frames[i], size);
if (ret < 0) {
coda_free_framebuffers(ctx);
@@ -1579,23 +1578,43 @@ static int coda_h264_padding(int size, char *p)
return nal_size;
}
+static phys_addr_t coda_iram_alloc(struct coda_iram_info *iram, size_t size)
+{
+ phys_addr_t ret;
+
+ size = round_up(size, 1024);
+ if (size > iram->remaining)
+ return 0;
+ iram->remaining -= size;
+
+ ret = iram->next_paddr;
+ iram->next_paddr += size;
+
+ return ret;
+}
+
static void coda_setup_iram(struct coda_ctx *ctx)
{
struct coda_iram_info *iram_info = &ctx->iram_info;
struct coda_dev *dev = ctx->dev;
- int ipacdc_size;
- int bitram_size;
- int dbk_size;
- int ovl_size;
int mb_width;
- int me_size;
- int size;
+ int dbk_bits;
+ int bit_bits;
+ int ip_bits;
memset(iram_info, 0, sizeof(*iram_info));
- size = dev->iram_size;
+ iram_info->next_paddr = dev->iram.paddr;
+ iram_info->remaining = dev->iram.size;
- if (dev->devtype->product == CODA_DX6)
+ switch (dev->devtype->product) {
+ case CODA_7541:
+ dbk_bits = CODA7_USE_HOST_DBK_ENABLE | CODA7_USE_DBK_ENABLE;
+ bit_bits = CODA7_USE_HOST_BIT_ENABLE | CODA7_USE_BIT_ENABLE;
+ ip_bits = CODA7_USE_HOST_IP_ENABLE | CODA7_USE_IP_ENABLE;
+ break;
+ default: /* CODA_DX6 */
return;
+ }
if (ctx->inst_type == CODA_INST_ENCODER) {
struct coda_q_data *q_data_src;
@@ -1604,111 +1623,63 @@ static void coda_setup_iram(struct coda_ctx *ctx)
mb_width = DIV_ROUND_UP(q_data_src->width, 16);
/* Prioritize in case IRAM is too small for everything */
- me_size = round_up(round_up(q_data_src->width, 16) * 36 + 2048,
- 1024);
- iram_info->search_ram_size = me_size;
- if (size >= iram_info->search_ram_size) {
- if (dev->devtype->product == CODA_7541)
- iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE;
- iram_info->search_ram_paddr = dev->iram_paddr;
- size -= iram_info->search_ram_size;
- } else {
- pr_err("IRAM is smaller than the search ram size\n");
- goto out;
+ if (dev->devtype->product == CODA_7541) {
+ iram_info->search_ram_size = round_up(mb_width * 16 *
+ 36 + 2048, 1024);
+ iram_info->search_ram_paddr = coda_iram_alloc(iram_info,
+ iram_info->search_ram_size);
+ if (!iram_info->search_ram_paddr) {
+ pr_err("IRAM is smaller than the search ram size\n");
+ goto out;
+ }
+ iram_info->axi_sram_use |= CODA7_USE_HOST_ME_ENABLE |
+ CODA7_USE_ME_ENABLE;
}
/* Only H.264BP and H.263P3 are considered */
- dbk_size = round_up(128 * mb_width, 1024);
- if (size >= dbk_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
- iram_info->buf_dbk_y_use = dev->iram_paddr +
- iram_info->search_ram_size;
- iram_info->buf_dbk_c_use = iram_info->buf_dbk_y_use +
- dbk_size / 2;
- size -= dbk_size;
- } else {
+ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 64 * mb_width);
+ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 64 * mb_width);
+ if (!iram_info->buf_dbk_c_use)
goto out;
- }
+ iram_info->axi_sram_use |= dbk_bits;
- bitram_size = round_up(128 * mb_width, 1024);
- if (size >= bitram_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
- iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
- dbk_size / 2;
- size -= bitram_size;
- } else {
+ iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_bit_use)
goto out;
- }
+ iram_info->axi_sram_use |= bit_bits;
- ipacdc_size = round_up(128 * mb_width, 1024);
- if (size >= ipacdc_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
- iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
- bitram_size;
- size -= ipacdc_size;
- }
+ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_ip_ac_dc_use)
+ goto out;
+ iram_info->axi_sram_use |= ip_bits;
/* OVL and BTP disabled for encoder */
} else if (ctx->inst_type == CODA_INST_DECODER) {
struct coda_q_data *q_data_dst;
- int mb_height;
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
mb_width = DIV_ROUND_UP(q_data_dst->width, 16);
- mb_height = DIV_ROUND_UP(q_data_dst->height, 16);
-
- dbk_size = round_up(256 * mb_width, 1024);
- if (size >= dbk_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_DBK_ENABLE;
- iram_info->buf_dbk_y_use = dev->iram_paddr;
- iram_info->buf_dbk_c_use = dev->iram_paddr +
- dbk_size / 2;
- size -= dbk_size;
- } else {
+
+ iram_info->buf_dbk_y_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ iram_info->buf_dbk_c_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_dbk_c_use)
goto out;
- }
+ iram_info->axi_sram_use |= dbk_bits;
- bitram_size = round_up(128 * mb_width, 1024);
- if (size >= bitram_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_BIT_ENABLE;
- iram_info->buf_bit_use = iram_info->buf_dbk_c_use +
- dbk_size / 2;
- size -= bitram_size;
- } else {
+ iram_info->buf_bit_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_bit_use)
goto out;
- }
+ iram_info->axi_sram_use |= bit_bits;
- ipacdc_size = round_up(128 * mb_width, 1024);
- if (size >= ipacdc_size) {
- iram_info->axi_sram_use |= CODA7_USE_HOST_IP_ENABLE;
- iram_info->buf_ip_ac_dc_use = iram_info->buf_bit_use +
- bitram_size;
- size -= ipacdc_size;
- } else {
+ iram_info->buf_ip_ac_dc_use = coda_iram_alloc(iram_info, 128 * mb_width);
+ if (!iram_info->buf_ip_ac_dc_use)
goto out;
- }
+ iram_info->axi_sram_use |= ip_bits;
- ovl_size = round_up(80 * mb_width, 1024);
+ /* OVL and BTP unused as there is no VC1 support yet */
}
out:
- switch (dev->devtype->product) {
- case CODA_DX6:
- break;
- case CODA_7541:
- /* i.MX53 uses secondary AXI for IRAM access */
- if (iram_info->axi_sram_use & CODA7_USE_HOST_BIT_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_BIT_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_IP_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_DBK_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_DBK_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_OVL_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_OVL_ENABLE;
- if (iram_info->axi_sram_use & CODA7_USE_HOST_ME_ENABLE)
- iram_info->axi_sram_use |= CODA7_USE_ME_ENABLE;
- }
-
if (!(iram_info->axi_sram_use & CODA7_USE_HOST_IP_ENABLE))
v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
"IRAM smaller than needed\n");
@@ -1888,7 +1859,7 @@ static int coda_start_decoding(struct coda_ctx *ctx)
v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "%s instance %d now: %dx%d\n",
__func__, ctx->idx, width, height);
- ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED) + 1;
+ ctx->num_internal_frames = coda_read(dev, CODA_RET_DEC_SEQ_FRAME_NEED);
if (ctx->num_internal_frames > CODA_MAX_FRAMEBUFFERS) {
v4l2_err(&dev->v4l2_dev,
"not enough framebuffers to decode (%d < %d)\n",
@@ -2064,7 +2035,7 @@ static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
if (dev->devtype->product == CODA_DX6) {
/* Configure the coda */
- coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
+ coda_write(dev, dev->iram.paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
}
/* Could set rotation here if needed */
@@ -2384,9 +2355,9 @@ static int coda_ctrls_setup(struct coda_ctx *ctx)
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 60, 1, 16);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 1, 51, 1, 25);
+ V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP, 0, 51, 1, 25);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
- V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 51, 1, 25);
+ V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 0, 51, 1, 25);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP, 1, 31, 1, 2);
v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
@@ -2693,15 +2664,6 @@ static void coda_finish_decode(struct coda_ctx *ctx)
q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
- val = coda_read(dev, CODA_RET_DEC_PIC_TYPE);
- if ((val & 0x7) == 0) {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
- } else {
- dst_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
- dst_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
- }
-
val = coda_read(dev, CODA_RET_DEC_PIC_ERR_MB);
if (val > 0)
v4l2_err(&dev->v4l2_dev,
@@ -2748,6 +2710,14 @@ static void coda_finish_decode(struct coda_ctx *ctx)
} else if (decoded_idx < 0 || decoded_idx >= ctx->num_internal_frames) {
v4l2_err(&dev->v4l2_dev,
"decoded frame index out of range: %d\n", decoded_idx);
+ } else {
+ val = coda_read(dev, CODA_RET_DEC_PIC_TYPE) & 0x7;
+ if (val == 0)
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_KEYFRAME;
+ else if (val == 1)
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_PFRAME;
+ else
+ ctx->frame_types[decoded_idx] = V4L2_BUF_FLAG_BFRAME;
}
if (display_idx == -1) {
@@ -2770,6 +2740,11 @@ static void coda_finish_decode(struct coda_ctx *ctx)
dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
dst_buf->v4l2_buf.sequence = ctx->osequence++;
+ dst_buf->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_KEYFRAME |
+ V4L2_BUF_FLAG_PFRAME |
+ V4L2_BUF_FLAG_BFRAME);
+ dst_buf->v4l2_buf.flags |= ctx->frame_types[ctx->display_idx];
+
vb2_set_plane_payload(dst_buf, 0, width * height * 3 / 2);
v4l2_m2m_buf_done(dst_buf, success ? VB2_BUF_STATE_DONE :
@@ -3293,15 +3268,15 @@ static int coda_probe(struct platform_device *pdev)
switch (dev->devtype->product) {
case CODA_DX6:
- dev->iram_size = CODADX6_IRAM_SIZE;
+ dev->iram.size = CODADX6_IRAM_SIZE;
break;
case CODA_7541:
- dev->iram_size = CODA7_IRAM_SIZE;
+ dev->iram.size = CODA7_IRAM_SIZE;
break;
}
- dev->iram_vaddr = (unsigned long)gen_pool_dma_alloc(dev->iram_pool,
- dev->iram_size, (dma_addr_t *)&dev->iram_paddr);
- if (!dev->iram_vaddr) {
+ dev->iram.vaddr = gen_pool_dma_alloc(dev->iram_pool, dev->iram.size,
+ &dev->iram.paddr);
+ if (!dev->iram.vaddr) {
dev_err(&pdev->dev, "unable to alloc iram\n");
return -ENOMEM;
}
@@ -3321,8 +3296,9 @@ static int coda_remove(struct platform_device *pdev)
if (dev->alloc_ctx)
vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
v4l2_device_unregister(&dev->v4l2_dev);
- if (dev->iram_vaddr)
- gen_pool_free(dev->iram_pool, dev->iram_vaddr, dev->iram_size);
+ if (dev->iram.vaddr)
+ gen_pool_free(dev->iram_pool, (unsigned long)dev->iram.vaddr,
+ dev->iram.size);
coda_free_aux_buf(dev, &dev->codebuf);
coda_free_aux_buf(dev, &dev->tempbuf);
coda_free_aux_buf(dev, &dev->workbuf);
diff --git a/drivers/media/platform/davinci/dm644x_ccdc.c b/drivers/media/platform/davinci/dm644x_ccdc.c
index 30fa08405d61..07e98df3d867 100644
--- a/drivers/media/platform/davinci/dm644x_ccdc.c
+++ b/drivers/media/platform/davinci/dm644x_ccdc.c
@@ -581,13 +581,8 @@ void ccdc_config_raw(void)
config_params->alaw.enable)
syn_mode |= CCDC_DATA_PACK_ENABLE;
-#ifdef CONFIG_DM644X_VIDEO_PORT_ENABLE
- /* enable video port */
- val = CCDC_ENABLE_VIDEO_PORT;
-#else
/* disable video port */
val = CCDC_DISABLE_VIDEO_PORT;
-#endif
if (config_params->data_sz == CCDC_DATA_8BITS)
val |= (CCDC_DATA_10BITS & CCDC_FMTCFG_VPIN_MASK)
diff --git a/drivers/media/platform/davinci/vpbe_display.c b/drivers/media/platform/davinci/vpbe_display.c
index bf5eff99452b..73496d953ba0 100644
--- a/drivers/media/platform/davinci/vpbe_display.c
+++ b/drivers/media/platform/davinci/vpbe_display.c
@@ -1709,7 +1709,6 @@ static int register_device(struct vpbe_layer *vpbe_display_layer,
vpbe_display_layer->disp_dev = disp_dev;
/* set the driver data in platform device */
platform_set_drvdata(pdev, disp_dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &vpbe_display_layer->video_dev.flags);
video_set_drvdata(&vpbe_display_layer->video_dev,
vpbe_display_layer);
diff --git a/drivers/media/platform/davinci/vpfe_capture.c b/drivers/media/platform/davinci/vpfe_capture.c
index a51bda2fb637..ea7661a27479 100644
--- a/drivers/media/platform/davinci/vpfe_capture.c
+++ b/drivers/media/platform/davinci/vpfe_capture.c
@@ -1916,7 +1916,6 @@ static int vpfe_probe(struct platform_device *pdev)
v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
"video_dev=%x\n", (int)&vpfe_dev->video_dev);
vpfe_dev->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- set_bit(V4L2_FL_USE_FH_PRIO, &vpfe_dev->video_dev->flags);
ret = video_register_device(vpfe_dev->video_dev,
VFL_TYPE_GRABBER, -1);
diff --git a/drivers/media/platform/davinci/vpif_capture.c b/drivers/media/platform/davinci/vpif_capture.c
index 1e4ec697fb10..b054b7eec53d 100644
--- a/drivers/media/platform/davinci/vpif_capture.c
+++ b/drivers/media/platform/davinci/vpif_capture.c
@@ -39,32 +39,10 @@ MODULE_VERSION(VPIF_CAPTURE_VERSION);
v4l2_dbg(level, debug, &vpif_obj.v4l2_dev, fmt, ## arg)
static int debug = 1;
-static u32 ch0_numbuffers = 3;
-static u32 ch1_numbuffers = 3;
-static u32 ch0_bufsize = 1920 * 1080 * 2;
-static u32 ch1_bufsize = 720 * 576 * 2;
module_param(debug, int, 0644);
-module_param(ch0_numbuffers, uint, S_IRUGO);
-module_param(ch1_numbuffers, uint, S_IRUGO);
-module_param(ch0_bufsize, uint, S_IRUGO);
-module_param(ch1_bufsize, uint, S_IRUGO);
MODULE_PARM_DESC(debug, "Debug level 0-1");
-MODULE_PARM_DESC(ch2_numbuffers, "Channel0 buffer count (default:3)");
-MODULE_PARM_DESC(ch3_numbuffers, "Channel1 buffer count (default:3)");
-MODULE_PARM_DESC(ch2_bufsize, "Channel0 buffer size (default:1920 x 1080 x 2)");
-MODULE_PARM_DESC(ch3_bufsize, "Channel1 buffer size (default:720 x 576 x 2)");
-
-static struct vpif_config_params config_params = {
- .min_numbuffers = 3,
- .numbuffers[0] = 3,
- .numbuffers[1] = 3,
- .min_bufsize[0] = 720 * 480 * 2,
- .min_bufsize[1] = 720 * 480 * 2,
- .channel_bufsize[0] = 1920 * 1080 * 2,
- .channel_bufsize[1] = 720 * 576 * 2,
-};
#define VPIF_DRIVER_NAME "vpif_capture"
@@ -521,10 +499,28 @@ static int vpif_update_std_info(struct channel_obj *ch)
common->width = std_info->width;
common->fmt.fmt.pix.height = std_info->height;
common->height = std_info->height;
+ common->fmt.fmt.pix.sizeimage = common->height * common->width * 2;
common->fmt.fmt.pix.bytesperline = std_info->width;
vpifparams->video_params.hpitch = std_info->width;
vpifparams->video_params.storage_mode = std_info->frm_fmt;
+ if (vid_ch->stdid)
+ common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+ else
+ common->fmt.fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+ if (ch->vpifparams.std_info.frm_fmt)
+ common->fmt.fmt.pix.field = V4L2_FIELD_NONE;
+ else
+ common->fmt.fmt.pix.field = V4L2_FIELD_INTERLACED;
+
+ if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
+ common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
+ else
+ common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
+
+ common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+
return 0;
}
@@ -601,27 +597,6 @@ static void vpif_calculate_offsets(struct channel_obj *ch)
}
/**
- * vpif_config_format: configure default frame format in the device
- * ch : ptr to channel object
- */
-static void vpif_config_format(struct channel_obj *ch)
-{
- struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-
- vpif_dbg(2, debug, "vpif_config_format\n");
-
- common->fmt.fmt.pix.field = V4L2_FIELD_ANY;
- common->fmt.fmt.pix.sizeimage
- = config_params.channel_bufsize[ch->channel_id];
-
- if (ch->vpifparams.iface.if_type == VPIF_IF_RAW_BAYER)
- common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_SBGGR8;
- else
- common->fmt.fmt.pix.pixelformat = V4L2_PIX_FMT_YUV422P;
- common->fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-}
-
-/**
* vpif_get_default_field() - Get default field type based on interface
* @vpif_params - ptr to vpif params
*/
@@ -633,112 +608,6 @@ static inline enum v4l2_field vpif_get_default_field(
}
/**
- * vpif_check_format() - check given pixel format for compatibility
- * @ch - channel ptr
- * @pixfmt - Given pixel format
- * @update - update the values as per hardware requirement
- *
- * Check the application pixel format for S_FMT and update the input
- * values as per hardware limits for TRY_FMT. The default pixel and
- * field format is selected based on interface type.
- */
-static int vpif_check_format(struct channel_obj *ch,
- struct v4l2_pix_format *pixfmt,
- int update)
-{
- struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
- struct vpif_params *vpif_params = &ch->vpifparams;
- enum v4l2_field field = pixfmt->field;
- u32 sizeimage, hpitch, vpitch;
- int ret = -EINVAL;
-
- vpif_dbg(2, debug, "vpif_check_format\n");
- /**
- * first check for the pixel format. If if_type is Raw bayer,
- * only V4L2_PIX_FMT_SBGGR8 format is supported. Otherwise only
- * V4L2_PIX_FMT_YUV422P is supported
- */
- if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
- if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pix format\n");
- goto exit;
- }
- pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
- }
- } else {
- if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pixel format\n");
- goto exit;
- }
- pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
- }
- }
-
- if (!(VPIF_VALID_FIELD(field))) {
- if (!update) {
- vpif_dbg(2, debug, "invalid field format\n");
- goto exit;
- }
- /**
- * By default use FIELD_NONE for RAW Bayer capture
- * and FIELD_INTERLACED for other interfaces
- */
- field = vpif_get_default_field(&vpif_params->iface);
- } else if (field == V4L2_FIELD_ANY)
- /* unsupported field. Use default */
- field = vpif_get_default_field(&vpif_params->iface);
-
- /* validate the hpitch */
- hpitch = pixfmt->bytesperline;
- if (hpitch < vpif_params->std_info.width) {
- if (!update) {
- vpif_dbg(2, debug, "invalid hpitch\n");
- goto exit;
- }
- hpitch = vpif_params->std_info.width;
- }
-
- sizeimage = pixfmt->sizeimage;
-
- vpitch = sizeimage / (hpitch * 2);
-
- /* validate the vpitch */
- if (vpitch < vpif_params->std_info.height) {
- if (!update) {
- vpif_dbg(2, debug, "Invalid vpitch\n");
- goto exit;
- }
- vpitch = vpif_params->std_info.height;
- }
-
- /* Check for 8 byte alignment */
- if (!ALIGN(hpitch, 8)) {
- if (!update) {
- vpif_dbg(2, debug, "invalid pitch alignment\n");
- goto exit;
- }
- /* adjust to next 8 byte boundary */
- hpitch = (((hpitch + 7) / 8) * 8);
- }
- /* if update is set, modify the bytesperline and sizeimage */
- if (update) {
- pixfmt->bytesperline = hpitch;
- pixfmt->sizeimage = hpitch * vpitch * 2;
- }
- /**
- * Image width and height is always based on current standard width and
- * height
- */
- pixfmt->width = common->fmt.fmt.pix.width;
- pixfmt->height = common->fmt.fmt.pix.height;
- return 0;
-exit:
- return ret;
-}
-
-/**
* vpif_config_addr() - function to configure buffer address in vpif
* @ch - channel ptr
* @muxmode - channel mux mode
@@ -948,9 +817,6 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id std_id)
return -EINVAL;
}
- /* Configure the default format information */
- vpif_config_format(ch);
-
/* set standard in the sub device */
ret = v4l2_subdev_call(ch->sd, video, s_std, std_id);
if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
@@ -977,10 +843,8 @@ static int vpif_enum_input(struct file *file, void *priv,
chan_cfg = &config->chan_config[ch->channel_id];
- if (input->index >= chan_cfg->input_count) {
- vpif_dbg(1, debug, "Invalid input index\n");
+ if (input->index >= chan_cfg->input_count)
return -EINVAL;
- }
memcpy(input, &chan_cfg->inputs[input->index].input,
sizeof(*input));
@@ -1069,8 +933,34 @@ static int vpif_try_fmt_vid_cap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
struct channel_obj *ch = video_get_drvdata(vdev);
struct v4l2_pix_format *pixfmt = &fmt->fmt.pix;
+ struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+ struct vpif_params *vpif_params = &ch->vpifparams;
- return vpif_check_format(ch, pixfmt, 1);
+ /*
+ * to supress v4l-compliance warnings silently correct
+ * the pixelformat
+ */
+ if (vpif_params->iface.if_type == VPIF_IF_RAW_BAYER) {
+ if (pixfmt->pixelformat != V4L2_PIX_FMT_SBGGR8)
+ pixfmt->pixelformat = V4L2_PIX_FMT_SBGGR8;
+ } else {
+ if (pixfmt->pixelformat != V4L2_PIX_FMT_YUV422P)
+ pixfmt->pixelformat = V4L2_PIX_FMT_YUV422P;
+ }
+
+ common->fmt.fmt.pix.pixelformat = pixfmt->pixelformat;
+
+ vpif_update_std_info(ch);
+
+ pixfmt->field = common->fmt.fmt.pix.field;
+ pixfmt->colorspace = common->fmt.fmt.pix.colorspace;
+ pixfmt->bytesperline = common->fmt.fmt.pix.width;
+ pixfmt->width = common->fmt.fmt.pix.width;
+ pixfmt->height = common->fmt.fmt.pix.height;
+ pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
+ pixfmt->priv = 0;
+
+ return 0;
}
@@ -1108,20 +998,17 @@ static int vpif_s_fmt_vid_cap(struct file *file, void *priv,
struct video_device *vdev = video_devdata(file);
struct channel_obj *ch = video_get_drvdata(vdev);
struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
- struct v4l2_pix_format *pixfmt;
- int ret = 0;
+ int ret;
vpif_dbg(2, debug, "%s\n", __func__);
if (vb2_is_busy(&common->buffer_queue))
return -EBUSY;
- pixfmt = &fmt->fmt.pix;
- /* Check for valid field format */
- ret = vpif_check_format(ch, pixfmt, 0);
-
+ ret = vpif_try_fmt_vid_cap(file, priv, fmt);
if (ret)
return ret;
+
/* store the format in the channel object */
common->fmt = *fmt;
return 0;
@@ -1411,36 +1298,9 @@ static struct v4l2_file_operations vpif_fops = {
*/
static int initialize_vpif(void)
{
- int err = 0, i, j;
+ int err, i, j;
int free_channel_objects_index;
- /* Default number of buffers should be 3 */
- if ((ch0_numbuffers > 0) &&
- (ch0_numbuffers < config_params.min_numbuffers))
- ch0_numbuffers = config_params.min_numbuffers;
- if ((ch1_numbuffers > 0) &&
- (ch1_numbuffers < config_params.min_numbuffers))
- ch1_numbuffers = config_params.min_numbuffers;
-
- /* Set buffer size to min buffers size if it is invalid */
- if (ch0_bufsize < config_params.min_bufsize[VPIF_CHANNEL0_VIDEO])
- ch0_bufsize =
- config_params.min_bufsize[VPIF_CHANNEL0_VIDEO];
- if (ch1_bufsize < config_params.min_bufsize[VPIF_CHANNEL1_VIDEO])
- ch1_bufsize =
- config_params.min_bufsize[VPIF_CHANNEL1_VIDEO];
-
- config_params.numbuffers[VPIF_CHANNEL0_VIDEO] = ch0_numbuffers;
- config_params.numbuffers[VPIF_CHANNEL1_VIDEO] = ch1_numbuffers;
- if (ch0_numbuffers) {
- config_params.channel_bufsize[VPIF_CHANNEL0_VIDEO]
- = ch0_bufsize;
- }
- if (ch1_numbuffers) {
- config_params.channel_bufsize[VPIF_CHANNEL1_VIDEO]
- = ch1_bufsize;
- }
-
/* Allocate memory for six channel objects */
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
vpif_obj.dev[i] =
@@ -1496,6 +1356,11 @@ static int vpif_probe_complete(void)
if (err)
goto probe_out;
+ /* set initial format */
+ ch->video.stdid = V4L2_STD_525_60;
+ memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
+ vpif_update_std_info(ch);
+
/* Initialize vb2 queue */
q = &common->buffer_queue;
q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
@@ -1533,7 +1398,6 @@ static int vpif_probe_complete(void)
vdev->vfl_dir = VFL_DIR_RX;
vdev->queue = q;
vdev->lock = &common->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(ch->video_dev, ch);
err = video_register_device(vdev,
VFL_TYPE_GRABBER, (j ? 1 : 0));
@@ -1714,7 +1578,7 @@ static int vpif_remove(struct platform_device *device)
for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[i];
- common = &ch->common[i];
+ common = &ch->common[VPIF_VIDEO_INDEX];
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
/* Unregister video device */
video_unregister_device(ch->video_dev);
diff --git a/drivers/media/platform/davinci/vpif_capture.h b/drivers/media/platform/davinci/vpif_capture.h
index 1ee17824f484..f65d28d38e66 100644
--- a/drivers/media/platform/davinci/vpif_capture.h
+++ b/drivers/media/platform/davinci/vpif_capture.h
@@ -119,15 +119,4 @@ struct vpif_device {
struct vpif_capture_config *config;
};
-struct vpif_config_params {
- u8 min_numbuffers;
- u8 numbuffers[VPIF_CAPTURE_NUM_CHANNELS];
- s8 device_type;
- u32 min_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
- u32 channel_bufsize[VPIF_CAPTURE_NUM_CHANNELS];
- u8 default_device[VPIF_CAPTURE_NUM_CHANNELS];
- u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
- u8 max_device_type;
-};
-
#endif /* VPIF_CAPTURE_H */
diff --git a/drivers/media/platform/davinci/vpif_display.c b/drivers/media/platform/davinci/vpif_display.c
index b431b58f39e3..a03ec7381cfe 100644
--- a/drivers/media/platform/davinci/vpif_display.c
+++ b/drivers/media/platform/davinci/vpif_display.c
@@ -649,7 +649,6 @@ static int vpif_try_fmt_vid_out(struct file *file, void *priv,
pixfmt->width = common->fmt.fmt.pix.width;
pixfmt->height = common->fmt.fmt.pix.height;
pixfmt->sizeimage = pixfmt->bytesperline * pixfmt->height * 2;
- pixfmt->priv = 0;
return 0;
}
@@ -1224,7 +1223,6 @@ static int vpif_probe_complete(void)
vdev->vfl_dir = VFL_DIR_TX;
vdev->queue = q;
vdev->lock = &common->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(ch->video_dev, ch);
err = video_register_device(vdev, VFL_TYPE_GRABBER,
(j ? 3 : 2));
@@ -1388,7 +1386,7 @@ static int vpif_remove(struct platform_device *device)
for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
/* Get the pointer to the channel object */
ch = vpif_obj.dev[i];
- common = &ch->common[i];
+ common = &ch->common[VPIF_VIDEO_INDEX];
vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
/* Unregister video device */
video_unregister_device(ch->video_dev);
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
index c21d14fd61db..d36c507a0ba2 100644
--- a/drivers/media/platform/m2m-deinterlace.c
+++ b/drivers/media/platform/m2m-deinterlace.c
@@ -1002,7 +1002,7 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_mask_t mask;
int ret = 0;
- pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+ pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
if (!pcdev)
return -ENOMEM;
@@ -1012,7 +1012,7 @@ static int deinterlace_probe(struct platform_device *pdev)
dma_cap_set(DMA_INTERLEAVE, mask);
pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
if (!pcdev->dma_chan)
- goto free_dev;
+ return -ENODEV;
if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
@@ -1078,8 +1078,6 @@ unreg_dev:
v4l2_device_unregister(&pcdev->v4l2_dev);
rel_dma:
dma_release_channel(pcdev->dma_chan);
-free_dev:
- kfree(pcdev);
return ret;
}
@@ -1094,7 +1092,6 @@ static int deinterlace_remove(struct platform_device *pdev)
v4l2_device_unregister(&pcdev->v4l2_dev);
vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
dma_release_channel(pcdev->dma_chan);
- kfree(pcdev);
return 0;
}
diff --git a/drivers/media/platform/mem2mem_testdev.c b/drivers/media/platform/mem2mem_testdev.c
index 0714070ed7fa..c1b03cfd6ded 100644
--- a/drivers/media/platform/mem2mem_testdev.c
+++ b/drivers/media/platform/mem2mem_testdev.c
@@ -532,7 +532,6 @@ static int vidioc_try_fmt(struct v4l2_format *f, struct m2mtest_fmt *fmt)
f->fmt.pix.bytesperline = (f->fmt.pix.width * fmt->depth) >> 3;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.field = V4L2_FIELD_NONE;
- f->fmt.pix.priv = 0;
return 0;
}
diff --git a/drivers/media/platform/omap/omap_vout.c b/drivers/media/platform/omap/omap_vout.c
index 9a726eacb29b..2d177fa58471 100644
--- a/drivers/media/platform/omap/omap_vout.c
+++ b/drivers/media/platform/omap/omap_vout.c
@@ -165,7 +165,6 @@ static int omap_vout_try_format(struct v4l2_pix_format *pix)
pix->pixelformat = omap_formats[ifmt].pixelformat;
pix->field = V4L2_FIELD_ANY;
- pix->priv = 0;
switch (pix->pixelformat) {
case V4L2_PIX_FMT_YUYV:
@@ -1896,7 +1895,6 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
pix->field = V4L2_FIELD_ANY;
pix->bytesperline = pix->width * 2;
pix->sizeimage = pix->bytesperline * pix->height;
- pix->priv = 0;
pix->colorspace = V4L2_COLORSPACE_JPEG;
vout->bpp = RGB565_BPP;
diff --git a/drivers/media/platform/s3c-camif/camif-capture.c b/drivers/media/platform/s3c-camif/camif-capture.c
index deba425e3d8f..f33641384e15 100644
--- a/drivers/media/platform/s3c-camif/camif-capture.c
+++ b/drivers/media/platform/s3c-camif/camif-capture.c
@@ -1172,7 +1172,6 @@ int s3c_camif_register_video_node(struct camif_dev *camif, int idx)
goto err_vd_rel;
video_set_drvdata(vfd, vp);
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
v4l2_ctrl_handler_init(&vp->ctrl_handler, 1);
ctrl = v4l2_ctrl_new_std(&vp->ctrl_handler, &s3c_camif_video_ctrl_ops,
@@ -1271,6 +1270,7 @@ static int s3c_camif_subdev_get_fmt(struct v4l2_subdev *sd,
}
mutex_unlock(&camif->lock);
+ mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_JPEG;
return 0;
}
@@ -1319,6 +1319,7 @@ static int s3c_camif_subdev_set_fmt(struct v4l2_subdev *sd,
v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %ux%u\n",
fmt->pad, mf->code, mf->width, mf->height);
+ mf->field = V4L2_FIELD_NONE;
mf->colorspace = V4L2_COLORSPACE_JPEG;
mutex_lock(&camif->lock);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 6c3f8f743900..390ca20be6ef 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
@@ -38,8 +38,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
dev->fw_virt_addr = dma_alloc_coherent(dev->mem_dev_l, dev->fw_size,
&dev->bank1, GFP_KERNEL);
- if (IS_ERR_OR_NULL(dev->fw_virt_addr)) {
- dev->fw_virt_addr = NULL;
+ if (!dev->fw_virt_addr) {
mfc_err("Allocating bitprocessor buffer failed\n");
return -ENOMEM;
}
@@ -48,7 +47,7 @@ int s5p_mfc_alloc_firmware(struct s5p_mfc_dev *dev)
bank2_virt = dma_alloc_coherent(dev->mem_dev_r, 1 << MFC_BASE_ALIGN_ORDER,
&bank2_dma_addr, GFP_KERNEL);
- if (IS_ERR(dev->fw_virt_addr)) {
+ if (!bank2_virt) {
mfc_err("Allocating bank2 base failed\n");
dma_free_coherent(dev->mem_dev_l, dev->fw_size,
dev->fw_virt_addr, dev->bank1);
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index 4d93835dec9d..9103258b7df3 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
@@ -436,6 +436,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
int ret = 0;
struct v4l2_pix_format_mplane *pix_mp;
+ struct s5p_mfc_buf_size *buf_size = dev->variant->buf_size;
mfc_debug_enter();
ret = vidioc_try_fmt(file, priv, f);
@@ -459,11 +460,13 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
mfc_debug(2, "The codec number is: %d\n", ctx->codec_mode);
pix_mp->height = 0;
pix_mp->width = 0;
- if (pix_mp->plane_fmt[0].sizeimage)
- ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
- else
+ if (pix_mp->plane_fmt[0].sizeimage == 0)
pix_mp->plane_fmt[0].sizeimage = ctx->dec_src_buf_size =
DEF_CPB_SIZE;
+ else if (pix_mp->plane_fmt[0].sizeimage > buf_size->cpb)
+ ctx->dec_src_buf_size = buf_size->cpb;
+ else
+ ctx->dec_src_buf_size = pix_mp->plane_fmt[0].sizeimage;
pix_mp->plane_fmt[0].bytesperline = 0;
ctx->state = MFCINST_INIT;
ret = 0;
diff --git a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 11d5f1dada32..b6a8be97a96c 100644
--- a/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
+++ b/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
@@ -21,6 +21,8 @@
#include "s5p_mfc_pm.h"
#define MFC_GATE_CLK_NAME "mfc"
+#define MFC_SCLK_NAME "sclk-mfc"
+#define MFC_SCLK_RATE (200 * 1000000)
#define CLK_DEBUG
@@ -50,6 +52,20 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
goto err_p_ip_clk;
}
+ if (dev->variant->version != MFC_VERSION_V6) {
+ pm->clock = clk_get(&dev->plat_dev->dev, MFC_SCLK_NAME);
+ if (IS_ERR(pm->clock)) {
+ mfc_info("Failed to get MFC special clock control\n");
+ } else {
+ clk_set_rate(pm->clock, MFC_SCLK_RATE);
+ ret = clk_prepare_enable(pm->clock);
+ if (ret) {
+ mfc_err("Failed to enable MFC special clock\n");
+ goto err_s_clk;
+ }
+ }
+ }
+
atomic_set(&pm->power, 0);
#ifdef CONFIG_PM_RUNTIME
pm->device = &dev->plat_dev->dev;
@@ -59,6 +75,9 @@ int s5p_mfc_init_pm(struct s5p_mfc_dev *dev)
atomic_set(&clk_ref, 0);
#endif
return 0;
+
+err_s_clk:
+ clk_put(pm->clock);
err_p_ip_clk:
clk_put(pm->clock_gate);
err_g_ip_clk:
@@ -67,6 +86,11 @@ err_g_ip_clk:
void s5p_mfc_final_pm(struct s5p_mfc_dev *dev)
{
+ if (dev->variant->version != MFC_VERSION_V6 &&
+ pm->clock) {
+ clk_disable_unprepare(pm->clock);
+ clk_put(pm->clock);
+ }
clk_unprepare(pm->clock_gate);
clk_put(pm->clock_gate);
#ifdef CONFIG_PM_RUNTIME
diff --git a/drivers/media/platform/s5p-tv/mixer_video.c b/drivers/media/platform/s5p-tv/mixer_video.c
index 8a8dbc8fdfde..b4d2696501e4 100644
--- a/drivers/media/platform/s5p-tv/mixer_video.c
+++ b/drivers/media/platform/s5p-tv/mixer_video.c
@@ -1109,8 +1109,6 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
.ioctl_ops = &mxr_ioctl_ops,
};
strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
- /* let framework control PRIORITY */
- set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
video_set_drvdata(&layer->vfd, layer);
layer->vfd.lock = &layer->mutex;
diff --git a/drivers/media/platform/sh_veu.c b/drivers/media/platform/sh_veu.c
index 744e43b480bc..8dc279d4d561 100644
--- a/drivers/media/platform/sh_veu.c
+++ b/drivers/media/platform/sh_veu.c
@@ -425,7 +425,6 @@ static int sh_veu_g_fmt(struct sh_veu_file *veu_file, struct v4l2_format *f)
pix->bytesperline = vfmt->bytesperline;
pix->sizeimage = vfmt->bytesperline * pix->height *
vfmt->fmt->depth / vfmt->fmt->ydepth;
- pix->priv = 0;
dev_dbg(veu->dev, "%s(): type: %d, size %u @ %ux%u, fmt %x\n", __func__,
f->type, pix->sizeimage, pix->width, pix->height, pix->pixelformat);
@@ -473,7 +472,6 @@ static int sh_veu_try_fmt(struct v4l2_format *f, const struct sh_veu_format *fmt
pix->pixelformat = fmt->fourcc;
pix->colorspace = sh_veu_4cc2cspace(pix->pixelformat);
- pix->priv = 0;
pr_debug("%s(): type: %d, size %u\n", __func__, f->type, pix->sizeimage);
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
index af39c4665554..6540847f4e1d 100644
--- a/drivers/media/platform/soc_camera/Kconfig
+++ b/drivers/media/platform/soc_camera/Kconfig
@@ -17,19 +17,6 @@ config SOC_CAMERA_PLATFORM
help
This is a generic SoC camera platform driver, useful for testing
-config MX1_VIDEO
- bool
-
-config VIDEO_MX1
- tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
- depends on BROKEN
- depends on VIDEO_DEV && ARCH_MX1 && SOC_CAMERA
- select FIQ
- select VIDEOBUF_DMA_CONTIG
- select MX1_VIDEO
- ---help---
- This is a v4l2 driver for the i.MX1/i.MXL CMOS Sensor Interface
-
config VIDEO_MX3
tristate "i.MX3x Camera Sensor Interface driver"
depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
@@ -47,6 +34,7 @@ config VIDEO_PXA27x
config VIDEO_RCAR_VIN
tristate "R-Car Video Input (VIN) support"
depends on VIDEO_DEV && SOC_CAMERA
+ depends on ARCH_SHMOBILE || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select SOC_CAMERA_SCALE_CROP
---help---
@@ -55,12 +43,14 @@ config VIDEO_RCAR_VIN
config VIDEO_SH_MOBILE_CSI2
tristate "SuperH Mobile MIPI CSI-2 Interface driver"
depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+ depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
---help---
This is a v4l2 driver for the SuperH MIPI CSI-2 Interface
config VIDEO_SH_MOBILE_CEU
tristate "SuperH Mobile CEU Interface driver"
depends on VIDEO_DEV && SOC_CAMERA && HAS_DMA && HAVE_CLK
+ depends on ARCH_SHMOBILE || SUPERH || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select SOC_CAMERA_SCALE_CROP
---help---
@@ -76,7 +66,7 @@ config VIDEO_OMAP1
config VIDEO_MX2
tristate "i.MX27 Camera Sensor Interface driver"
- depends on VIDEO_DEV && SOC_CAMERA && MACH_MX27
+ depends on VIDEO_DEV && SOC_CAMERA && SOC_IMX27
select VIDEOBUF2_DMA_CONTIG
---help---
This is a v4l2 driver for the i.MX27 Camera Sensor Interface
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
index 8aed26d7a64d..2826382dc9f8 100644
--- a/drivers/media/platform/soc_camera/Makefile
+++ b/drivers/media/platform/soc_camera/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_SOC_CAMERA_PLATFORM) += soc_camera_platform.o
# soc-camera host drivers have to be linked after camera drivers
obj-$(CONFIG_VIDEO_ATMEL_ISI) += atmel-isi.o
-obj-$(CONFIG_VIDEO_MX1) += mx1_camera.o
obj-$(CONFIG_VIDEO_MX2) += mx2_camera.o
obj-$(CONFIG_VIDEO_MX3) += mx3_camera.o
obj-$(CONFIG_VIDEO_OMAP1) += omap1_camera.o
diff --git a/drivers/media/platform/soc_camera/mx1_camera.c b/drivers/media/platform/soc_camera/mx1_camera.c
deleted file mode 100644
index fea3e61476ae..000000000000
--- a/drivers/media/platform/soc_camera/mx1_camera.c
+++ /dev/null
@@ -1,866 +0,0 @@
-/*
- * V4L2 Driver for i.MXL/i.MXL camera (CSI) host
- *
- * Copyright (C) 2008, Paulius Zaleckas <paulius.zaleckas@teltonika.lt>
- * Copyright (C) 2009, Darius Augulis <augulis.darius@gmail.com>
- *
- * Based on PXA SoC camera driver
- * Copyright (C) 2006, Sascha Hauer, Pengutronix
- * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#include <linux/clk.h>
-#include <linux/delay.h>
-#include <linux/device.h>
-#include <linux/dma-mapping.h>
-#include <linux/errno.h>
-#include <linux/fs.h>
-#include <linux/init.h>
-#include <linux/interrupt.h>
-#include <linux/io.h>
-#include <linux/kernel.h>
-#include <linux/mm.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-#include <linux/platform_device.h>
-#include <linux/sched.h>
-#include <linux/slab.h>
-#include <linux/time.h>
-#include <linux/videodev2.h>
-
-#include <media/soc_camera.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-dev.h>
-#include <media/videobuf-dma-contig.h>
-#include <media/soc_mediabus.h>
-
-#include <asm/dma.h>
-#include <asm/fiq.h>
-#include <mach/dma-mx1-mx2.h>
-#include <mach/hardware.h>
-#include <mach/irqs.h>
-#include <linux/platform_data/camera-mx1.h>
-
-/*
- * CSI registers
- */
-#define CSICR1 0x00 /* CSI Control Register 1 */
-#define CSISR 0x08 /* CSI Status Register */
-#define CSIRXR 0x10 /* CSI RxFIFO Register */
-
-#define CSICR1_RXFF_LEVEL(x) (((x) & 0x3) << 19)
-#define CSICR1_SOF_POL (1 << 17)
-#define CSICR1_SOF_INTEN (1 << 16)
-#define CSICR1_MCLKDIV(x) (((x) & 0xf) << 12)
-#define CSICR1_MCLKEN (1 << 9)
-#define CSICR1_FCC (1 << 8)
-#define CSICR1_BIG_ENDIAN (1 << 7)
-#define CSICR1_CLR_RXFIFO (1 << 5)
-#define CSICR1_GCLK_MODE (1 << 4)
-#define CSICR1_DATA_POL (1 << 2)
-#define CSICR1_REDGE (1 << 1)
-#define CSICR1_EN (1 << 0)
-
-#define CSISR_SFF_OR_INT (1 << 25)
-#define CSISR_RFF_OR_INT (1 << 24)
-#define CSISR_STATFF_INT (1 << 21)
-#define CSISR_RXFF_INT (1 << 18)
-#define CSISR_SOF_INT (1 << 16)
-#define CSISR_DRDY (1 << 0)
-
-#define DRIVER_VERSION "0.0.2"
-#define DRIVER_NAME "mx1-camera"
-
-#define CSI_IRQ_MASK (CSISR_SFF_OR_INT | CSISR_RFF_OR_INT | \
- CSISR_STATFF_INT | CSISR_RXFF_INT | CSISR_SOF_INT)
-
-#define CSI_BUS_FLAGS (V4L2_MBUS_MASTER | V4L2_MBUS_HSYNC_ACTIVE_HIGH | \
- V4L2_MBUS_VSYNC_ACTIVE_HIGH | V4L2_MBUS_VSYNC_ACTIVE_LOW | \
- V4L2_MBUS_PCLK_SAMPLE_RISING | V4L2_MBUS_PCLK_SAMPLE_FALLING | \
- V4L2_MBUS_DATA_ACTIVE_HIGH | V4L2_MBUS_DATA_ACTIVE_LOW)
-
-#define MAX_VIDEO_MEM 16 /* Video memory limit in megabytes */
-
-/*
- * Structures
- */
-
-/* buffer for one video frame */
-struct mx1_buffer {
- /* common v4l buffer stuff -- must be first */
- struct videobuf_buffer vb;
- enum v4l2_mbus_pixelcode code;
- int inwork;
-};
-
-/*
- * i.MX1/i.MXL is only supposed to handle one camera on its Camera Sensor
- * Interface. If anyone ever builds hardware to enable more than
- * one camera, they will have to modify this driver too
- */
-struct mx1_camera_dev {
- struct soc_camera_host soc_host;
- struct mx1_camera_pdata *pdata;
- struct mx1_buffer *active;
- struct resource *res;
- struct clk *clk;
- struct list_head capture;
-
- void __iomem *base;
- int dma_chan;
- unsigned int irq;
- unsigned long mclk;
-
- spinlock_t lock;
-};
-
-/*
- * Videobuf operations
- */
-static int mx1_videobuf_setup(struct videobuf_queue *vq, unsigned int *count,
- unsigned int *size)
-{
- struct soc_camera_device *icd = vq->priv_data;
-
- *size = icd->sizeimage;
-
- if (!*count)
- *count = 32;
-
- if (*size * *count > MAX_VIDEO_MEM * 1024 * 1024)
- *count = (MAX_VIDEO_MEM * 1024 * 1024) / *size;
-
- dev_dbg(icd->parent, "count=%d, size=%d\n", *count, *size);
-
- return 0;
-}
-
-static void free_buffer(struct videobuf_queue *vq, struct mx1_buffer *buf)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct videobuf_buffer *vb = &buf->vb;
-
- BUG_ON(in_interrupt());
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- /*
- * This waits until this buffer is out of danger, i.e., until it is no
- * longer in STATE_QUEUED or STATE_ACTIVE
- */
- videobuf_waiton(vq, vb, 0, 0);
- videobuf_dma_contig_free(vq, vb);
-
- vb->state = VIDEOBUF_NEEDS_INIT;
-}
-
-static int mx1_videobuf_prepare(struct videobuf_queue *vq,
- struct videobuf_buffer *vb, enum v4l2_field field)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
- int ret;
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- /* Added list head initialization on alloc */
- WARN_ON(!list_empty(&vb->queue));
-
- BUG_ON(NULL == icd->current_fmt);
-
- /*
- * I think, in buf_prepare you only have to protect global data,
- * the actual buffer is yours
- */
- buf->inwork = 1;
-
- if (buf->code != icd->current_fmt->code ||
- vb->width != icd->user_width ||
- vb->height != icd->user_height ||
- vb->field != field) {
- buf->code = icd->current_fmt->code;
- vb->width = icd->user_width;
- vb->height = icd->user_height;
- vb->field = field;
- vb->state = VIDEOBUF_NEEDS_INIT;
- }
-
- vb->size = icd->sizeimage;
- if (0 != vb->baddr && vb->bsize < vb->size) {
- ret = -EINVAL;
- goto out;
- }
-
- if (vb->state == VIDEOBUF_NEEDS_INIT) {
- ret = videobuf_iolock(vq, vb, NULL);
- if (ret)
- goto fail;
-
- vb->state = VIDEOBUF_PREPARED;
- }
-
- buf->inwork = 0;
-
- return 0;
-
-fail:
- free_buffer(vq, buf);
-out:
- buf->inwork = 0;
- return ret;
-}
-
-static int mx1_camera_setup_dma(struct mx1_camera_dev *pcdev)
-{
- struct videobuf_buffer *vbuf = &pcdev->active->vb;
- struct device *dev = pcdev->soc_host.icd->parent;
- int ret;
-
- if (unlikely(!pcdev->active)) {
- dev_err(dev, "DMA End IRQ with no active buffer\n");
- return -EFAULT;
- }
-
- /* setup sg list for future DMA */
- ret = imx_dma_setup_single(pcdev->dma_chan,
- videobuf_to_dma_contig(vbuf),
- vbuf->size, pcdev->res->start +
- CSIRXR, DMA_MODE_READ);
- if (unlikely(ret))
- dev_err(dev, "Failed to setup DMA sg list\n");
-
- return ret;
-}
-
-/* Called under spinlock_irqsave(&pcdev->lock, ...) */
-static void mx1_videobuf_queue(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct soc_camera_device *icd = vq->priv_data;
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-
- dev_dbg(icd->parent, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- list_add_tail(&vb->queue, &pcdev->capture);
-
- vb->state = VIDEOBUF_ACTIVE;
-
- if (!pcdev->active) {
- pcdev->active = buf;
-
- /* setup sg list for future DMA */
- if (!mx1_camera_setup_dma(pcdev)) {
- unsigned int temp;
- /* enable SOF irq */
- temp = __raw_readl(pcdev->base + CSICR1) |
- CSICR1_SOF_INTEN;
- __raw_writel(temp, pcdev->base + CSICR1);
- }
- }
-}
-
-static void mx1_videobuf_release(struct videobuf_queue *vq,
- struct videobuf_buffer *vb)
-{
- struct mx1_buffer *buf = container_of(vb, struct mx1_buffer, vb);
-#ifdef DEBUG
- struct soc_camera_device *icd = vq->priv_data;
- struct device *dev = icd->parent;
-
- dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- switch (vb->state) {
- case VIDEOBUF_ACTIVE:
- dev_dbg(dev, "%s (active)\n", __func__);
- break;
- case VIDEOBUF_QUEUED:
- dev_dbg(dev, "%s (queued)\n", __func__);
- break;
- case VIDEOBUF_PREPARED:
- dev_dbg(dev, "%s (prepared)\n", __func__);
- break;
- default:
- dev_dbg(dev, "%s (unknown)\n", __func__);
- break;
- }
-#endif
-
- free_buffer(vq, buf);
-}
-
-static void mx1_camera_wakeup(struct mx1_camera_dev *pcdev,
- struct videobuf_buffer *vb,
- struct mx1_buffer *buf)
-{
- /* _init is used to debug races, see comment in mx1_camera_reqbufs() */
- list_del_init(&vb->queue);
- vb->state = VIDEOBUF_DONE;
- v4l2_get_timestamp(&vb->ts);
- vb->field_count++;
- wake_up(&vb->done);
-
- if (list_empty(&pcdev->capture)) {
- pcdev->active = NULL;
- return;
- }
-
- pcdev->active = list_entry(pcdev->capture.next,
- struct mx1_buffer, vb.queue);
-
- /* setup sg list for future DMA */
- if (likely(!mx1_camera_setup_dma(pcdev))) {
- unsigned int temp;
-
- /* enable SOF irq */
- temp = __raw_readl(pcdev->base + CSICR1) | CSICR1_SOF_INTEN;
- __raw_writel(temp, pcdev->base + CSICR1);
- }
-}
-
-static void mx1_camera_dma_irq(int channel, void *data)
-{
- struct mx1_camera_dev *pcdev = data;
- struct device *dev = pcdev->soc_host.icd->parent;
- struct mx1_buffer *buf;
- struct videobuf_buffer *vb;
- unsigned long flags;
-
- spin_lock_irqsave(&pcdev->lock, flags);
-
- imx_dma_disable(channel);
-
- if (unlikely(!pcdev->active)) {
- dev_err(dev, "DMA End IRQ with no active buffer\n");
- goto out;
- }
-
- vb = &pcdev->active->vb;
- buf = container_of(vb, struct mx1_buffer, vb);
- WARN_ON(buf->inwork || list_empty(&vb->queue));
- dev_dbg(dev, "%s (vb=0x%p) 0x%08lx %d\n", __func__,
- vb, vb->baddr, vb->bsize);
-
- mx1_camera_wakeup(pcdev, vb, buf);
-out:
- spin_unlock_irqrestore(&pcdev->lock, flags);
-}
-
-static struct videobuf_queue_ops mx1_videobuf_ops = {
- .buf_setup = mx1_videobuf_setup,
- .buf_prepare = mx1_videobuf_prepare,
- .buf_queue = mx1_videobuf_queue,
- .buf_release = mx1_videobuf_release,
-};
-
-static void mx1_camera_init_videobuf(struct videobuf_queue *q,
- struct soc_camera_device *icd)
-{
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
-
- videobuf_queue_dma_contig_init(q, &mx1_videobuf_ops, icd->parent,
- &pcdev->lock, V4L2_BUF_TYPE_VIDEO_CAPTURE,
- V4L2_FIELD_NONE,
- sizeof(struct mx1_buffer), icd, &ici->host_lock);
-}
-
-static int mclk_get_divisor(struct mx1_camera_dev *pcdev)
-{
- unsigned int mclk = pcdev->mclk;
- unsigned long div;
- unsigned long lcdclk;
-
- lcdclk = clk_get_rate(pcdev->clk);
-
- /*
- * We verify platform_mclk_10khz != 0, so if anyone breaks it, here
- * they get a nice Oops
- */
- div = (lcdclk + 2 * mclk - 1) / (2 * mclk) - 1;
-
- dev_dbg(pcdev->soc_host.icd->parent,
- "System clock %lukHz, target freq %dkHz, divisor %lu\n",
- lcdclk / 1000, mclk / 1000, div);
-
- return div;
-}
-
-static void mx1_camera_activate(struct mx1_camera_dev *pcdev)
-{
- unsigned int csicr1 = CSICR1_EN;
-
- dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Activate device\n");
-
- clk_prepare_enable(pcdev->clk);
-
- /* enable CSI before doing anything else */
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- csicr1 |= CSICR1_MCLKEN | CSICR1_FCC | CSICR1_GCLK_MODE;
- csicr1 |= CSICR1_MCLKDIV(mclk_get_divisor(pcdev));
- csicr1 |= CSICR1_RXFF_LEVEL(2); /* 16 words */
-
- __raw_writel(csicr1, pcdev->base + CSICR1);
-}
-
-static void mx1_camera_deactivate(struct mx1_camera_dev *pcdev)
-{
- dev_dbg(pcdev->soc_host.v4l2_dev.dev, "Deactivate device\n");
-
- /* Disable all CSI interface */
- __raw_writel(0x00, pcdev->base + CSICR1);
-
- clk_disable_unprepare(pcdev->clk);
-}
-
-static int mx1_camera_add_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX1 Camera driver attached to camera %d\n",
- icd->devnum);
-
- return 0;
-}
-
-static void mx1_camera_remove_device(struct soc_camera_device *icd)
-{
- dev_info(icd->parent, "MX1 Camera driver detached from camera %d\n",
- icd->devnum);
-}
-
-/*
- * The following two functions absolutely depend on the fact, that
- * there can be only one camera on i.MX1/i.MXL camera sensor interface
- */
-static int mx1_camera_clock_start(struct soc_camera_host *ici)
-{
- struct mx1_camera_dev *pcdev = ici->priv;
-
- mx1_camera_activate(pcdev);
-
- return 0;
-}
-
-static void mx1_camera_clock_stop(struct soc_camera_host *ici)
-{
- struct mx1_camera_dev *pcdev = ici->priv;
- unsigned int csicr1;
-
- /* disable interrupts */
- csicr1 = __raw_readl(pcdev->base + CSICR1) & ~CSI_IRQ_MASK;
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- /* Stop DMA engine */
- imx_dma_disable(pcdev->dma_chan);
-
- mx1_camera_deactivate(pcdev);
-}
-
-static int mx1_camera_set_bus_param(struct soc_camera_device *icd)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
- struct mx1_camera_dev *pcdev = ici->priv;
- struct v4l2_mbus_config cfg = {.type = V4L2_MBUS_PARALLEL,};
- unsigned long common_flags;
- unsigned int csicr1;
- int ret;
-
- /* MX1 supports only 8bit buswidth */
- ret = v4l2_subdev_call(sd, video, g_mbus_config, &cfg);
- if (!ret) {
- common_flags = soc_mbus_config_compatible(&cfg, CSI_BUS_FLAGS);
- if (!common_flags) {
- dev_warn(icd->parent,
- "Flags incompatible: camera 0x%x, host 0x%x\n",
- cfg.flags, CSI_BUS_FLAGS);
- return -EINVAL;
- }
- } else if (ret != -ENOIOCTLCMD) {
- return ret;
- } else {
- common_flags = CSI_BUS_FLAGS;
- }
-
- /* Make choises, based on platform choice */
- if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_VSYNC_HIGH)
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
- else
- common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
- }
-
- if ((common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) &&
- (common_flags & V4L2_MBUS_PCLK_SAMPLE_FALLING)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_PCLK_RISING)
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_FALLING;
- else
- common_flags &= ~V4L2_MBUS_PCLK_SAMPLE_RISING;
- }
-
- if ((common_flags & V4L2_MBUS_DATA_ACTIVE_HIGH) &&
- (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)) {
- if (!pcdev->pdata ||
- pcdev->pdata->flags & MX1_CAMERA_DATA_HIGH)
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_LOW;
- else
- common_flags &= ~V4L2_MBUS_DATA_ACTIVE_HIGH;
- }
-
- cfg.flags = common_flags;
- ret = v4l2_subdev_call(sd, video, s_mbus_config, &cfg);
- if (ret < 0 && ret != -ENOIOCTLCMD) {
- dev_dbg(icd->parent, "camera s_mbus_config(0x%lx) returned %d\n",
- common_flags, ret);
- return ret;
- }
-
- csicr1 = __raw_readl(pcdev->base + CSICR1);
-
- if (common_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
- csicr1 |= CSICR1_REDGE;
- if (common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH)
- csicr1 |= CSICR1_SOF_POL;
- if (common_flags & V4L2_MBUS_DATA_ACTIVE_LOW)
- csicr1 |= CSICR1_DATA_POL;
-
- __raw_writel(csicr1, pcdev->base + CSICR1);
-
- return 0;
-}
-
-static int mx1_camera_set_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
- int ret, buswidth;
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- buswidth = xlate->host_fmt->bits_per_sample;
- if (buswidth > 8) {
- dev_warn(icd->parent,
- "bits-per-sample %d for format %x unsupported\n",
- buswidth, pix->pixelformat);
- return -EINVAL;
- }
-
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
-
- ret = v4l2_subdev_call(sd, video, s_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
-
- if (mf.code != xlate->code)
- return -EINVAL;
-
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
- icd->current_fmt = xlate;
-
- return ret;
-}
-
-static int mx1_camera_try_fmt(struct soc_camera_device *icd,
- struct v4l2_format *f)
-{
- struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
- const struct soc_camera_format_xlate *xlate;
- struct v4l2_pix_format *pix = &f->fmt.pix;
- struct v4l2_mbus_framefmt mf;
- int ret;
- /* TODO: limit to mx1 hardware capabilities */
-
- xlate = soc_camera_xlate_by_fourcc(icd, pix->pixelformat);
- if (!xlate) {
- dev_warn(icd->parent, "Format %x not found\n",
- pix->pixelformat);
- return -EINVAL;
- }
-
- mf.width = pix->width;
- mf.height = pix->height;
- mf.field = pix->field;
- mf.colorspace = pix->colorspace;
- mf.code = xlate->code;
-
- /* limit to sensor capabilities */
- ret = v4l2_subdev_call(sd, video, try_mbus_fmt, &mf);
- if (ret < 0)
- return ret;
-
- pix->width = mf.width;
- pix->height = mf.height;
- pix->field = mf.field;
- pix->colorspace = mf.colorspace;
-
- return 0;
-}
-
-static int mx1_camera_reqbufs(struct soc_camera_device *icd,
- struct v4l2_requestbuffers *p)
-{
- int i;
-
- /*
- * This is for locking debugging only. I removed spinlocks and now I
- * check whether .prepare is ever called on a linked buffer, or whether
- * a dma IRQ can occur for an in-work or unlinked buffer. Until now
- * it hadn't triggered
- */
- for (i = 0; i < p->count; i++) {
- struct mx1_buffer *buf = container_of(icd->vb_vidq.bufs[i],
- struct mx1_buffer, vb);
- buf->inwork = 0;
- INIT_LIST_HEAD(&buf->vb.queue);
- }
-
- return 0;
-}
-
-static unsigned int mx1_camera_poll(struct file *file, poll_table *pt)
-{
- struct soc_camera_device *icd = file->private_data;
- struct mx1_buffer *buf;
-
- buf = list_entry(icd->vb_vidq.stream.next, struct mx1_buffer,
- vb.stream);
-
- poll_wait(file, &buf->vb.done, pt);
-
- if (buf->vb.state == VIDEOBUF_DONE ||
- buf->vb.state == VIDEOBUF_ERROR)
- return POLLIN | POLLRDNORM;
-
- return 0;
-}
-
-static int mx1_camera_querycap(struct soc_camera_host *ici,
- struct v4l2_capability *cap)
-{
- /* cap->name is set by the friendly caller:-> */
- strlcpy(cap->card, "i.MX1/i.MXL Camera", sizeof(cap->card));
- cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-
- return 0;
-}
-
-static struct soc_camera_host_ops mx1_soc_camera_host_ops = {
- .owner = THIS_MODULE,
- .add = mx1_camera_add_device,
- .remove = mx1_camera_remove_device,
- .clock_start = mx1_camera_clock_start,
- .clock_stop = mx1_camera_clock_stop,
- .set_bus_param = mx1_camera_set_bus_param,
- .set_fmt = mx1_camera_set_fmt,
- .try_fmt = mx1_camera_try_fmt,
- .init_videobuf = mx1_camera_init_videobuf,
- .reqbufs = mx1_camera_reqbufs,
- .poll = mx1_camera_poll,
- .querycap = mx1_camera_querycap,
-};
-
-static struct fiq_handler fh = {
- .name = "csi_sof"
-};
-
-static int __init mx1_camera_probe(struct platform_device *pdev)
-{
- struct mx1_camera_dev *pcdev;
- struct resource *res;
- struct pt_regs regs;
- struct clk *clk;
- void __iomem *base;
- unsigned int irq;
- int err = 0;
-
- res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
- irq = platform_get_irq(pdev, 0);
- if (!res || (int)irq <= 0) {
- err = -ENODEV;
- goto exit;
- }
-
- clk = clk_get(&pdev->dev, "csi_clk");
- if (IS_ERR(clk)) {
- err = PTR_ERR(clk);
- goto exit;
- }
-
- pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
- if (!pcdev) {
- dev_err(&pdev->dev, "Could not allocate pcdev\n");
- err = -ENOMEM;
- goto exit_put_clk;
- }
-
- pcdev->res = res;
- pcdev->clk = clk;
-
- pcdev->pdata = pdev->dev.platform_data;
-
- if (pcdev->pdata)
- pcdev->mclk = pcdev->pdata->mclk_10khz * 10000;
-
- if (!pcdev->mclk) {
- dev_warn(&pdev->dev,
- "mclk_10khz == 0! Please, fix your platform data. "
- "Using default 20MHz\n");
- pcdev->mclk = 20000000;
- }
-
- INIT_LIST_HEAD(&pcdev->capture);
- spin_lock_init(&pcdev->lock);
-
- /*
- * Request the regions.
- */
- if (!request_mem_region(res->start, resource_size(res), DRIVER_NAME)) {
- err = -EBUSY;
- goto exit_kfree;
- }
-
- base = ioremap(res->start, resource_size(res));
- if (!base) {
- err = -ENOMEM;
- goto exit_release;
- }
- pcdev->irq = irq;
- pcdev->base = base;
-
- /* request dma */
- pcdev->dma_chan = imx_dma_request_by_prio(DRIVER_NAME, DMA_PRIO_HIGH);
- if (pcdev->dma_chan < 0) {
- dev_err(&pdev->dev, "Can't request DMA for MX1 CSI\n");
- err = -EBUSY;
- goto exit_iounmap;
- }
- dev_dbg(&pdev->dev, "got DMA channel %d\n", pcdev->dma_chan);
-
- imx_dma_setup_handlers(pcdev->dma_chan, mx1_camera_dma_irq, NULL,
- pcdev);
-
- imx_dma_config_channel(pcdev->dma_chan, IMX_DMA_TYPE_FIFO,
- IMX_DMA_MEMSIZE_32, MX1_DMA_REQ_CSI_R, 0);
- /* burst length : 16 words = 64 bytes */
- imx_dma_config_burstlen(pcdev->dma_chan, 0);
-
- /* request irq */
- err = claim_fiq(&fh);
- if (err) {
- dev_err(&pdev->dev, "Camera interrupt register failed\n");
- goto exit_free_dma;
- }
-
- set_fiq_handler(&mx1_camera_sof_fiq_start, &mx1_camera_sof_fiq_end -
- &mx1_camera_sof_fiq_start);
-
- regs.ARM_r8 = (long)MX1_DMA_DIMR;
- regs.ARM_r9 = (long)MX1_DMA_CCR(pcdev->dma_chan);
- regs.ARM_r10 = (long)pcdev->base + CSICR1;
- regs.ARM_fp = (long)pcdev->base + CSISR;
- regs.ARM_sp = 1 << pcdev->dma_chan;
- set_fiq_regs(&regs);
-
- mxc_set_irq_fiq(irq, 1);
- enable_fiq(irq);
-
- pcdev->soc_host.drv_name = DRIVER_NAME;
- pcdev->soc_host.ops = &mx1_soc_camera_host_ops;
- pcdev->soc_host.priv = pcdev;
- pcdev->soc_host.v4l2_dev.dev = &pdev->dev;
- pcdev->soc_host.nr = pdev->id;
- err = soc_camera_host_register(&pcdev->soc_host);
- if (err)
- goto exit_free_irq;
-
- dev_info(&pdev->dev, "MX1 Camera driver loaded\n");
-
- return 0;
-
-exit_free_irq:
- disable_fiq(irq);
- mxc_set_irq_fiq(irq, 0);
- release_fiq(&fh);
-exit_free_dma:
- imx_dma_free(pcdev->dma_chan);
-exit_iounmap:
- iounmap(base);
-exit_release:
- release_mem_region(res->start, resource_size(res));
-exit_kfree:
- kfree(pcdev);
-exit_put_clk:
- clk_put(clk);
-exit:
- return err;
-}
-
-static int __exit mx1_camera_remove(struct platform_device *pdev)
-{
- struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
- struct mx1_camera_dev *pcdev = container_of(soc_host,
- struct mx1_camera_dev, soc_host);
- struct resource *res;
-
- imx_dma_free(pcdev->dma_chan);
- disable_fiq(pcdev->irq);
- mxc_set_irq_fiq(pcdev->irq, 0);
- release_fiq(&fh);
-
- clk_put(pcdev->clk);
-
- soc_camera_host_unregister(soc_host);
-
- iounmap(pcdev->base);
-
- res = pcdev->res;
- release_mem_region(res->start, resource_size(res));
-
- kfree(pcdev);
-
- dev_info(&pdev->dev, "MX1 Camera driver unloaded\n");
-
- return 0;
-}
-
-static struct platform_driver mx1_camera_driver = {
- .driver = {
- .name = DRIVER_NAME,
- },
- .remove = __exit_p(mx1_camera_remove),
-};
-
-module_platform_driver_probe(mx1_camera_driver, mx1_camera_probe);
-
-MODULE_DESCRIPTION("i.MX1/i.MXL SoC Camera Host driver");
-MODULE_AUTHOR("Paulius Zaleckas <paulius.zaleckas@teltonika.lt>");
-MODULE_LICENSE("GPL v2");
-MODULE_VERSION(DRIVER_VERSION);
-MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/media/platform/soc_camera/rcar_vin.c b/drivers/media/platform/soc_camera/rcar_vin.c
index e594230e84d3..7c4299d9a100 100644
--- a/drivers/media/platform/soc_camera/rcar_vin.c
+++ b/drivers/media/platform/soc_camera/rcar_vin.c
@@ -126,13 +126,13 @@ struct rcar_vin_priv {
int sequence;
/* State of the VIN module in capturing mode */
enum rcar_vin_state state;
- struct rcar_vin_platform_data *pdata;
struct soc_camera_host ici;
struct list_head capture;
#define MAX_BUFFER_NUM 3
struct vb2_buffer *queue_buf[MAX_BUFFER_NUM];
struct vb2_alloc_ctx *alloc_ctx;
enum v4l2_field field;
+ unsigned int pdata_flags;
unsigned int vb_count;
unsigned int nr_hw_slots;
bool request_to_stop;
@@ -275,12 +275,12 @@ static int rcar_vin_setup(struct rcar_vin_priv *priv)
break;
case V4L2_MBUS_FMT_YUYV8_2X8:
/* BT.656 8bit YCbCr422 or BT.601 8bit YCbCr422 */
- vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV8_BT656 : VNMC_INF_YUV8_BT601;
break;
case V4L2_MBUS_FMT_YUYV10_2X10:
/* BT.656 10bit YCbCr422 or BT.601 10bit YCbCr422 */
- vnmc |= priv->pdata->flags & RCAR_VIN_BT656 ?
+ vnmc |= priv->pdata_flags & RCAR_VIN_BT656 ?
VNMC_INF_YUV10_BT656 : VNMC_INF_YUV10_BT601;
break;
default:
@@ -797,7 +797,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
/* Make choises, based on platform preferences */
if ((common_flags & V4L2_MBUS_HSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_HSYNC_ACTIVE_LOW)) {
- if (priv->pdata->flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
+ if (priv->pdata_flags & RCAR_VIN_HSYNC_ACTIVE_LOW)
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_HSYNC_ACTIVE_LOW;
@@ -805,7 +805,7 @@ static int rcar_vin_set_bus_param(struct soc_camera_device *icd)
if ((common_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH) &&
(common_flags & V4L2_MBUS_VSYNC_ACTIVE_LOW)) {
- if (priv->pdata->flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
+ if (priv->pdata_flags & RCAR_VIN_VSYNC_ACTIVE_LOW)
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_HIGH;
else
common_flags &= ~V4L2_MBUS_VSYNC_ACTIVE_LOW;
@@ -1445,7 +1445,7 @@ static int rcar_vin_probe(struct platform_device *pdev)
priv->ici.drv_name = dev_name(&pdev->dev);
priv->ici.ops = &rcar_vin_host_ops;
- priv->pdata = pdata;
+ priv->pdata_flags = pdata->flags;
priv->chip = pdev->id_entry->driver_data;
spin_lock_init(&priv->lock);
INIT_LIST_HEAD(&priv->capture);
diff --git a/drivers/media/platform/soc_camera/soc_camera.c b/drivers/media/platform/soc_camera/soc_camera.c
index 7fec8cdaf095..dc626b9a177d 100644
--- a/drivers/media/platform/soc_camera/soc_camera.c
+++ b/drivers/media/platform/soc_camera/soc_camera.c
@@ -1524,14 +1524,14 @@ static int scan_async_group(struct soc_camera_host *ici,
ret = soc_camera_dyn_pdev(&sdesc, sasc);
if (ret < 0)
- return ret;
+ goto eallocpdev;
sasc->sensor = &sasd->asd;
icd = soc_camera_add_pdev(sasc);
if (!icd) {
- platform_device_put(sasc->pdev);
- return -ENOMEM;
+ ret = -ENOMEM;
+ goto eaddpdev;
}
sasc->notifier.subdevs = asd;
@@ -1559,7 +1559,11 @@ static int scan_async_group(struct soc_camera_host *ici,
v4l2_clk_unregister(icd->clk);
eclkreg:
icd->clk = NULL;
- platform_device_unregister(sasc->pdev);
+ platform_device_del(sasc->pdev);
+eaddpdev:
+ platform_device_put(sasc->pdev);
+eallocpdev:
+ devm_kfree(ici->v4l2_dev.dev, sasc);
dev_err(ici->v4l2_dev.dev, "group probe failed: %d\n", ret);
return ret;
diff --git a/drivers/media/platform/vino.c b/drivers/media/platform/vino.c
index 470d35336119..91d44ea16f27 100644
--- a/drivers/media/platform/vino.c
+++ b/drivers/media/platform/vino.c
@@ -3147,7 +3147,6 @@ static int vino_try_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[tempvcs.data_format].colorspace;
- pf->priv = 0;
return 0;
}
@@ -3175,8 +3174,6 @@ static int vino_g_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[vcs->data_format].colorspace;
- pf->priv = 0;
-
spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
@@ -3219,8 +3216,6 @@ static int vino_s_fmt_vid_cap(struct file *file, void *__fh,
pf->colorspace =
vino_data_formats[vcs->data_format].colorspace;
- pf->priv = 0;
-
spin_unlock_irqrestore(&vino_drvdata->input_lock, flags);
return 0;
}
diff --git a/drivers/media/platform/vivi.c b/drivers/media/platform/vivi.c
index d00bf3df0f8a..80333714ffa7 100644
--- a/drivers/media/platform/vivi.c
+++ b/drivers/media/platform/vivi.c
@@ -648,13 +648,13 @@ static void vivi_fillbuff(struct vivi_dev *dev, struct vivi_buffer *buf)
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " int32 %d, int64 %lld, bitmask %08x ",
dev->int32->cur.val,
- dev->int64->cur.val64,
+ *dev->int64->p_cur.p_s64,
dev->bitmask->cur.val);
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " boolean %d, menu %s, string \"%s\" ",
dev->boolean->cur.val,
dev->menu->qmenu[dev->menu->cur.val],
- dev->string->cur.string);
+ dev->string->p_cur.p_char);
gen_text(dev, vbuf, line++ * 16, 16, str);
snprintf(str, sizeof(str), " integer_menu %lld, value %d ",
dev->int_menu->qmenu_int[dev->int_menu->cur.val],
@@ -1014,7 +1014,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
else
f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1236,7 +1235,7 @@ static const struct v4l2_ctrl_config vivi_ctrl_int32 = {
.id = VIVI_CID_CUSTOM_BASE + 2,
.name = "Integer 32 Bits",
.type = V4L2_CTRL_TYPE_INTEGER,
- .min = 0x80000000,
+ .min = -0x80000000LL,
.max = 0x7fffffff,
.step = 1,
};
@@ -1246,6 +1245,9 @@ static const struct v4l2_ctrl_config vivi_ctrl_int64 = {
.id = VIVI_CID_CUSTOM_BASE + 3,
.name = "Integer 64 Bits",
.type = V4L2_CTRL_TYPE_INTEGER64,
+ .min = LLONG_MIN,
+ .max = LLONG_MAX,
+ .step = 1,
};
static const char * const vivi_ctrl_menu_strings[] = {
@@ -1459,7 +1461,6 @@ static int __init vivi_create_instance(int inst)
vfd->debug = debug;
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->queue = q;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
/*
* Provide a mutex to v4l2 core. It will be used to protect
diff --git a/drivers/media/platform/vsp1/vsp1.h b/drivers/media/platform/vsp1/vsp1.h
index 6ca2cf20d545..12467191dff4 100644
--- a/drivers/media/platform/vsp1/vsp1.h
+++ b/drivers/media/platform/vsp1/vsp1.h
@@ -36,9 +36,9 @@ struct vsp1_rwpf;
struct vsp1_sru;
struct vsp1_uds;
-#define VPS1_MAX_RPF 5
-#define VPS1_MAX_UDS 3
-#define VPS1_MAX_WPF 4
+#define VSP1_MAX_RPF 5
+#define VSP1_MAX_UDS 3
+#define VSP1_MAX_WPF 4
struct vsp1_device {
struct device *dev;
@@ -55,10 +55,10 @@ struct vsp1_device {
struct vsp1_hsit *hst;
struct vsp1_lif *lif;
struct vsp1_lut *lut;
- struct vsp1_rwpf *rpf[VPS1_MAX_RPF];
+ struct vsp1_rwpf *rpf[VSP1_MAX_RPF];
struct vsp1_sru *sru;
- struct vsp1_uds *uds[VPS1_MAX_UDS];
- struct vsp1_rwpf *wpf[VPS1_MAX_WPF];
+ struct vsp1_uds *uds[VSP1_MAX_UDS];
+ struct vsp1_rwpf *wpf[VSP1_MAX_WPF];
struct list_head entities;
@@ -66,7 +66,7 @@ struct vsp1_device {
struct media_device media_dev;
};
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1);
+int vsp1_device_get(struct vsp1_device *vsp1);
void vsp1_device_put(struct vsp1_device *vsp1);
static inline u32 vsp1_read(struct vsp1_device *vsp1, u32 reg)
diff --git a/drivers/media/platform/vsp1/vsp1_bru.c b/drivers/media/platform/vsp1/vsp1_bru.c
index f80695480060..a0c1984c733e 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.c
+++ b/drivers/media/platform/vsp1/vsp1_bru.c
@@ -18,6 +18,7 @@
#include "vsp1.h"
#include "vsp1_bru.h"
+#include "vsp1_rwpf.h"
#define BRU_MIN_SIZE 4U
#define BRU_MAX_SIZE 8190U
@@ -37,19 +38,47 @@ static inline void vsp1_bru_write(struct vsp1_bru *bru, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
+ * Controls
*/
-static bool bru_is_input_enabled(struct vsp1_bru *bru, unsigned int input)
+static int bru_s_ctrl(struct v4l2_ctrl *ctrl)
{
- return media_entity_remote_pad(&bru->entity.pads[input]) != NULL;
+ struct vsp1_bru *bru =
+ container_of(ctrl->handler, struct vsp1_bru, ctrls);
+
+ if (!vsp1_entity_is_streaming(&bru->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_BG_COLOR:
+ vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL, ctrl->val |
+ (0xff << VI6_BRU_VIRRPF_COL_A_SHIFT));
+ break;
+ }
+
+ return 0;
}
+static const struct v4l2_ctrl_ops bru_ctrl_ops = {
+ .s_ctrl = bru_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
{
+ struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
struct vsp1_bru *bru = to_bru(subdev);
struct v4l2_mbus_framefmt *format;
+ unsigned int flags;
unsigned int i;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&bru->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
@@ -62,18 +91,19 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
* to sane default values for now.
*/
- /* Disable both color data normalization and dithering. */
- vsp1_bru_write(bru, VI6_BRU_INCTRL, 0);
-
- /* Set the background position to cover the whole output image and
- * set its color to opaque black.
+ /* Disable dithering and enable color data normalization unless the
+ * format at the pipeline output is premultiplied.
*/
+ flags = pipe->output ? pipe->output->video.format.flags : 0;
+ vsp1_bru_write(bru, VI6_BRU_INCTRL,
+ flags & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA ?
+ 0 : VI6_BRU_INCTRL_NRM);
+
+ /* Set the background position to cover the whole output image. */
vsp1_bru_write(bru, VI6_BRU_VIRRPF_SIZE,
(format->width << VI6_BRU_VIRRPF_SIZE_HSIZE_SHIFT) |
(format->height << VI6_BRU_VIRRPF_SIZE_VSIZE_SHIFT));
vsp1_bru_write(bru, VI6_BRU_VIRRPF_LOC, 0);
- vsp1_bru_write(bru, VI6_BRU_VIRRPF_COL,
- 0xff << VI6_BRU_VIRRPF_COL_A_SHIFT);
/* Route BRU input 1 as SRC input to the ROP unit and configure the ROP
* unit with a NOP operation to make BRU input 1 available as the
@@ -84,6 +114,7 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
VI6_BRU_ROP_AROP(VI6_ROP_NOP));
for (i = 0; i < 4; ++i) {
+ bool premultiplied = false;
u32 ctrl = 0;
/* Configure all Blend/ROP units corresponding to an enabled BRU
@@ -91,11 +122,15 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
* disabled BRU inputs are used in ROP NOP mode to ignore the
* SRC input.
*/
- if (bru_is_input_enabled(bru, i))
+ if (bru->inputs[i].rpf) {
ctrl |= VI6_BRU_CTRL_RBC;
- else
+
+ premultiplied = bru->inputs[i].rpf->video.format.flags
+ & V4L2_PIX_FMT_FLAG_PREMUL_ALPHA;
+ } else {
ctrl |= VI6_BRU_CTRL_CROP(VI6_ROP_NOP)
| VI6_BRU_CTRL_AROP(VI6_ROP_NOP);
+ }
/* Select the virtual RPF as the Blend/ROP unit A DST input to
* serve as a background color.
@@ -117,10 +152,18 @@ static int bru_s_stream(struct v4l2_subdev *subdev, int enable)
*
* DSTc = DSTc * (1 - SRCa) + SRCc * SRCa
* DSTa = DSTa * (1 - SRCa) + SRCa
+ *
+ * when the SRC input isn't premultiplied, and to
+ *
+ * DSTc = DSTc * (1 - SRCa) + SRCc
+ * DSTa = DSTa * (1 - SRCa) + SRCa
+ *
+ * otherwise.
*/
vsp1_bru_write(bru, VI6_BRU_BLD(i),
VI6_BRU_BLD_CCMDX_255_SRC_A |
- VI6_BRU_BLD_CCMDY_SRC_A |
+ (premultiplied ? VI6_BRU_BLD_CCMDY_COEFY :
+ VI6_BRU_BLD_CCMDY_SRC_A) |
VI6_BRU_BLD_ACMDX_255_SRC_A |
VI6_BRU_BLD_ACMDY_COEFY |
(0xff << VI6_BRU_BLD_COEFY_SHIFT));
@@ -192,7 +235,7 @@ static struct v4l2_rect *bru_get_compose(struct vsp1_bru *bru,
case V4L2_SUBDEV_FORMAT_TRY:
return v4l2_subdev_get_try_crop(fh, pad);
case V4L2_SUBDEV_FORMAT_ACTIVE:
- return &bru->compose[pad];
+ return &bru->inputs[pad].compose;
default:
return NULL;
}
@@ -391,5 +434,19 @@ struct vsp1_bru *vsp1_bru_create(struct vsp1_device *vsp1)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&bru->ctrls, 1);
+ v4l2_ctrl_new_std(&bru->ctrls, &bru_ctrl_ops, V4L2_CID_BG_COLOR,
+ 0, 0xffffff, 1, 0);
+
+ bru->entity.subdev.ctrl_handler = &bru->ctrls;
+
+ if (bru->ctrls.error) {
+ dev_err(vsp1->dev, "bru: failed to initialize controls\n");
+ ret = bru->ctrls.error;
+ vsp1_entity_destroy(&bru->entity);
+ return ERR_PTR(ret);
+ }
+
return bru;
}
diff --git a/drivers/media/platform/vsp1/vsp1_bru.h b/drivers/media/platform/vsp1/vsp1_bru.h
index 37062704dbf6..16b1c6554911 100644
--- a/drivers/media/platform/vsp1/vsp1_bru.h
+++ b/drivers/media/platform/vsp1/vsp1_bru.h
@@ -14,11 +14,13 @@
#define __VSP1_BRU_H__
#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include "vsp1_entity.h"
struct vsp1_device;
+struct vsp1_rwpf;
#define BRU_PAD_SINK(n) (n)
#define BRU_PAD_SOURCE 4
@@ -26,7 +28,12 @@ struct vsp1_device;
struct vsp1_bru {
struct vsp1_entity entity;
- struct v4l2_rect compose[4];
+ struct v4l2_ctrl_handler ctrls;
+
+ struct {
+ struct vsp1_rwpf *rpf;
+ struct v4l2_rect compose;
+ } inputs[4];
};
static inline struct vsp1_bru *to_bru(struct v4l2_subdev *subdev)
diff --git a/drivers/media/platform/vsp1/vsp1_drv.c b/drivers/media/platform/vsp1/vsp1_drv.c
index c69ee0657f75..3e6601b5b4de 100644
--- a/drivers/media/platform/vsp1/vsp1_drv.c
+++ b/drivers/media/platform/vsp1/vsp1_drv.c
@@ -345,36 +345,32 @@ static int vsp1_device_init(struct vsp1_device *vsp1)
* Increment the VSP1 reference count and initialize the device if the first
* reference is taken.
*
- * Return a pointer to the VSP1 device or NULL if an error occurred.
+ * Return 0 on success or a negative error code otherwise.
*/
-struct vsp1_device *vsp1_device_get(struct vsp1_device *vsp1)
+int vsp1_device_get(struct vsp1_device *vsp1)
{
- struct vsp1_device *__vsp1 = vsp1;
- int ret;
+ int ret = 0;
mutex_lock(&vsp1->lock);
if (vsp1->ref_count > 0)
goto done;
ret = clk_prepare_enable(vsp1->clock);
- if (ret < 0) {
- __vsp1 = NULL;
+ if (ret < 0)
goto done;
- }
ret = vsp1_device_init(vsp1);
if (ret < 0) {
clk_disable_unprepare(vsp1->clock);
- __vsp1 = NULL;
goto done;
}
done:
- if (__vsp1)
+ if (!ret)
vsp1->ref_count++;
mutex_unlock(&vsp1->lock);
- return __vsp1;
+ return ret;
}
/*
@@ -440,19 +436,19 @@ static int vsp1_validate_platform_data(struct platform_device *pdev,
return -EINVAL;
}
- if (pdata->rpf_count <= 0 || pdata->rpf_count > VPS1_MAX_RPF) {
+ if (pdata->rpf_count <= 0 || pdata->rpf_count > VSP1_MAX_RPF) {
dev_err(&pdev->dev, "invalid number of RPF (%u)\n",
pdata->rpf_count);
return -EINVAL;
}
- if (pdata->uds_count <= 0 || pdata->uds_count > VPS1_MAX_UDS) {
+ if (pdata->uds_count <= 0 || pdata->uds_count > VSP1_MAX_UDS) {
dev_err(&pdev->dev, "invalid number of UDS (%u)\n",
pdata->uds_count);
return -EINVAL;
}
- if (pdata->wpf_count <= 0 || pdata->wpf_count > VPS1_MAX_WPF) {
+ if (pdata->wpf_count <= 0 || pdata->wpf_count > VSP1_MAX_WPF) {
dev_err(&pdev->dev, "invalid number of WPF (%u)\n",
pdata->wpf_count);
return -EINVAL;
diff --git a/drivers/media/platform/vsp1/vsp1_entity.c b/drivers/media/platform/vsp1/vsp1_entity.c
index 44167834285d..79af71d5e270 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.c
+++ b/drivers/media/platform/vsp1/vsp1_entity.c
@@ -20,6 +20,42 @@
#include "vsp1.h"
#include "vsp1_entity.h"
+#include "vsp1_video.h"
+
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity)
+{
+ bool streaming;
+
+ mutex_lock(&entity->lock);
+ streaming = entity->streaming;
+ mutex_unlock(&entity->lock);
+
+ return streaming;
+}
+
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming)
+{
+ int ret;
+
+ mutex_lock(&entity->lock);
+ entity->streaming = streaming;
+ mutex_unlock(&entity->lock);
+
+ if (!streaming)
+ return 0;
+
+ if (!entity->subdev.ctrl_handler)
+ return 0;
+
+ ret = v4l2_ctrl_handler_setup(entity->subdev.ctrl_handler);
+ if (ret < 0) {
+ mutex_lock(&entity->lock);
+ entity->streaming = false;
+ mutex_unlock(&entity->lock);
+ }
+
+ return ret;
+}
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Operations
@@ -157,6 +193,8 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
if (i == ARRAY_SIZE(vsp1_routes))
return -EINVAL;
+ mutex_init(&entity->lock);
+
entity->vsp1 = vsp1;
entity->source_pad = num_pads - 1;
@@ -185,7 +223,11 @@ int vsp1_entity_init(struct vsp1_device *vsp1, struct vsp1_entity *entity,
void vsp1_entity_destroy(struct vsp1_entity *entity)
{
+ if (entity->video)
+ vsp1_video_cleanup(entity->video);
if (entity->subdev.ctrl_handler)
v4l2_ctrl_handler_free(entity->subdev.ctrl_handler);
media_entity_cleanup(&entity->subdev.entity);
+
+ mutex_destroy(&entity->lock);
}
diff --git a/drivers/media/platform/vsp1/vsp1_entity.h b/drivers/media/platform/vsp1/vsp1_entity.h
index 7afbd8a7ba66..aa20aaa58208 100644
--- a/drivers/media/platform/vsp1/vsp1_entity.h
+++ b/drivers/media/platform/vsp1/vsp1_entity.h
@@ -14,10 +14,12 @@
#define __VSP1_ENTITY_H__
#include <linux/list.h>
+#include <linux/mutex.h>
#include <media/v4l2-subdev.h>
struct vsp1_device;
+struct vsp1_video;
enum vsp1_entity_type {
VSP1_ENTITY_BRU,
@@ -68,6 +70,11 @@ struct vsp1_entity {
struct v4l2_subdev subdev;
struct v4l2_mbus_framefmt *formats;
+
+ struct vsp1_video *video;
+
+ struct mutex lock; /* Protects the streaming field */
+ bool streaming;
};
static inline struct vsp1_entity *to_vsp1_entity(struct v4l2_subdev *subdev)
@@ -89,4 +96,7 @@ vsp1_entity_get_pad_format(struct vsp1_entity *entity,
void vsp1_entity_init_formats(struct v4l2_subdev *subdev,
struct v4l2_subdev_fh *fh);
+bool vsp1_entity_is_streaming(struct vsp1_entity *entity);
+int vsp1_entity_set_streaming(struct vsp1_entity *entity, bool streaming);
+
#endif /* __VSP1_ENTITY_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_regs.h b/drivers/media/platform/vsp1/vsp1_regs.h
index 3e74b44286f6..55f163d32d15 100644
--- a/drivers/media/platform/vsp1/vsp1_regs.h
+++ b/drivers/media/platform/vsp1/vsp1_regs.h
@@ -336,7 +336,9 @@
*/
#define VI6_SRU_CTRL0 0x2200
+#define VI6_SRU_CTRL0_PARAM0_MASK (0x1ff << 16)
#define VI6_SRU_CTRL0_PARAM0_SHIFT 16
+#define VI6_SRU_CTRL0_PARAM1_MASK (0x1f << 8)
#define VI6_SRU_CTRL0_PARAM1_SHIFT 8
#define VI6_SRU_CTRL0_MODE_UPSCALE (4 << 4)
#define VI6_SRU_CTRL0_PARAM2 (1 << 3)
diff --git a/drivers/media/platform/vsp1/vsp1_rpf.c b/drivers/media/platform/vsp1/vsp1_rpf.c
index c3d98642a4aa..d14d26b718ef 100644
--- a/drivers/media/platform/vsp1/vsp1_rpf.c
+++ b/drivers/media/platform/vsp1/vsp1_rpf.c
@@ -39,6 +39,36 @@ static inline void vsp1_rpf_write(struct vsp1_rwpf *rpf, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int rpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_rwpf *rpf =
+ container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+ struct vsp1_pipeline *pipe;
+
+ if (!vsp1_entity_is_streaming(&rpf->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ALPHA_COMPONENT:
+ vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
+ ctrl->val << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+
+ pipe = to_vsp1_pipeline(&rpf->entity.subdev.entity);
+ vsp1_pipeline_propagate_alpha(pipe, &rpf->entity, ctrl->val);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops rpf_ctrl_ops = {
+ .s_ctrl = rpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
@@ -50,6 +80,11 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
const struct v4l2_rect *crop = &rpf->crop;
u32 pstride;
u32 infmt;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&rpf->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
@@ -101,12 +136,13 @@ static int rpf_s_stream(struct v4l2_subdev *subdev, int enable)
(rpf->location.left << VI6_RPF_LOC_HCOORD_SHIFT) |
(rpf->location.top << VI6_RPF_LOC_VCOORD_SHIFT));
- /* Disable alpha, mask and color key. Set the alpha channel to a fixed
- * value of 255.
+ /* Use the alpha channel (extended to 8 bits) when available or an
+ * alpha value set through the V4L2_CID_ALPHA_COMPONENT control
+ * otherwise. Disable color keying.
*/
- vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_ASEL_FIXED);
- vsp1_rpf_write(rpf, VI6_RPF_VRTCOL_SET,
- 255 << VI6_RPF_VRTCOL_SET_LAYA_SHIFT);
+ vsp1_rpf_write(rpf, VI6_RPF_ALPH_SEL, VI6_RPF_ALPH_SEL_AEXT_EXT |
+ (fmtinfo->alpha ? VI6_RPF_ALPH_SEL_ASEL_PACKED
+ : VI6_RPF_ALPH_SEL_ASEL_FIXED));
vsp1_rpf_write(rpf, VI6_RPF_MSK_CTRL, 0);
vsp1_rpf_write(rpf, VI6_RPF_CKEY_CTRL, 0);
@@ -196,6 +232,20 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&rpf->ctrls, 1);
+ v4l2_ctrl_new_std(&rpf->ctrls, &rpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 255);
+
+ rpf->entity.subdev.ctrl_handler = &rpf->ctrls;
+
+ if (rpf->ctrls.error) {
+ dev_err(vsp1->dev, "rpf%u: failed to initialize controls\n",
+ index);
+ ret = rpf->ctrls.error;
+ goto error;
+ }
+
/* Initialize the video device. */
video = &rpf->video;
@@ -205,7 +255,9 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
ret = vsp1_video_init(video, &rpf->entity);
if (ret < 0)
- goto error_video;
+ goto error;
+
+ rpf->entity.video = video;
/* Connect the video device to the RPF. */
ret = media_entity_create_link(&rpf->video.video.entity, 0,
@@ -214,13 +266,11 @@ struct vsp1_rwpf *vsp1_rpf_create(struct vsp1_device *vsp1, unsigned int index)
MEDIA_LNK_FL_ENABLED |
MEDIA_LNK_FL_IMMUTABLE);
if (ret < 0)
- goto error_link;
+ goto error;
return rpf;
-error_link:
- vsp1_video_cleanup(video);
-error_video:
- media_entity_cleanup(&rpf->entity.subdev.entity);
+error:
+ vsp1_entity_destroy(&rpf->entity);
return ERR_PTR(ret);
}
diff --git a/drivers/media/platform/vsp1/vsp1_rwpf.h b/drivers/media/platform/vsp1/vsp1_rwpf.h
index b4fb65e58770..28dd9e7b3838 100644
--- a/drivers/media/platform/vsp1/vsp1_rwpf.h
+++ b/drivers/media/platform/vsp1/vsp1_rwpf.h
@@ -14,6 +14,7 @@
#define __VSP1_RWPF_H__
#include <media/media-entity.h>
+#include <media/v4l2-ctrls.h>
#include <media/v4l2-subdev.h>
#include "vsp1.h"
@@ -26,6 +27,7 @@
struct vsp1_rwpf {
struct vsp1_entity entity;
struct vsp1_video video;
+ struct v4l2_ctrl_handler ctrls;
unsigned int max_width;
unsigned int max_height;
diff --git a/drivers/media/platform/vsp1/vsp1_sru.c b/drivers/media/platform/vsp1/vsp1_sru.c
index aa0e04c56f3f..b7d3c8b9f189 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.c
+++ b/drivers/media/platform/vsp1/vsp1_sru.c
@@ -42,38 +42,6 @@ static inline void vsp1_sru_write(struct vsp1_sru *sru, u32 reg, u32 data)
#define V4L2_CID_VSP1_SRU_INTENSITY (V4L2_CID_USER_BASE + 1)
-static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
-{
- struct vsp1_sru *sru =
- container_of(ctrl->handler, struct vsp1_sru, ctrls);
-
- switch (ctrl->id) {
- case V4L2_CID_VSP1_SRU_INTENSITY:
- sru->intensity = ctrl->val;
- break;
- }
-
- return 0;
-}
-
-static const struct v4l2_ctrl_ops sru_ctrl_ops = {
- .s_ctrl = sru_s_ctrl,
-};
-
-static const struct v4l2_ctrl_config sru_intensity_control = {
- .ops = &sru_ctrl_ops,
- .id = V4L2_CID_VSP1_SRU_INTENSITY,
- .name = "Intensity",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .min = 1,
- .max = 6,
- .step = 1,
-};
-
-/* -----------------------------------------------------------------------------
- * V4L2 Subdevice Core Operations
- */
-
struct vsp1_sru_param {
u32 ctrl0;
u32 ctrl2;
@@ -110,22 +78,66 @@ static const struct vsp1_sru_param vsp1_sru_params[] = {
},
};
+static int sru_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_sru *sru =
+ container_of(ctrl->handler, struct vsp1_sru, ctrls);
+ const struct vsp1_sru_param *param;
+ u32 value;
+
+ switch (ctrl->id) {
+ case V4L2_CID_VSP1_SRU_INTENSITY:
+ param = &vsp1_sru_params[ctrl->val - 1];
+
+ value = vsp1_sru_read(sru, VI6_SRU_CTRL0);
+ value &= ~(VI6_SRU_CTRL0_PARAM0_MASK |
+ VI6_SRU_CTRL0_PARAM1_MASK);
+ value |= param->ctrl0;
+ vsp1_sru_write(sru, VI6_SRU_CTRL0, value);
+
+ vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops sru_ctrl_ops = {
+ .s_ctrl = sru_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config sru_intensity_control = {
+ .ops = &sru_ctrl_ops,
+ .id = V4L2_CID_VSP1_SRU_INTENSITY,
+ .name = "Intensity",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .min = 1,
+ .max = 6,
+ .def = 1,
+ .step = 1,
+};
+
+/* -----------------------------------------------------------------------------
+ * V4L2 Subdevice Core Operations
+ */
+
static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
{
struct vsp1_sru *sru = to_sru(subdev);
- const struct vsp1_sru_param *param;
struct v4l2_mbus_framefmt *input;
struct v4l2_mbus_framefmt *output;
- bool upscale;
u32 ctrl0;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&sru->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable)
return 0;
input = &sru->entity.formats[SRU_PAD_SINK];
output = &sru->entity.formats[SRU_PAD_SOURCE];
- upscale = input->width != output->width;
- param = &vsp1_sru_params[sru->intensity];
if (input->code == V4L2_MBUS_FMT_ARGB8888_1X32)
ctrl0 = VI6_SRU_CTRL0_PARAM2 | VI6_SRU_CTRL0_PARAM3
@@ -133,10 +145,18 @@ static int sru_s_stream(struct v4l2_subdev *subdev, int enable)
else
ctrl0 = VI6_SRU_CTRL0_PARAM3;
- vsp1_sru_write(sru, VI6_SRU_CTRL0, param->ctrl0 | ctrl0 |
- (upscale ? VI6_SRU_CTRL0_MODE_UPSCALE : 0));
+ if (input->width != output->width)
+ ctrl0 |= VI6_SRU_CTRL0_MODE_UPSCALE;
+
+ /* Take the control handler lock to ensure that the CTRL0 value won't be
+ * changed behind our back by a set control operation.
+ */
+ mutex_lock(sru->ctrls.lock);
+ ctrl0 |= vsp1_sru_read(sru, VI6_SRU_CTRL0)
+ & (VI6_SRU_CTRL0_PARAM0_MASK | VI6_SRU_CTRL0_PARAM1_MASK);
+ mutex_unlock(sru->ctrls.lock);
+
vsp1_sru_write(sru, VI6_SRU_CTRL1, VI6_SRU_CTRL1_PARAM5);
- vsp1_sru_write(sru, VI6_SRU_CTRL2, param->ctrl2);
return 0;
}
@@ -348,8 +368,15 @@ struct vsp1_sru *vsp1_sru_create(struct vsp1_device *vsp1)
/* Initialize the control handler. */
v4l2_ctrl_handler_init(&sru->ctrls, 1);
v4l2_ctrl_new_custom(&sru->ctrls, &sru_intensity_control, NULL);
- v4l2_ctrl_handler_setup(&sru->ctrls);
+
sru->entity.subdev.ctrl_handler = &sru->ctrls;
+ if (sru->ctrls.error) {
+ dev_err(vsp1->dev, "sru: failed to initialize controls\n");
+ ret = sru->ctrls.error;
+ vsp1_entity_destroy(&sru->entity);
+ return ERR_PTR(ret);
+ }
+
return sru;
}
diff --git a/drivers/media/platform/vsp1/vsp1_sru.h b/drivers/media/platform/vsp1/vsp1_sru.h
index 381870b74780..b6768bf3dc47 100644
--- a/drivers/media/platform/vsp1/vsp1_sru.h
+++ b/drivers/media/platform/vsp1/vsp1_sru.h
@@ -28,7 +28,6 @@ struct vsp1_sru {
struct vsp1_entity entity;
struct v4l2_ctrl_handler ctrls;
- unsigned int intensity;
};
static 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 0293bdbb4401..de92ef4944b3 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.c
+++ b/drivers/media/platform/vsp1/vsp1_uds.c
@@ -45,6 +45,11 @@ static inline void vsp1_uds_write(struct vsp1_uds *uds, u32 reg, u32 data)
* Scaling Computation
*/
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha)
+{
+ vsp1_uds_write(uds, VI6_UDS_ALPVAL, alpha << VI6_UDS_ALPVAL_VAL0_SHIFT);
+}
+
/*
* uds_output_size - Return the output size for an input size and scaling ratio
* @input: input size in pixels
@@ -105,49 +110,56 @@ static unsigned int uds_compute_ratio(unsigned int input, unsigned int output)
return (input - 1) * 4096 / (output - 1);
}
-static void uds_compute_ratios(struct vsp1_uds *uds)
-{
- struct v4l2_mbus_framefmt *input = &uds->entity.formats[UDS_PAD_SINK];
- struct v4l2_mbus_framefmt *output =
- &uds->entity.formats[UDS_PAD_SOURCE];
-
- uds->hscale = uds_compute_ratio(input->width, output->width);
- uds->vscale = uds_compute_ratio(input->height, output->height);
-
- dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n",
- uds->hscale, uds->vscale);
-}
-
/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int uds_s_stream(struct v4l2_subdev *subdev, int enable)
{
- const struct v4l2_mbus_framefmt *format;
struct vsp1_uds *uds = to_uds(subdev);
+ const struct v4l2_mbus_framefmt *output;
+ const struct v4l2_mbus_framefmt *input;
+ unsigned int hscale;
+ unsigned int vscale;
+ bool multitap;
if (!enable)
return 0;
- /* Enable multi-tap scaling. */
- vsp1_uds_write(uds, VI6_UDS_CTRL, VI6_UDS_CTRL_AON | VI6_UDS_CTRL_BC);
+ input = &uds->entity.formats[UDS_PAD_SINK];
+ output = &uds->entity.formats[UDS_PAD_SOURCE];
+
+ hscale = uds_compute_ratio(input->width, output->width);
+ vscale = uds_compute_ratio(input->height, output->height);
+
+ dev_dbg(uds->entity.vsp1->dev, "hscale %u vscale %u\n", hscale, vscale);
+
+ /* Multi-tap scaling can't be enabled along with alpha scaling when
+ * scaling down with a factor lower than or equal to 1/2 in either
+ * direction.
+ */
+ if (uds->scale_alpha && (hscale >= 8192 || vscale >= 8192))
+ multitap = false;
+ else
+ multitap = true;
+
+ vsp1_uds_write(uds, VI6_UDS_CTRL,
+ (uds->scale_alpha ? VI6_UDS_CTRL_AON : 0) |
+ (multitap ? VI6_UDS_CTRL_BC : 0));
vsp1_uds_write(uds, VI6_UDS_PASS_BWIDTH,
- (uds_passband_width(uds->hscale)
+ (uds_passband_width(hscale)
<< VI6_UDS_PASS_BWIDTH_H_SHIFT) |
- (uds_passband_width(uds->vscale)
+ (uds_passband_width(vscale)
<< VI6_UDS_PASS_BWIDTH_V_SHIFT));
/* Set the scaling ratios and the output size. */
- format = &uds->entity.formats[UDS_PAD_SOURCE];
-
vsp1_uds_write(uds, VI6_UDS_SCALE,
- (uds->hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
- (uds->vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
+ (hscale << VI6_UDS_SCALE_HFRAC_SHIFT) |
+ (vscale << VI6_UDS_SCALE_VFRAC_SHIFT));
vsp1_uds_write(uds, VI6_UDS_CLIP_SIZE,
- (format->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
- (format->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
+ (output->width << VI6_UDS_CLIP_SIZE_HSIZE_SHIFT) |
+ (output->height << VI6_UDS_CLIP_SIZE_VSIZE_SHIFT));
return 0;
}
@@ -280,9 +292,6 @@ static int uds_set_format(struct v4l2_subdev *subdev, struct v4l2_subdev_fh *fh,
uds_try_format(uds, fh, UDS_PAD_SOURCE, format, fmt->which);
}
- if (fmt->which == V4L2_SUBDEV_FORMAT_ACTIVE)
- uds_compute_ratios(uds);
-
return 0;
}
diff --git a/drivers/media/platform/vsp1/vsp1_uds.h b/drivers/media/platform/vsp1/vsp1_uds.h
index 479d12df1180..031ac0da1b66 100644
--- a/drivers/media/platform/vsp1/vsp1_uds.h
+++ b/drivers/media/platform/vsp1/vsp1_uds.h
@@ -25,9 +25,7 @@ struct vsp1_device;
struct vsp1_uds {
struct vsp1_entity entity;
-
- unsigned int hscale;
- unsigned int vscale;
+ bool scale_alpha;
};
static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
@@ -37,4 +35,6 @@ static inline struct vsp1_uds *to_uds(struct v4l2_subdev *subdev)
struct vsp1_uds *vsp1_uds_create(struct vsp1_device *vsp1, unsigned int index);
+void vsp1_uds_set_alpha(struct vsp1_uds *uds, unsigned int alpha);
+
#endif /* __VSP1_UDS_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_video.c b/drivers/media/platform/vsp1/vsp1_video.c
index 8a1253e51f04..915a20eb003e 100644
--- a/drivers/media/platform/vsp1/vsp1_video.c
+++ b/drivers/media/platform/vsp1/vsp1_video.c
@@ -31,6 +31,7 @@
#include "vsp1_bru.h"
#include "vsp1_entity.h"
#include "vsp1_rwpf.h"
+#include "vsp1_uds.h"
#include "vsp1_video.h"
#define VSP1_VIDEO_DEF_FORMAT V4L2_PIX_FMT_YUYV
@@ -50,70 +51,85 @@ static const struct vsp1_format_info vsp1_video_formats[] = {
{ V4L2_PIX_FMT_RGB332, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_332, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 8, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 8, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ARGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB444, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_4444, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_ARGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS,
+ 1, { 16, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB555, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_XRGB_1555, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
+ 1, { 16, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGB565, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_565, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS,
- 1, { 16, 0, 0 }, false, false, 1, 1 },
+ 1, { 16, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_BGR24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_BGR_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 24, 0, 0 }, false, false, 1, 1 },
+ 1, { 24, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_RGB24, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_RGB_888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 24, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_BGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 24, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ABGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
+ 1, { 32, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XBGR32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS,
- 1, { 32, 0, 0 }, false, false, 1, 1 },
- { V4L2_PIX_FMT_RGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ 1, { 32, 0, 0 }, false, false, 1, 1, false },
+ { V4L2_PIX_FMT_ARGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
+ VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
+ VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
+ 1, { 32, 0, 0 }, false, false, 1, 1, true },
+ { V4L2_PIX_FMT_XRGB32, V4L2_MBUS_FMT_ARGB8888_1X32,
VI6_FMT_ARGB_8888, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 32, 0, 0 }, false, false, 1, 1 },
+ 1, { 32, 0, 0 }, false, false, 1, 1, false },
{ V4L2_PIX_FMT_UYVY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, false, false, 2, 1 },
+ 1, { 16, 0, 0 }, false, false, 2, 1, false },
{ V4L2_PIX_FMT_VYUY, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, false, true, 2, 1 },
+ 1, { 16, 0, 0 }, false, true, 2, 1, false },
{ V4L2_PIX_FMT_YUYV, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, true, false, 2, 1 },
+ 1, { 16, 0, 0 }, true, false, 2, 1, false },
{ V4L2_PIX_FMT_YVYU, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_YUYV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 1, { 16, 0, 0 }, true, true, 2, 1 },
+ 1, { 16, 0, 0 }, true, true, 2, 1, false },
{ V4L2_PIX_FMT_NV12M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, false, 2, 2 },
+ 2, { 8, 16, 0 }, false, false, 2, 2, false },
{ V4L2_PIX_FMT_NV21M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, true, 2, 2 },
+ 2, { 8, 16, 0 }, false, true, 2, 2, false },
{ V4L2_PIX_FMT_NV16M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, false, 2, 1 },
+ 2, { 8, 16, 0 }, false, false, 2, 1, false },
{ V4L2_PIX_FMT_NV61M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_UV_422, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 2, { 8, 16, 0 }, false, true, 2, 1 },
+ 2, { 8, 16, 0 }, false, true, 2, 1, false },
{ V4L2_PIX_FMT_YUV420M, V4L2_MBUS_FMT_AYUV8_1X32,
VI6_FMT_Y_U_V_420, VI6_RPF_DSWAP_P_LLS | VI6_RPF_DSWAP_P_LWS |
VI6_RPF_DSWAP_P_WDS | VI6_RPF_DSWAP_P_BTS,
- 3, { 8, 8, 8 }, false, false, 2, 2 },
+ 3, { 8, 8, 8 }, false, false, 2, 2, false },
};
/*
@@ -181,11 +197,29 @@ static int __vsp1_video_try_format(struct vsp1_video *video,
struct v4l2_pix_format_mplane *pix,
const struct vsp1_format_info **fmtinfo)
{
+ static const u32 xrgb_formats[][2] = {
+ { V4L2_PIX_FMT_RGB444, V4L2_PIX_FMT_XRGB444 },
+ { V4L2_PIX_FMT_RGB555, V4L2_PIX_FMT_XRGB555 },
+ { V4L2_PIX_FMT_BGR32, V4L2_PIX_FMT_XBGR32 },
+ { V4L2_PIX_FMT_RGB32, V4L2_PIX_FMT_XRGB32 },
+ };
+
const struct vsp1_format_info *info;
unsigned int width = pix->width;
unsigned int height = pix->height;
unsigned int i;
+ /* Backward compatibility: replace deprecated RGB formats by their XRGB
+ * equivalent. This selects the format older userspace applications want
+ * while still exposing the new format.
+ */
+ for (i = 0; i < ARRAY_SIZE(xrgb_formats); ++i) {
+ if (xrgb_formats[i][0] == pix->pixelformat) {
+ pix->pixelformat = xrgb_formats[i][1];
+ break;
+ }
+ }
+
/* Retrieve format information and select the default format if the
* requested format isn't supported.
*/
@@ -273,13 +307,14 @@ vsp1_video_format_adjust(struct vsp1_video *video,
* Pipeline Management
*/
-static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
+static int vsp1_pipeline_validate_branch(struct vsp1_pipeline *pipe,
+ struct vsp1_rwpf *input,
struct vsp1_rwpf *output)
{
struct vsp1_entity *entity;
unsigned int entities = 0;
struct media_pad *pad;
- bool uds_found = false;
+ bool bru_found = false;
input->location.left = 0;
input->location.top = 0;
@@ -301,10 +336,15 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
*/
if (entity->type == VSP1_ENTITY_BRU) {
struct vsp1_bru *bru = to_bru(&entity->subdev);
- struct v4l2_rect *rect = &bru->compose[pad->index];
+ struct v4l2_rect *rect =
+ &bru->inputs[pad->index].compose;
+
+ bru->inputs[pad->index].rpf = input;
input->location.left = rect->left;
input->location.top = rect->top;
+
+ bru_found = true;
}
/* We've reached the WPF, we're done. */
@@ -319,9 +359,12 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
/* UDS can't be chained. */
if (entity->type == VSP1_ENTITY_UDS) {
- if (uds_found)
+ if (pipe->uds)
return -EPIPE;
- uds_found = true;
+
+ pipe->uds = entity;
+ pipe->uds_input = bru_found ? pipe->bru
+ : &input->entity;
}
/* Follow the source link. The link setup operations ensure
@@ -340,6 +383,27 @@ static int vsp1_pipeline_validate_branch(struct vsp1_rwpf *input,
return 0;
}
+static void __vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
+{
+ if (pipe->bru) {
+ struct vsp1_bru *bru = to_bru(&pipe->bru->subdev);
+ unsigned int i;
+
+ for (i = 0; i < ARRAY_SIZE(bru->inputs); ++i)
+ bru->inputs[i].rpf = NULL;
+ }
+
+ INIT_LIST_HEAD(&pipe->entities);
+ pipe->state = VSP1_PIPELINE_STOPPED;
+ pipe->buffers_ready = 0;
+ pipe->num_video = 0;
+ pipe->num_inputs = 0;
+ pipe->output = NULL;
+ pipe->bru = NULL;
+ pipe->lif = NULL;
+ pipe->uds = NULL;
+}
+
static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
struct vsp1_video *video)
{
@@ -395,7 +459,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
* contains no loop and that all branches end at the output WPF.
*/
for (i = 0; i < pipe->num_inputs; ++i) {
- ret = vsp1_pipeline_validate_branch(pipe->inputs[i],
+ ret = vsp1_pipeline_validate_branch(pipe, pipe->inputs[i],
pipe->output);
if (ret < 0)
goto error;
@@ -404,13 +468,7 @@ static int vsp1_pipeline_validate(struct vsp1_pipeline *pipe,
return 0;
error:
- INIT_LIST_HEAD(&pipe->entities);
- pipe->buffers_ready = 0;
- pipe->num_video = 0;
- pipe->num_inputs = 0;
- pipe->output = NULL;
- pipe->bru = NULL;
- pipe->lif = NULL;
+ __vsp1_pipeline_cleanup(pipe);
return ret;
}
@@ -441,16 +499,8 @@ static void vsp1_pipeline_cleanup(struct vsp1_pipeline *pipe)
mutex_lock(&pipe->lock);
/* If we're the last user clean up the pipeline. */
- if (--pipe->use_count == 0) {
- INIT_LIST_HEAD(&pipe->entities);
- pipe->state = VSP1_PIPELINE_STOPPED;
- pipe->buffers_ready = 0;
- pipe->num_video = 0;
- pipe->num_inputs = 0;
- pipe->output = NULL;
- pipe->bru = NULL;
- pipe->lif = NULL;
- }
+ if (--pipe->use_count == 0)
+ __vsp1_pipeline_cleanup(pipe);
mutex_unlock(&pipe->lock);
}
@@ -471,7 +521,8 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
int ret;
spin_lock_irqsave(&pipe->irqlock, flags);
- pipe->state = VSP1_PIPELINE_STOPPING;
+ if (pipe->state == VSP1_PIPELINE_RUNNING)
+ pipe->state = VSP1_PIPELINE_STOPPING;
spin_unlock_irqrestore(&pipe->irqlock, flags);
ret = wait_event_timeout(pipe->wq, pipe->state == VSP1_PIPELINE_STOPPED,
@@ -479,7 +530,7 @@ static int vsp1_pipeline_stop(struct vsp1_pipeline *pipe)
ret = ret == 0 ? -ETIMEDOUT : 0;
list_for_each_entry(entity, &pipe->entities, list_pipe) {
- if (entity->route)
+ if (entity->route && entity->route->reg)
vsp1_write(entity->vsp1, entity->route->reg,
VI6_DPR_NODE_UNUSED);
@@ -576,6 +627,7 @@ static void vsp1_video_frame_end(struct vsp1_pipeline *pipe,
void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
{
+ enum vsp1_pipeline_state state;
unsigned long flags;
unsigned int i;
@@ -591,11 +643,13 @@ void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe)
spin_lock_irqsave(&pipe->irqlock, flags);
+ state = pipe->state;
+ pipe->state = VSP1_PIPELINE_STOPPED;
+
/* If a stop has been requested, mark the pipeline as stopped and
* return.
*/
- if (pipe->state == VSP1_PIPELINE_STOPPING) {
- pipe->state = VSP1_PIPELINE_STOPPED;
+ if (state == VSP1_PIPELINE_STOPPING) {
wake_up(&pipe->wq);
goto done;
}
@@ -608,6 +662,47 @@ done:
spin_unlock_irqrestore(&pipe->irqlock, flags);
}
+/*
+ * Propagate the alpha value through the pipeline.
+ *
+ * As the UDS has restricted scaling capabilities when the alpha component needs
+ * to be scaled, we disable alpha scaling when the UDS input has a fixed alpha
+ * value. The UDS then outputs a fixed alpha value which needs to be programmed
+ * from the input RPF alpha.
+ */
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+ struct vsp1_entity *input,
+ unsigned int alpha)
+{
+ struct vsp1_entity *entity;
+ struct media_pad *pad;
+
+ pad = media_entity_remote_pad(&input->pads[RWPF_PAD_SOURCE]);
+
+ while (pad) {
+ if (media_entity_type(pad->entity) != MEDIA_ENT_T_V4L2_SUBDEV)
+ break;
+
+ entity = to_vsp1_entity(media_entity_to_v4l2_subdev(pad->entity));
+
+ /* The BRU background color has a fixed alpha value set to 255,
+ * the output alpha value is thus always equal to 255.
+ */
+ if (entity->type == VSP1_ENTITY_BRU)
+ alpha = 255;
+
+ if (entity->type == VSP1_ENTITY_UDS) {
+ struct vsp1_uds *uds = to_uds(&entity->subdev);
+
+ vsp1_uds_set_alpha(uds, alpha);
+ break;
+ }
+
+ pad = &entity->pads[entity->source_pad];
+ pad = media_entity_remote_pad(pad);
+ }
+}
+
/* -----------------------------------------------------------------------------
* videobuf2 Queue Operations
*/
@@ -654,8 +749,6 @@ static int vsp1_video_buffer_prepare(struct vb2_buffer *vb)
if (vb->num_planes < format->num_planes)
return -EINVAL;
- buf->video = video;
-
for (i = 0; i < vb->num_planes; ++i) {
buf->addr[i] = vb2_dma_contig_plane_dma_addr(vb, i);
buf->length[i] = vb2_plane_size(vb, i);
@@ -717,6 +810,25 @@ static int vsp1_video_start_streaming(struct vb2_queue *vq, unsigned int count)
mutex_lock(&pipe->lock);
if (pipe->stream_count == pipe->num_video - 1) {
+ if (pipe->uds) {
+ struct vsp1_uds *uds = to_uds(&pipe->uds->subdev);
+
+ /* If a BRU is present in the pipeline before the UDS,
+ * the alpha component doesn't need to be scaled as the
+ * BRU output alpha value is fixed to 255. Otherwise we
+ * need to scale the alpha component only when available
+ * at the input RPF.
+ */
+ if (pipe->uds_input->type == VSP1_ENTITY_BRU) {
+ uds->scale_alpha = false;
+ } else {
+ struct vsp1_rwpf *rpf =
+ to_rwpf(&pipe->uds_input->subdev);
+
+ uds->scale_alpha = rpf->video.fmtinfo->alpha;
+ }
+ }
+
list_for_each_entry(entity, &pipe->entities, list_pipe) {
vsp1_entity_route_setup(entity);
@@ -744,6 +856,7 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
{
struct vsp1_video *video = vb2_get_drv_priv(vq);
struct vsp1_pipeline *pipe = to_vsp1_pipeline(&video->video.entity);
+ struct vsp1_video_buffer *buffer;
unsigned long flags;
int ret;
@@ -761,6 +874,8 @@ static void vsp1_video_stop_streaming(struct vb2_queue *vq)
/* Remove all buffers from the IRQ queue. */
spin_lock_irqsave(&video->irqlock, flags);
+ list_for_each_entry(buffer, &video->irqqueue, queue)
+ vb2_buffer_done(&buffer->buf, VB2_BUF_STATE_ERROR);
INIT_LIST_HEAD(&video->irqqueue);
spin_unlock_irqrestore(&video->irqlock, flags);
}
@@ -950,8 +1065,8 @@ static int vsp1_video_open(struct file *file)
file->private_data = vfh;
- if (!vsp1_device_get(video->vsp1)) {
- ret = -EBUSY;
+ ret = vsp1_device_get(video->vsp1);
+ if (ret < 0) {
v4l2_fh_del(vfh);
kfree(vfh);
}
diff --git a/drivers/media/platform/vsp1/vsp1_video.h b/drivers/media/platform/vsp1/vsp1_video.h
index c04d48fa2999..fd2851a82e00 100644
--- a/drivers/media/platform/vsp1/vsp1_video.h
+++ b/drivers/media/platform/vsp1/vsp1_video.h
@@ -33,6 +33,7 @@ struct vsp1_video;
* @swap_uv: the U and V components are swapped (V comes before U)
* @hsub: horizontal subsampling factor
* @vsub: vertical subsampling factor
+ * @alpha: has an alpha channel
*/
struct vsp1_format_info {
u32 fourcc;
@@ -45,6 +46,7 @@ struct vsp1_format_info {
bool swap_uv;
unsigned int hsub;
unsigned int vsub;
+ bool alpha;
};
enum vsp1_pipeline_state {
@@ -73,10 +75,12 @@ struct vsp1_pipeline {
unsigned int num_video;
unsigned int num_inputs;
- struct vsp1_rwpf *inputs[VPS1_MAX_RPF];
+ struct vsp1_rwpf *inputs[VSP1_MAX_RPF];
struct vsp1_rwpf *output;
struct vsp1_entity *bru;
struct vsp1_entity *lif;
+ struct vsp1_entity *uds;
+ struct vsp1_entity *uds_input;
struct list_head entities;
};
@@ -90,7 +94,6 @@ static inline struct vsp1_pipeline *to_vsp1_pipeline(struct media_entity *e)
}
struct vsp1_video_buffer {
- struct vsp1_video *video;
struct vb2_buffer buf;
struct list_head queue;
@@ -142,4 +145,8 @@ void vsp1_video_cleanup(struct vsp1_video *video);
void vsp1_pipeline_frame_end(struct vsp1_pipeline *pipe);
+void vsp1_pipeline_propagate_alpha(struct vsp1_pipeline *pipe,
+ struct vsp1_entity *input,
+ unsigned int alpha);
+
#endif /* __VSP1_VIDEO_H__ */
diff --git a/drivers/media/platform/vsp1/vsp1_wpf.c b/drivers/media/platform/vsp1/vsp1_wpf.c
index 1294340dcb36..6e057762c933 100644
--- a/drivers/media/platform/vsp1/vsp1_wpf.c
+++ b/drivers/media/platform/vsp1/vsp1_wpf.c
@@ -39,22 +39,56 @@ static inline void vsp1_wpf_write(struct vsp1_rwpf *wpf, u32 reg, u32 data)
}
/* -----------------------------------------------------------------------------
+ * Controls
+ */
+
+static int wpf_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct vsp1_rwpf *wpf =
+ container_of(ctrl->handler, struct vsp1_rwpf, ctrls);
+ u32 value;
+
+ if (!vsp1_entity_is_streaming(&wpf->entity))
+ return 0;
+
+ switch (ctrl->id) {
+ case V4L2_CID_ALPHA_COMPONENT:
+ value = vsp1_wpf_read(wpf, VI6_WPF_OUTFMT);
+ value &= ~VI6_WPF_OUTFMT_PDV_MASK;
+ value |= ctrl->val << VI6_WPF_OUTFMT_PDV_SHIFT;
+ vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, value);
+ break;
+ }
+
+ return 0;
+}
+
+static const struct v4l2_ctrl_ops wpf_ctrl_ops = {
+ .s_ctrl = wpf_s_ctrl,
+};
+
+/* -----------------------------------------------------------------------------
* V4L2 Subdevice Core Operations
*/
static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
{
+ struct vsp1_pipeline *pipe = to_vsp1_pipeline(&subdev->entity);
struct vsp1_rwpf *wpf = to_rwpf(subdev);
- struct vsp1_pipeline *pipe =
- to_vsp1_pipeline(&wpf->entity.subdev.entity);
struct vsp1_device *vsp1 = wpf->entity.vsp1;
const struct v4l2_rect *crop = &wpf->crop;
unsigned int i;
u32 srcrpf = 0;
u32 outfmt = 0;
+ int ret;
+
+ ret = vsp1_entity_set_streaming(&wpf->entity, enable);
+ if (ret < 0)
+ return ret;
if (!enable) {
vsp1_write(vsp1, VI6_WPF_IRQ_ENB(wpf->entity.index), 0);
+ vsp1_wpf_write(wpf, VI6_WPF_SRCRPF, 0);
return 0;
}
@@ -99,6 +133,8 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
outfmt = fmtinfo->hwfmt << VI6_WPF_OUTFMT_WRFMT_SHIFT;
+ if (fmtinfo->alpha)
+ outfmt |= VI6_WPF_OUTFMT_PXA;
if (fmtinfo->swap_yc)
outfmt |= VI6_WPF_OUTFMT_SPYCS;
if (fmtinfo->swap_uv)
@@ -111,7 +147,13 @@ static int wpf_s_stream(struct v4l2_subdev *subdev, int enable)
wpf->entity.formats[RWPF_PAD_SOURCE].code)
outfmt |= VI6_WPF_OUTFMT_CSC;
+ /* Take the control handler lock to ensure that the PDV value won't be
+ * changed behind our back by a set control operation.
+ */
+ mutex_lock(wpf->ctrls.lock);
+ outfmt |= vsp1_wpf_read(wpf, VI6_WPF_OUTFMT) & VI6_WPF_OUTFMT_PDV_MASK;
vsp1_wpf_write(wpf, VI6_WPF_OUTFMT, outfmt);
+ mutex_unlock(wpf->ctrls.lock);
vsp1_write(vsp1, VI6_DPR_WPF_FPORCH(wpf->entity.index),
VI6_DPR_WPF_FPORCH_FP_WPFN);
@@ -207,6 +249,20 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
vsp1_entity_init_formats(subdev, NULL);
+ /* Initialize the control handler. */
+ v4l2_ctrl_handler_init(&wpf->ctrls, 1);
+ v4l2_ctrl_new_std(&wpf->ctrls, &wpf_ctrl_ops, V4L2_CID_ALPHA_COMPONENT,
+ 0, 255, 1, 255);
+
+ wpf->entity.subdev.ctrl_handler = &wpf->ctrls;
+
+ if (wpf->ctrls.error) {
+ dev_err(vsp1->dev, "wpf%u: failed to initialize controls\n",
+ index);
+ ret = wpf->ctrls.error;
+ goto error;
+ }
+
/* Initialize the video device. */
video = &wpf->video;
@@ -216,7 +272,9 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
ret = vsp1_video_init(video, &wpf->entity);
if (ret < 0)
- goto error_video;
+ goto error;
+
+ wpf->entity.video = video;
/* Connect the video device to the WPF. All connections are immutable
* except for the WPF0 source link if a LIF is present.
@@ -229,15 +287,13 @@ struct vsp1_rwpf *vsp1_wpf_create(struct vsp1_device *vsp1, unsigned int index)
RWPF_PAD_SOURCE,
&wpf->video.video.entity, 0, flags);
if (ret < 0)
- goto error_link;
+ goto error;
wpf->entity.sink = &wpf->video.video.entity;
return wpf;
-error_link:
- vsp1_video_cleanup(video);
-error_video:
- media_entity_cleanup(&wpf->entity.subdev.entity);
+error:
+ vsp1_entity_destroy(&wpf->entity);
return ERR_PTR(ret);
}
diff --git a/drivers/media/radio/dsbr100.c b/drivers/media/radio/dsbr100.c
index 142c2ee64d31..2262b8139ca1 100644
--- a/drivers/media/radio/dsbr100.c
+++ b/drivers/media/radio/dsbr100.c
@@ -390,7 +390,6 @@ static int usb_dsbr100_probe(struct usb_interface *intf,
radio->videodev.release = video_device_release_empty;
radio->videodev.lock = &radio->v4l2_lock;
radio->videodev.ctrl_handler = &radio->hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->curfreq = FREQ_MIN * FREQ_MUL;
diff --git a/drivers/media/radio/radio-cadet.c b/drivers/media/radio/radio-cadet.c
index d719e59e2179..82affaedf067 100644
--- a/drivers/media/radio/radio-cadet.c
+++ b/drivers/media/radio/radio-cadet.c
@@ -650,7 +650,6 @@ static int __init cadet_init(void)
dev->vdev.ioctl_ops = &cadet_ioctl_ops;
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
res = video_register_device(&dev->vdev, VFL_TYPE_RADIO, radio_nr);
diff --git a/drivers/media/radio/radio-isa.c b/drivers/media/radio/radio-isa.c
index 6ff350831d56..c309ee45a08e 100644
--- a/drivers/media/radio/radio-isa.c
+++ b/drivers/media/radio/radio-isa.c
@@ -253,7 +253,6 @@ static int radio_isa_common_probe(struct radio_isa_card *isa,
isa->vdev.fops = &radio_isa_fops;
isa->vdev.ioctl_ops = &radio_isa_ioctl_ops;
isa->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &isa->vdev.flags);
video_set_drvdata(&isa->vdev, isa);
isa->freq = FREQ_LOW;
isa->stereo = drv->has_stereo;
diff --git a/drivers/media/radio/radio-keene.c b/drivers/media/radio/radio-keene.c
index 3d127825eceb..0c5d2db3b828 100644
--- a/drivers/media/radio/radio-keene.c
+++ b/drivers/media/radio/radio-keene.c
@@ -265,7 +265,7 @@ static int keene_s_ctrl(struct v4l2_ctrl *ctrl)
return keene_cmd_set(radio);
case V4L2_CID_AUDIO_COMPRESSION_GAIN:
- radio->tx = db2tx[(ctrl->val - ctrl->minimum) / ctrl->step];
+ radio->tx = db2tx[(ctrl->val - (s32)ctrl->minimum) / (s32)ctrl->step];
return keene_cmd_set(radio);
}
return -EINVAL;
@@ -380,7 +380,6 @@ static int usb_keene_probe(struct usb_interface *intf,
usb_set_intfdata(intf, &radio->v4l2_dev);
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
/* at least 11ms is needed in order to settle hardware */
msleep(20);
diff --git a/drivers/media/radio/radio-ma901.c b/drivers/media/radio/radio-ma901.c
index a85b064cb7be..b3000ef85ee7 100644
--- a/drivers/media/radio/radio-ma901.c
+++ b/drivers/media/radio/radio-ma901.c
@@ -411,7 +411,6 @@ static int usb_ma901radio_probe(struct usb_interface *intf,
radio->vdev.ioctl_ops = &usb_ma901radio_ioctl_ops;
radio->vdev.release = video_device_release_empty;
radio->vdev.lock = &radio->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
diff --git a/drivers/media/radio/radio-miropcm20.c b/drivers/media/radio/radio-miropcm20.c
index a7e93d7477dd..3d12edf520a0 100644
--- a/drivers/media/radio/radio-miropcm20.c
+++ b/drivers/media/radio/radio-miropcm20.c
@@ -210,7 +210,6 @@ static int __init pcm20_init(void)
dev->vdev.ioctl_ops = &pcm20_ioctl_ops;
dev->vdev.release = video_device_release_empty;
dev->vdev.lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
snd_aci_cmd(dev->aci, ACI_SET_TUNERMONO,
dev->audmode == V4L2_TUNER_MODE_MONO, -1);
diff --git a/drivers/media/radio/radio-mr800.c b/drivers/media/radio/radio-mr800.c
index a360227ca3ab..c2927fd12615 100644
--- a/drivers/media/radio/radio-mr800.c
+++ b/drivers/media/radio/radio-mr800.c
@@ -32,7 +32,7 @@
* achievements (specifications given).
* Also, Faidon Liambotis <paravoid@debian.org> wrote nice driver for this radio
* in 2007. He allowed to use his driver to improve current mr800 radio driver.
- * http://kerneltrap.org/mailarchive/linux-usb-devel/2007/10/11/342492
+ * http://www.spinics.net/lists/linux-usb-devel/msg10109.html
*
* Version 0.01: First working version.
* It's required to blacklist AverMedia USB Radio
@@ -558,7 +558,6 @@ static int usb_amradio_probe(struct usb_interface *intf,
radio->vdev.ioctl_ops = &usb_amradio_ioctl_ops;
radio->vdev.release = video_device_release_empty;
radio->vdev.lock = &radio->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
radio->usbdev = interface_to_usbdev(intf);
radio->intf = intf;
diff --git a/drivers/media/radio/radio-raremono.c b/drivers/media/radio/radio-raremono.c
index 7b3bdbb1be73..bfb3a6d051ba 100644
--- a/drivers/media/radio/radio-raremono.c
+++ b/drivers/media/radio/radio-raremono.c
@@ -361,7 +361,6 @@ static int usb_raremono_probe(struct usb_interface *intf,
usb_set_intfdata(intf, &radio->v4l2_dev);
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
raremono_cmd_main(radio, BAND_FM, 95160);
diff --git a/drivers/media/radio/radio-sf16fmi.c b/drivers/media/radio/radio-sf16fmi.c
index 6f4318ff0db3..d7ce8fe6b5ae 100644
--- a/drivers/media/radio/radio-sf16fmi.c
+++ b/drivers/media/radio/radio-sf16fmi.c
@@ -344,7 +344,6 @@ static int __init fmi_init(void)
fmi->vdev.fops = &fmi_fops;
fmi->vdev.ioctl_ops = &fmi_ioctl_ops;
fmi->vdev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &fmi->vdev.flags);
video_set_drvdata(&fmi->vdev, fmi);
mutex_init(&fmi->lock);
diff --git a/drivers/media/radio/radio-si476x.c b/drivers/media/radio/radio-si476x.c
index 2fd9009f8663..633022b45f33 100644
--- a/drivers/media/radio/radio-si476x.c
+++ b/drivers/media/radio/radio-si476x.c
@@ -1470,7 +1470,6 @@ static int si476x_radio_probe(struct platform_device *pdev)
video_set_drvdata(&radio->videodev, radio);
platform_set_drvdata(pdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
radio->v4l2dev.ctrl_handler = &radio->ctrl_handler;
v4l2_ctrl_handler_init(&radio->ctrl_handler,
diff --git a/drivers/media/radio/radio-tea5764.c b/drivers/media/radio/radio-tea5764.c
index 3ed1f5669f79..925049654c5b 100644
--- a/drivers/media/radio/radio-tea5764.c
+++ b/drivers/media/radio/radio-tea5764.c
@@ -478,7 +478,6 @@ static int tea5764_i2c_probe(struct i2c_client *client,
video_set_drvdata(&radio->vdev, radio);
radio->vdev.lock = &radio->mutex;
radio->vdev.v4l2_dev = v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
/* initialize and power off the chip */
tea5764_i2c_read(radio);
diff --git a/drivers/media/radio/radio-tea5777.c b/drivers/media/radio/radio-tea5777.c
index e2455970725a..83fe7ab358df 100644
--- a/drivers/media/radio/radio-tea5777.c
+++ b/drivers/media/radio/radio-tea5777.c
@@ -570,7 +570,6 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner)
tea->fops = tea575x_fops;
tea->fops.owner = owner;
tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
tea->vd.ctrl_handler = &tea->ctrl_handler;
v4l2_ctrl_handler_init(&tea->ctrl_handler, 1);
diff --git a/drivers/media/radio/radio-timb.c b/drivers/media/radio/radio-timb.c
index 0817964d9172..b9285e6584af 100644
--- a/drivers/media/radio/radio-timb.c
+++ b/drivers/media/radio/radio-timb.c
@@ -126,7 +126,6 @@ static int timbradio_probe(struct platform_device *pdev)
tr->video_dev.release = video_device_release_empty;
tr->video_dev.minor = -1;
tr->video_dev.lock = &tr->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &tr->video_dev.flags);
strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
err = v4l2_device_register(NULL, &tr->v4l2_dev);
diff --git a/drivers/media/radio/si470x/radio-si470x-usb.c b/drivers/media/radio/si470x/radio-si470x-usb.c
index 07ef40595efd..494fac061306 100644
--- a/drivers/media/radio/si470x/radio-si470x-usb.c
+++ b/drivers/media/radio/si470x/radio-si470x-usb.c
@@ -680,7 +680,6 @@ static int si470x_usb_driver_probe(struct usb_interface *intf,
radio->videodev.lock = &radio->lock;
radio->videodev.v4l2_dev = &radio->v4l2_dev;
radio->videodev.release = video_device_release_empty;
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->videodev.flags);
video_set_drvdata(&radio->videodev, radio);
/* get device and chip versions */
diff --git a/drivers/media/radio/si4713/radio-platform-si4713.c b/drivers/media/radio/si4713/radio-platform-si4713.c
index ba4cfc946868..a47502a330f0 100644
--- a/drivers/media/radio/si4713/radio-platform-si4713.c
+++ b/drivers/media/radio/si4713/radio-platform-si4713.c
@@ -196,7 +196,6 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
rsdev->radio_dev = radio_si4713_vdev_template;
rsdev->radio_dev.v4l2_dev = &rsdev->v4l2_dev;
rsdev->radio_dev.ctrl_handler = sd->ctrl_handler;
- set_bit(V4L2_FL_USE_FH_PRIO, &rsdev->radio_dev.flags);
/* Serialize all access to the si4713 */
rsdev->radio_dev.lock = &rsdev->lock;
video_set_drvdata(&rsdev->radio_dev, rsdev);
diff --git a/drivers/media/radio/si4713/radio-usb-si4713.c b/drivers/media/radio/si4713/radio-usb-si4713.c
index 86502b2786d0..a77319dcba05 100644
--- a/drivers/media/radio/si4713/radio-usb-si4713.c
+++ b/drivers/media/radio/si4713/radio-usb-si4713.c
@@ -492,7 +492,6 @@ static int usb_si4713_probe(struct usb_interface *intf,
radio->vdev.vfl_dir = VFL_DIR_TX;
video_set_drvdata(&radio->vdev, radio);
- set_bit(V4L2_FL_USE_FH_PRIO, &radio->vdev.flags);
retval = video_register_device(&radio->vdev, VFL_TYPE_RADIO, -1);
if (retval < 0) {
diff --git a/drivers/media/radio/si4713/si4713.c b/drivers/media/radio/si4713/si4713.c
index 07d5153811e8..dbe47261b513 100644
--- a/drivers/media/radio/si4713/si4713.c
+++ b/drivers/media/radio/si4713/si4713.c
@@ -1098,11 +1098,11 @@ static int si4713_s_ctrl(struct v4l2_ctrl *ctrl)
switch (ctrl->id) {
case V4L2_CID_RDS_TX_PS_NAME:
- ret = si4713_set_rds_ps_name(sdev, ctrl->string);
+ ret = si4713_set_rds_ps_name(sdev, ctrl->p_new.p_char);
break;
case V4L2_CID_RDS_TX_RADIO_TEXT:
- ret = si4713_set_rds_radio_text(sdev, ctrl->string);
+ ret = si4713_set_rds_radio_text(sdev, ctrl->p_new.p_char);
break;
case V4L2_CID_TUNE_ANTENNA_CAPACITOR:
diff --git a/drivers/media/radio/tea575x.c b/drivers/media/radio/tea575x.c
index 7c14060a40b8..f1a0867789fe 100644
--- a/drivers/media/radio/tea575x.c
+++ b/drivers/media/radio/tea575x.c
@@ -523,7 +523,6 @@ int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner)
tea->fops = tea575x_fops;
tea->fops.owner = owner;
tea->vd.fops = &tea->fops;
- set_bit(V4L2_FL_USE_FH_PRIO, &tea->vd.flags);
/* disable hw_freq_seek if we can't use it */
if (tea->cannot_read_data)
v4l2_disable_ioctl(&tea->vd, VIDIOC_S_HW_FREQ_SEEK);
diff --git a/drivers/media/rc/Kconfig b/drivers/media/rc/Kconfig
index 8fbd377e6311..9427faddce32 100644
--- a/drivers/media/rc/Kconfig
+++ b/drivers/media/rc/Kconfig
@@ -343,4 +343,14 @@ config RC_ST
If you're not sure, select N here.
+config IR_SUNXI
+ tristate "SUNXI IR remote control"
+ depends on RC_CORE
+ depends on ARCH_SUNXI
+ ---help---
+ Say Y if you want to use sunXi internal IR Controller
+
+ To compile this driver as a module, choose M here: the module will
+ be called sunxi-ir.
+
endif #RC_DEVICES
diff --git a/drivers/media/rc/Makefile b/drivers/media/rc/Makefile
index f8b54ff46601..9ee9ee75ae8d 100644
--- a/drivers/media/rc/Makefile
+++ b/drivers/media/rc/Makefile
@@ -32,4 +32,5 @@ obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
obj-$(CONFIG_IR_IGUANA) += iguanair.o
obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
obj-$(CONFIG_RC_ST) += st_rc.o
+obj-$(CONFIG_IR_SUNXI) += sunxi-cir.o
obj-$(CONFIG_IR_IMG) += img-ir/
diff --git a/drivers/media/rc/img-ir/img-ir-core.c b/drivers/media/rc/img-ir/img-ir-core.c
index 6b7834834fb8..a0cac2f09109 100644
--- a/drivers/media/rc/img-ir/img-ir-core.c
+++ b/drivers/media/rc/img-ir/img-ir-core.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This contains core img-ir code for setting up the driver. The two interfaces
* (raw and hardware decode) are handled separately.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-hw.c b/drivers/media/rc/img-ir/img-ir-hw.c
index 0127dd257a57..153c0840bf4c 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.c
+++ b/drivers/media/rc/img-ir/img-ir-hw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core. Protocol support is
* provided in separate modules which provide the parameters and scancode
* translation functions to set up the hardware decoder and interpret the
diff --git a/drivers/media/rc/img-ir/img-ir-hw.h b/drivers/media/rc/img-ir/img-ir-hw.h
index 6c9a94a81190..450f17dfb66a 100644
--- a/drivers/media/rc/img-ir/img-ir-hw.h
+++ b/drivers/media/rc/img-ir/img-ir-hw.h
@@ -2,6 +2,11 @@
* ImgTec IR Hardware Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_HW_H_
diff --git a/drivers/media/rc/img-ir/img-ir-jvc.c b/drivers/media/rc/img-ir/img-ir-jvc.c
index 10209d200efb..85ee90f53242 100644
--- a/drivers/media/rc/img-ir/img-ir-jvc.c
+++ b/drivers/media/rc/img-ir/img-ir-jvc.c
@@ -2,6 +2,11 @@
* ImgTec IR Decoder setup for JVC protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
diff --git a/drivers/media/rc/img-ir/img-ir-nec.c b/drivers/media/rc/img-ir/img-ir-nec.c
index 751d9d945269..f7520e25fbdb 100644
--- a/drivers/media/rc/img-ir/img-ir-nec.c
+++ b/drivers/media/rc/img-ir/img-ir-nec.c
@@ -2,6 +2,11 @@
* ImgTec IR Decoder setup for NEC protocol.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
diff --git a/drivers/media/rc/img-ir/img-ir-raw.c b/drivers/media/rc/img-ir/img-ir-raw.c
index cfb01d9e571a..33f37ed87ad2 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.c
+++ b/drivers/media/rc/img-ir/img-ir-raw.c
@@ -3,6 +3,11 @@
*
* Copyright 2010-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* This ties into the input subsystem using the RC-core in raw mode. Raw IR
* signal edges are reported and decoded by generic software decoders.
*/
diff --git a/drivers/media/rc/img-ir/img-ir-raw.h b/drivers/media/rc/img-ir/img-ir-raw.h
index 9802ffd51b9a..4c9b7676e6fc 100644
--- a/drivers/media/rc/img-ir/img-ir-raw.h
+++ b/drivers/media/rc/img-ir/img-ir-raw.h
@@ -2,6 +2,11 @@
* ImgTec IR Raw Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_RAW_H_
diff --git a/drivers/media/rc/img-ir/img-ir-sanyo.c b/drivers/media/rc/img-ir/img-ir-sanyo.c
index c2c763e08a41..6755c945bce8 100644
--- a/drivers/media/rc/img-ir/img-ir-sanyo.c
+++ b/drivers/media/rc/img-ir/img-ir-sanyo.c
@@ -3,6 +3,11 @@
*
* Copyright 2012-2014 Imagination Technologies Ltd.
*
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
+ *
* From ir-sanyo-decoder.c:
*
* This protocol uses the NEC protocol timings. However, data is formatted as:
diff --git a/drivers/media/rc/img-ir/img-ir-sharp.c b/drivers/media/rc/img-ir/img-ir-sharp.c
index 3397cc5a6794..5867be088cce 100644
--- a/drivers/media/rc/img-ir/img-ir-sharp.c
+++ b/drivers/media/rc/img-ir/img-ir-sharp.c
@@ -2,6 +2,11 @@
* ImgTec IR Decoder setup for Sharp protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
diff --git a/drivers/media/rc/img-ir/img-ir-sony.c b/drivers/media/rc/img-ir/img-ir-sony.c
index 993409a51a71..b9029aecceac 100644
--- a/drivers/media/rc/img-ir/img-ir-sony.c
+++ b/drivers/media/rc/img-ir/img-ir-sony.c
@@ -2,6 +2,11 @@
* ImgTec IR Decoder setup for Sony (SIRC) protocol.
*
* Copyright 2012-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#include "img-ir-hw.h"
diff --git a/drivers/media/rc/img-ir/img-ir.h b/drivers/media/rc/img-ir/img-ir.h
index afb189394af9..2ddf56083182 100644
--- a/drivers/media/rc/img-ir/img-ir.h
+++ b/drivers/media/rc/img-ir/img-ir.h
@@ -2,6 +2,11 @@
* ImgTec IR Decoder found in PowerDown Controller.
*
* Copyright 2010-2014 Imagination Technologies Ltd.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by the
+ * Free Software Foundation; either version 2 of the License, or (at your
+ * option) any later version.
*/
#ifndef _IMG_IR_H_
diff --git a/drivers/media/rc/sunxi-cir.c b/drivers/media/rc/sunxi-cir.c
new file mode 100644
index 000000000000..13dcd800eb41
--- /dev/null
+++ b/drivers/media/rc/sunxi-cir.c
@@ -0,0 +1,318 @@
+/*
+ * Driver for Allwinner sunXi IR controller
+ *
+ * Copyright (C) 2014 Alexsey Shestacov <wingrime@linux-sunxi.org>
+ * Copyright (C) 2014 Alexander Bersenev <bay@hackerdom.ru>
+ *
+ * Based on sun5i-ir.c:
+ * Copyright (C) 2007-2012 Daniel Wang
+ * Allwinner Technology Co., Ltd. <www.allwinnertech.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of
+ * the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/clk.h>
+#include <linux/interrupt.h>
+#include <linux/module.h>
+#include <linux/of_platform.h>
+#include <media/rc-core.h>
+
+#define SUNXI_IR_DEV "sunxi-ir"
+
+/* Registers */
+/* IR Control */
+#define SUNXI_IR_CTL_REG 0x00
+/* Global Enable */
+#define REG_CTL_GEN BIT(0)
+/* RX block enable */
+#define REG_CTL_RXEN BIT(1)
+/* CIR mode */
+#define REG_CTL_MD (BIT(4) | BIT(5))
+
+/* Rx Config */
+#define SUNXI_IR_RXCTL_REG 0x10
+/* Pulse Polarity Invert flag */
+#define REG_RXCTL_RPPI BIT(2)
+
+/* Rx Data */
+#define SUNXI_IR_RXFIFO_REG 0x20
+
+/* Rx Interrupt Enable */
+#define SUNXI_IR_RXINT_REG 0x2C
+/* Rx FIFO Overflow */
+#define REG_RXINT_ROI_EN BIT(0)
+/* Rx Packet End */
+#define REG_RXINT_RPEI_EN BIT(1)
+/* Rx FIFO Data Available */
+#define REG_RXINT_RAI_EN BIT(4)
+
+/* Rx FIFO available byte level */
+#define REG_RXINT_RAL(val) (((val) << 8) & (GENMASK(11, 8)))
+
+/* Rx Interrupt Status */
+#define SUNXI_IR_RXSTA_REG 0x30
+/* RX FIFO Get Available Counter */
+#define REG_RXSTA_GET_AC(val) (((val) >> 8) & (GENMASK(5, 0)))
+/* Clear all interrupt status value */
+#define REG_RXSTA_CLEARALL 0xff
+
+/* IR Sample Config */
+#define SUNXI_IR_CIR_REG 0x34
+/* CIR_REG register noise threshold */
+#define REG_CIR_NTHR(val) (((val) << 2) & (GENMASK(7, 2)))
+/* CIR_REG register idle threshold */
+#define REG_CIR_ITHR(val) (((val) << 8) & (GENMASK(15, 8)))
+
+/* Hardware supported fifo size */
+#define SUNXI_IR_FIFO_SIZE 16
+/* How many messages in FIFO trigger IRQ */
+#define TRIGGER_LEVEL 8
+/* Required frequency for IR0 or IR1 clock in CIR mode */
+#define SUNXI_IR_BASE_CLK 8000000
+/* Frequency after IR internal divider */
+#define SUNXI_IR_CLK (SUNXI_IR_BASE_CLK / 64)
+/* Sample period in ns */
+#define SUNXI_IR_SAMPLE (1000000000ul / SUNXI_IR_CLK)
+/* Noise threshold in samples */
+#define SUNXI_IR_RXNOISE 1
+/* Idle Threshold in samples */
+#define SUNXI_IR_RXIDLE 20
+/* Time after which device stops sending data in ms */
+#define SUNXI_IR_TIMEOUT 120
+
+struct sunxi_ir {
+ spinlock_t ir_lock;
+ struct rc_dev *rc;
+ void __iomem *base;
+ int irq;
+ struct clk *clk;
+ struct clk *apb_clk;
+ const char *map_name;
+};
+
+static irqreturn_t sunxi_ir_irq(int irqno, void *dev_id)
+{
+ unsigned long status;
+ unsigned char dt;
+ unsigned int cnt, rc;
+ struct sunxi_ir *ir = dev_id;
+ DEFINE_IR_RAW_EVENT(rawir);
+
+ spin_lock(&ir->ir_lock);
+
+ status = readl(ir->base + SUNXI_IR_RXSTA_REG);
+
+ /* clean all pending statuses */
+ writel(status | REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ if (status & REG_RXINT_RAI_EN) {
+ /* How many messages in fifo */
+ rc = REG_RXSTA_GET_AC(status);
+ /* Sanity check */
+ rc = rc > SUNXI_IR_FIFO_SIZE ? SUNXI_IR_FIFO_SIZE : rc;
+ /* If we have data */
+ for (cnt = 0; cnt < rc; cnt++) {
+ /* for each bit in fifo */
+ dt = readb(ir->base + SUNXI_IR_RXFIFO_REG);
+ rawir.pulse = (dt & 0x80) != 0;
+ rawir.duration = ((dt & 0x7f) + 1) * SUNXI_IR_SAMPLE;
+ ir_raw_event_store_with_filter(ir->rc, &rawir);
+ }
+ }
+
+ if (status & REG_RXINT_ROI_EN) {
+ ir_raw_event_reset(ir->rc);
+ } else if (status & REG_RXINT_RPEI_EN) {
+ ir_raw_event_set_idle(ir->rc, true);
+ ir_raw_event_handle(ir->rc);
+ }
+
+ spin_unlock(&ir->ir_lock);
+
+ return IRQ_HANDLED;
+}
+
+static int sunxi_ir_probe(struct platform_device *pdev)
+{
+ int ret = 0;
+ unsigned long tmp = 0;
+
+ struct device *dev = &pdev->dev;
+ struct device_node *dn = dev->of_node;
+ struct resource *res;
+ struct sunxi_ir *ir;
+
+ ir = devm_kzalloc(dev, sizeof(struct sunxi_ir), GFP_KERNEL);
+ if (!ir)
+ return -ENOMEM;
+
+ /* Clock */
+ ir->apb_clk = devm_clk_get(dev, "apb");
+ if (IS_ERR(ir->apb_clk)) {
+ dev_err(dev, "failed to get a apb clock.\n");
+ return PTR_ERR(ir->apb_clk);
+ }
+ ir->clk = devm_clk_get(dev, "ir");
+ if (IS_ERR(ir->clk)) {
+ dev_err(dev, "failed to get a ir clock.\n");
+ return PTR_ERR(ir->clk);
+ }
+
+ ret = clk_set_rate(ir->clk, SUNXI_IR_BASE_CLK);
+ if (ret) {
+ dev_err(dev, "set ir base clock failed!\n");
+ return ret;
+ }
+
+ if (clk_prepare_enable(ir->apb_clk)) {
+ dev_err(dev, "try to enable apb_ir_clk failed\n");
+ return -EINVAL;
+ }
+
+ if (clk_prepare_enable(ir->clk)) {
+ dev_err(dev, "try to enable ir_clk failed\n");
+ ret = -EINVAL;
+ goto exit_clkdisable_apb_clk;
+ }
+
+ /* IO */
+ res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+ ir->base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(ir->base)) {
+ dev_err(dev, "failed to map registers\n");
+ ret = PTR_ERR(ir->base);
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc = rc_allocate_device();
+ if (!ir->rc) {
+ dev_err(dev, "failed to allocate device\n");
+ ret = -ENOMEM;
+ goto exit_clkdisable_clk;
+ }
+
+ ir->rc->priv = ir;
+ ir->rc->input_name = SUNXI_IR_DEV;
+ ir->rc->input_phys = "sunxi-ir/input0";
+ ir->rc->input_id.bustype = BUS_HOST;
+ ir->rc->input_id.vendor = 0x0001;
+ ir->rc->input_id.product = 0x0001;
+ ir->rc->input_id.version = 0x0100;
+ ir->map_name = of_get_property(dn, "linux,rc-map-name", NULL);
+ ir->rc->map_name = ir->map_name ?: RC_MAP_EMPTY;
+ ir->rc->dev.parent = dev;
+ ir->rc->driver_type = RC_DRIVER_IR_RAW;
+ rc_set_allowed_protocols(ir->rc, RC_BIT_ALL);
+ ir->rc->rx_resolution = SUNXI_IR_SAMPLE;
+ ir->rc->timeout = MS_TO_NS(SUNXI_IR_TIMEOUT);
+ ir->rc->driver_name = SUNXI_IR_DEV;
+
+ ret = rc_register_device(ir->rc);
+ if (ret) {
+ dev_err(dev, "failed to register rc device\n");
+ goto exit_free_dev;
+ }
+
+ platform_set_drvdata(pdev, ir);
+
+ /* IRQ */
+ ir->irq = platform_get_irq(pdev, 0);
+ if (ir->irq < 0) {
+ dev_err(dev, "no irq resource\n");
+ ret = ir->irq;
+ goto exit_free_dev;
+ }
+
+ ret = devm_request_irq(dev, ir->irq, sunxi_ir_irq, 0, SUNXI_IR_DEV, ir);
+ if (ret) {
+ dev_err(dev, "failed request irq\n");
+ goto exit_free_dev;
+ }
+
+ /* Enable CIR Mode */
+ writel(REG_CTL_MD, ir->base+SUNXI_IR_CTL_REG);
+
+ /* Set noise threshold and idle threshold */
+ writel(REG_CIR_NTHR(SUNXI_IR_RXNOISE)|REG_CIR_ITHR(SUNXI_IR_RXIDLE),
+ ir->base + SUNXI_IR_CIR_REG);
+
+ /* Invert Input Signal */
+ writel(REG_RXCTL_RPPI, ir->base + SUNXI_IR_RXCTL_REG);
+
+ /* Clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+
+ /*
+ * Enable IRQ on overflow, packet end, FIFO available with trigger
+ * level
+ */
+ writel(REG_RXINT_ROI_EN | REG_RXINT_RPEI_EN |
+ REG_RXINT_RAI_EN | REG_RXINT_RAL(TRIGGER_LEVEL - 1),
+ ir->base + SUNXI_IR_RXINT_REG);
+
+ /* Enable IR Module */
+ tmp = readl(ir->base + SUNXI_IR_CTL_REG);
+ writel(tmp | REG_CTL_GEN | REG_CTL_RXEN, ir->base + SUNXI_IR_CTL_REG);
+
+ dev_info(dev, "initialized sunXi IR driver\n");
+ return 0;
+
+exit_free_dev:
+ rc_free_device(ir->rc);
+exit_clkdisable_clk:
+ clk_disable_unprepare(ir->clk);
+exit_clkdisable_apb_clk:
+ clk_disable_unprepare(ir->apb_clk);
+
+ return ret;
+}
+
+static int sunxi_ir_remove(struct platform_device *pdev)
+{
+ unsigned long flags;
+ struct sunxi_ir *ir = platform_get_drvdata(pdev);
+
+ clk_disable_unprepare(ir->clk);
+ clk_disable_unprepare(ir->apb_clk);
+
+ spin_lock_irqsave(&ir->ir_lock, flags);
+ /* disable IR IRQ */
+ writel(0, ir->base + SUNXI_IR_RXINT_REG);
+ /* clear All Rx Interrupt Status */
+ writel(REG_RXSTA_CLEARALL, ir->base + SUNXI_IR_RXSTA_REG);
+ /* disable IR */
+ writel(0, ir->base + SUNXI_IR_CTL_REG);
+ spin_unlock_irqrestore(&ir->ir_lock, flags);
+
+ rc_unregister_device(ir->rc);
+ return 0;
+}
+
+static const struct of_device_id sunxi_ir_match[] = {
+ { .compatible = "allwinner,sun4i-a10-ir", },
+ {},
+};
+
+static struct platform_driver sunxi_ir_driver = {
+ .probe = sunxi_ir_probe,
+ .remove = sunxi_ir_remove,
+ .driver = {
+ .name = SUNXI_IR_DEV,
+ .owner = THIS_MODULE,
+ .of_match_table = sunxi_ir_match,
+ },
+};
+
+module_platform_driver(sunxi_ir_driver);
+
+MODULE_DESCRIPTION("Allwinner sunXi IR controller driver");
+MODULE_AUTHOR("Alexsey Shestacov <wingrime@linux-sunxi.org>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/Kconfig b/drivers/media/tuners/Kconfig
index 22b6b8bb1d93..906461da1310 100644
--- a/drivers/media/tuners/Kconfig
+++ b/drivers/media/tuners/Kconfig
@@ -71,6 +71,12 @@ config MEDIA_TUNER_TEA5767
help
Say Y here to include support for the Philips TEA5767 radio tuner.
+config MEDIA_TUNER_MSI001
+ tristate "Mirics MSi001"
+ depends on MEDIA_SUPPORT && SPI && VIDEO_V4L2
+ help
+ Mirics MSi001 silicon tuner driver.
+
config MEDIA_TUNER_MT20XX
tristate "Microtune 2032 / 2050 tuners"
depends on MEDIA_SUPPORT && I2C
diff --git a/drivers/media/tuners/Makefile b/drivers/media/tuners/Makefile
index a6ff0c628dfa..5591699755ba 100644
--- a/drivers/media/tuners/Makefile
+++ b/drivers/media/tuners/Makefile
@@ -17,6 +17,7 @@ obj-$(CONFIG_MEDIA_TUNER_TDA827X) += tda827x.o
obj-$(CONFIG_MEDIA_TUNER_TDA18271) += tda18271.o
obj-$(CONFIG_MEDIA_TUNER_XC5000) += xc5000.o
obj-$(CONFIG_MEDIA_TUNER_XC4000) += xc4000.o
+obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o
obj-$(CONFIG_MEDIA_TUNER_MT2060) += mt2060.o
obj-$(CONFIG_MEDIA_TUNER_MT2063) += mt2063.o
obj-$(CONFIG_MEDIA_TUNER_MT2266) += mt2266.o
diff --git a/drivers/staging/media/msi3101/msi001.c b/drivers/media/tuners/msi001.c
index bd0b93cb6c53..ee99e372c943 100644
--- a/drivers/staging/media/msi3101/msi001.c
+++ b/drivers/media/tuners/msi001.c
@@ -381,7 +381,7 @@ static int msi001_s_ctrl(struct v4l2_ctrl *ctrl)
int ret;
dev_dbg(&s->spi->dev,
- "%s: id=%d name=%s val=%d min=%d max=%d step=%d\n",
+ "%s: id=%d name=%s val=%d min=%lld max=%lld step=%lld\n",
__func__, ctrl->id, ctrl->name, ctrl->val,
ctrl->minimum, ctrl->maximum, ctrl->step);
diff --git a/drivers/media/tuners/r820t.c b/drivers/media/tuners/r820t.c
index 96ccfebce7ca..a0db64f57a98 100644
--- a/drivers/media/tuners/r820t.c
+++ b/drivers/media/tuners/r820t.c
@@ -1545,7 +1545,7 @@ static int r820t_imr_cross(struct r820t_priv *priv,
cross[i].value = rc;
if (cross[i].value < tmp.value)
- memcpy(&tmp, &cross[i], sizeof(tmp));
+ tmp = cross[i];
}
if ((tmp.phase_y & 0x1f) == 1) { /* y-direction */
diff --git a/drivers/media/tuners/si2157.c b/drivers/media/tuners/si2157.c
index fa4cc7b880aa..6c53edb73a63 100644
--- a/drivers/media/tuners/si2157.c
+++ b/drivers/media/tuners/si2157.c
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -16,54 +16,58 @@
#include "si2157_priv.h"
+static const struct dvb_tuner_ops si2157_ops;
+
/* execute firmware command */
static int si2157_cmd_execute(struct si2157 *s, struct si2157_cmd *cmd)
{
int ret;
- u8 buf[1];
unsigned long timeout;
mutex_lock(&s->i2c_mutex);
- if (cmd->len) {
+ if (cmd->wlen) {
/* write cmd and args for firmware */
- ret = i2c_master_send(s->client, cmd->args, cmd->len);
+ ret = i2c_master_send(s->client, cmd->args, cmd->wlen);
if (ret < 0) {
goto err_mutex_unlock;
- } else if (ret != cmd->len) {
+ } else if (ret != cmd->wlen) {
ret = -EREMOTEIO;
goto err_mutex_unlock;
}
}
- /* wait cmd execution terminate */
- #define TIMEOUT 80
- timeout = jiffies + msecs_to_jiffies(TIMEOUT);
- while (!time_after(jiffies, timeout)) {
- ret = i2c_master_recv(s->client, buf, 1);
- if (ret < 0) {
- goto err_mutex_unlock;
- } else if (ret != 1) {
- ret = -EREMOTEIO;
- goto err_mutex_unlock;
+ if (cmd->rlen) {
+ /* wait cmd execution terminate */
+ #define TIMEOUT 80
+ timeout = jiffies + msecs_to_jiffies(TIMEOUT);
+ while (!time_after(jiffies, timeout)) {
+ ret = i2c_master_recv(s->client, cmd->args, cmd->rlen);
+ if (ret < 0) {
+ goto err_mutex_unlock;
+ } else if (ret != cmd->rlen) {
+ ret = -EREMOTEIO;
+ goto err_mutex_unlock;
+ }
+
+ /* firmware ready? */
+ if ((cmd->args[0] >> 7) & 0x01)
+ break;
}
- /* firmware ready? */
- if ((buf[0] >> 7) & 0x01)
- break;
- }
+ dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n",
+ __func__,
+ jiffies_to_msecs(jiffies) -
+ (jiffies_to_msecs(timeout) - TIMEOUT));
- dev_dbg(&s->client->dev, "%s: cmd execution took %d ms\n", __func__,
- jiffies_to_msecs(jiffies) -
- (jiffies_to_msecs(timeout) - TIMEOUT));
-
- if (!((buf[0] >> 7) & 0x01)) {
- ret = -ETIMEDOUT;
- goto err_mutex_unlock;
- } else {
- ret = 0;
+ if (!((cmd->args[0] >> 7) & 0x01)) {
+ ret = -ETIMEDOUT;
+ goto err_mutex_unlock;
+ }
}
+ ret = 0;
+
err_mutex_unlock:
mutex_unlock(&s->i2c_mutex);
if (ret)
@@ -78,23 +82,133 @@ err:
static int si2157_init(struct dvb_frontend *fe)
{
struct si2157 *s = fe->tuner_priv;
+ int ret, len, remaining;
+ struct si2157_cmd cmd;
+ const struct firmware *fw = NULL;
+ u8 *fw_file;
+ unsigned int chip_id;
dev_dbg(&s->client->dev, "%s:\n", __func__);
+ /* configure? */
+ memcpy(cmd.args, "\xc0\x00\x0c\x00\x00\x01\x01\x01\x01\x01\x01\x02\x00\x00\x01", 15);
+ cmd.wlen = 15;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
+ /* query chip revision */
+ memcpy(cmd.args, "\x02", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 13;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
+ chip_id = cmd.args[1] << 24 | cmd.args[2] << 16 | cmd.args[3] << 8 |
+ cmd.args[4] << 0;
+
+ #define SI2158_A20 ('A' << 24 | 58 << 16 | '2' << 8 | '0' << 0)
+ #define SI2157_A30 ('A' << 24 | 57 << 16 | '3' << 8 | '0' << 0)
+
+ switch (chip_id) {
+ case SI2158_A20:
+ fw_file = SI2158_A20_FIRMWARE;
+ break;
+ case SI2157_A30:
+ goto skip_fw_download;
+ break;
+ default:
+ dev_err(&s->client->dev,
+ "%s: unkown chip version Si21%d-%c%c%c\n",
+ KBUILD_MODNAME, cmd.args[2], cmd.args[1],
+ cmd.args[3], cmd.args[4]);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* cold state - try to download firmware */
+ dev_info(&s->client->dev, "%s: found a '%s' in cold state\n",
+ KBUILD_MODNAME, si2157_ops.info.name);
+
+ /* request the firmware, this will block and timeout */
+ ret = request_firmware(&fw, fw_file, &s->client->dev);
+ if (ret) {
+ dev_err(&s->client->dev, "%s: firmware file '%s' not found\n",
+ KBUILD_MODNAME, fw_file);
+ goto err;
+ }
+
+ /* firmware should be n chunks of 17 bytes */
+ if (fw->size % 17 != 0) {
+ dev_err(&s->client->dev, "%s: firmware file '%s' is invalid\n",
+ KBUILD_MODNAME, fw_file);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ dev_info(&s->client->dev, "%s: downloading firmware from file '%s'\n",
+ KBUILD_MODNAME, fw_file);
+
+ for (remaining = fw->size; remaining > 0; remaining -= 17) {
+ len = fw->data[fw->size - remaining];
+ memcpy(cmd.args, &fw->data[(fw->size - remaining) + 1], len);
+ cmd.wlen = len;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret) {
+ dev_err(&s->client->dev,
+ "%s: firmware download failed=%d\n",
+ KBUILD_MODNAME, ret);
+ goto err;
+ }
+ }
+
+ release_firmware(fw);
+ fw = NULL;
+
+skip_fw_download:
+ /* reboot the tuner with new firmware? */
+ memcpy(cmd.args, "\x01\x01", 2);
+ cmd.wlen = 2;
+ cmd.rlen = 1;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
s->active = true;
return 0;
+err:
+ if (fw)
+ release_firmware(fw);
+
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2157_sleep(struct dvb_frontend *fe)
{
struct si2157 *s = fe->tuner_priv;
+ int ret;
+ struct si2157_cmd cmd;
dev_dbg(&s->client->dev, "%s:\n", __func__);
s->active = false;
+ memcpy(cmd.args, "\x13", 1);
+ cmd.wlen = 1;
+ cmd.rlen = 0;
+ ret = si2157_cmd_execute(s, &cmd);
+ if (ret)
+ goto err;
+
return 0;
+err:
+ dev_dbg(&s->client->dev, "%s: failed=%d\n", __func__, ret);
+ return ret;
}
static int si2157_set_params(struct dvb_frontend *fe)
@@ -103,6 +217,7 @@ static int si2157_set_params(struct dvb_frontend *fe)
struct dtv_frontend_properties *c = &fe->dtv_property_cache;
int ret;
struct si2157_cmd cmd;
+ u8 bandwidth, delivery_system;
dev_dbg(&s->client->dev,
"%s: delivery_system=%d frequency=%u bandwidth_hz=%u\n",
@@ -114,50 +229,46 @@ static int si2157_set_params(struct dvb_frontend *fe)
goto err;
}
- /* configure? */
- cmd.args[0] = 0xc0;
- cmd.args[1] = 0x00;
- cmd.args[2] = 0x0c;
- cmd.args[3] = 0x00;
- cmd.args[4] = 0x00;
- cmd.args[5] = 0x01;
- cmd.args[6] = 0x01;
- cmd.args[7] = 0x01;
- cmd.args[8] = 0x01;
- cmd.args[9] = 0x01;
- cmd.args[10] = 0x01;
- cmd.args[11] = 0x02;
- cmd.args[12] = 0x00;
- cmd.args[13] = 0x00;
- cmd.args[14] = 0x01;
- cmd.len = 15;
- ret = si2157_cmd_execute(s, &cmd);
- if (ret)
- goto err;
-
- cmd.args[0] = 0x02;
- cmd.len = 1;
- ret = si2157_cmd_execute(s, &cmd);
- if (ret)
- goto err;
+ if (c->bandwidth_hz <= 6000000)
+ bandwidth = 0x06;
+ else if (c->bandwidth_hz <= 7000000)
+ bandwidth = 0x07;
+ else if (c->bandwidth_hz <= 8000000)
+ bandwidth = 0x08;
+ else
+ bandwidth = 0x0f;
+
+ switch (c->delivery_system) {
+ case SYS_DVBT:
+ case SYS_DVBT2: /* it seems DVB-T and DVB-T2 both are 0x20 here */
+ delivery_system = 0x20;
+ break;
+ case SYS_DVBC_ANNEX_A:
+ delivery_system = 0x30;
+ break;
+ default:
+ ret = -EINVAL;
+ goto err;
+ }
- cmd.args[0] = 0x01;
- cmd.args[1] = 0x01;
- cmd.len = 2;
+ memcpy(cmd.args, "\x14\x00\x03\x07\x00\x00", 6);
+ cmd.args[4] = delivery_system | bandwidth;
+ if (s->inversion)
+ cmd.args[5] = 0x01;
+ cmd.wlen = 6;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
/* set frequency */
- cmd.args[0] = 0x41;
- cmd.args[1] = 0x00;
- cmd.args[2] = 0x00;
- cmd.args[3] = 0x00;
+ memcpy(cmd.args, "\x41\x00\x00\x00\x00\x00\x00\x00", 8);
cmd.args[4] = (c->frequency >> 0) & 0xff;
cmd.args[5] = (c->frequency >> 8) & 0xff;
cmd.args[6] = (c->frequency >> 16) & 0xff;
cmd.args[7] = (c->frequency >> 24) & 0xff;
- cmd.len = 8;
+ cmd.wlen = 8;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
@@ -168,9 +279,15 @@ err:
return ret;
}
-static const struct dvb_tuner_ops si2157_tuner_ops = {
+static int si2157_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+ *frequency = 5000000; /* default value of property 0x0706 */
+ return 0;
+}
+
+static const struct dvb_tuner_ops si2157_ops = {
.info = {
- .name = "Silicon Labs Si2157",
+ .name = "Silicon Labs Si2157/Si2158",
.frequency_min = 110000000,
.frequency_max = 862000000,
},
@@ -178,6 +295,7 @@ static const struct dvb_tuner_ops si2157_tuner_ops = {
.init = si2157_init,
.sleep = si2157_sleep,
.set_params = si2157_set_params,
+ .get_if_frequency = si2157_get_if_frequency,
};
static int si2157_probe(struct i2c_client *client,
@@ -198,22 +316,24 @@ static int si2157_probe(struct i2c_client *client,
s->client = client;
s->fe = cfg->fe;
+ s->inversion = cfg->inversion;
mutex_init(&s->i2c_mutex);
/* check if the tuner is there */
- cmd.len = 0;
+ cmd.wlen = 0;
+ cmd.rlen = 1;
ret = si2157_cmd_execute(s, &cmd);
if (ret)
goto err;
fe->tuner_priv = s;
- memcpy(&fe->ops.tuner_ops, &si2157_tuner_ops,
+ memcpy(&fe->ops.tuner_ops, &si2157_ops,
sizeof(struct dvb_tuner_ops));
i2c_set_clientdata(client, s);
dev_info(&s->client->dev,
- "%s: Silicon Labs Si2157 successfully attached\n",
+ "%s: Silicon Labs Si2157/Si2158 successfully attached\n",
KBUILD_MODNAME);
return 0;
err:
@@ -255,6 +375,7 @@ static struct i2c_driver si2157_driver = {
module_i2c_driver(si2157_driver);
-MODULE_DESCRIPTION("Silicon Labs Si2157 silicon tuner driver");
+MODULE_DESCRIPTION("Silicon Labs Si2157/Si2158 silicon tuner driver");
MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(SI2158_A20_FIRMWARE);
diff --git a/drivers/media/tuners/si2157.h b/drivers/media/tuners/si2157.h
index f469a092b66b..6da4d5d1c817 100644
--- a/drivers/media/tuners/si2157.h
+++ b/drivers/media/tuners/si2157.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -29,6 +29,11 @@ struct si2157_config {
* frontend
*/
struct dvb_frontend *fe;
+
+ /*
+ * Spectral Inversion
+ */
+ bool inversion;
};
#endif
diff --git a/drivers/media/tuners/si2157_priv.h b/drivers/media/tuners/si2157_priv.h
index 6cc6c6fdab7a..3ddab5e6b500 100644
--- a/drivers/media/tuners/si2157_priv.h
+++ b/drivers/media/tuners/si2157_priv.h
@@ -1,5 +1,5 @@
/*
- * Silicon Labs Si2157 silicon tuner driver
+ * Silicon Labs Si2157/2158 silicon tuner driver
*
* Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
*
@@ -17,6 +17,7 @@
#ifndef SI2157_PRIV_H
#define SI2157_PRIV_H
+#include <linux/firmware.h>
#include "si2157.h"
/* state struct */
@@ -25,13 +26,17 @@ struct si2157 {
struct i2c_client *client;
struct dvb_frontend *fe;
bool active;
+ bool inversion;
};
/* firmare command struct */
#define SI2157_ARGLEN 30
struct si2157_cmd {
u8 args[SI2157_ARGLEN];
- unsigned len;
+ unsigned wlen;
+ unsigned rlen;
};
+#define SI2158_A20_FIRMWARE "dvb-tuner-si2158-a20-01.fw"
+
#endif
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
index 39d824e2bb69..fa67519abda2 100644
--- a/drivers/media/usb/Kconfig
+++ b/drivers/media/usb/Kconfig
@@ -52,5 +52,11 @@ if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
source "drivers/media/usb/em28xx/Kconfig"
endif
+if MEDIA_SDR_SUPPORT
+ comment "Software defined radio USB devices"
+source "drivers/media/usb/msi2500/Kconfig"
+source "drivers/media/usb/airspy/Kconfig"
+endif
+
endif #MEDIA_USB_SUPPORT
endif #USB
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
index 7ac4b143dce8..712a6b1e8882 100644
--- a/drivers/media/usb/Makefile
+++ b/drivers/media/usb/Makefile
@@ -9,6 +9,8 @@ obj-y += zr364xx/ stkwebcam/ s2255/
obj-$(CONFIG_USB_VIDEO_CLASS) += uvc/
obj-$(CONFIG_USB_GSPCA) += gspca/
obj-$(CONFIG_USB_PWC) += pwc/
+obj-$(CONFIG_USB_MSI2500) += msi2500/
+obj-$(CONFIG_USB_AIRSPY) += airspy/
obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
obj-$(CONFIG_VIDEO_AU0828) += au0828/
obj-$(CONFIG_VIDEO_HDPVR) += hdpvr/
diff --git a/drivers/media/usb/airspy/Kconfig b/drivers/media/usb/airspy/Kconfig
new file mode 100644
index 000000000000..10b204cf4dbc
--- /dev/null
+++ b/drivers/media/usb/airspy/Kconfig
@@ -0,0 +1,10 @@
+config USB_AIRSPY
+ tristate "AirSpy"
+ depends on VIDEO_V4L2
+ select VIDEOBUF2_VMALLOC
+ ---help---
+ This is a video4linux2 driver for AirSpy SDR device.
+
+ To compile this driver as a module, choose M here: the
+ module will be called airspy
+
diff --git a/drivers/media/usb/airspy/Makefile b/drivers/media/usb/airspy/Makefile
new file mode 100644
index 000000000000..8d8e61c1a349
--- /dev/null
+++ b/drivers/media/usb/airspy/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_AIRSPY) += airspy.o
diff --git a/drivers/media/usb/airspy/airspy.c b/drivers/media/usb/airspy/airspy.c
new file mode 100644
index 000000000000..cb0e515d80ae
--- /dev/null
+++ b/drivers/media/usb/airspy/airspy.c
@@ -0,0 +1,1132 @@
+/*
+ * AirSpy SDR driver
+ *
+ * Copyright (C) 2014 Antti Palosaari <crope@iki.fi>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/usb.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-event.h>
+#include <media/videobuf2-vmalloc.h>
+
+/* AirSpy USB API commands (from AirSpy Library) */
+enum {
+ CMD_INVALID = 0x00,
+ CMD_RECEIVER_MODE = 0x01,
+ CMD_SI5351C_WRITE = 0x02,
+ CMD_SI5351C_READ = 0x03,
+ CMD_R820T_WRITE = 0x04,
+ CMD_R820T_READ = 0x05,
+ CMD_SPIFLASH_ERASE = 0x06,
+ CMD_SPIFLASH_WRITE = 0x07,
+ CMD_SPIFLASH_READ = 0x08,
+ CMD_BOARD_ID_READ = 0x09,
+ CMD_VERSION_STRING_READ = 0x0a,
+ CMD_BOARD_PARTID_SERIALNO_READ = 0x0b,
+ CMD_SET_SAMPLE_RATE = 0x0c,
+ CMD_SET_FREQ = 0x0d,
+ CMD_SET_LNA_GAIN = 0x0e,
+ CMD_SET_MIXER_GAIN = 0x0f,
+ CMD_SET_VGA_GAIN = 0x10,
+ CMD_SET_LNA_AGC = 0x11,
+ CMD_SET_MIXER_AGC = 0x12,
+ CMD_SET_PACKING = 0x13,
+};
+
+/*
+ * bEndpointAddress 0x81 EP 1 IN
+ * Transfer Type Bulk
+ * wMaxPacketSize 0x0200 1x 512 bytes
+ */
+#define MAX_BULK_BUFS (6)
+#define BULK_BUFFER_SIZE (128 * 512)
+
+static const struct v4l2_frequency_band bands[] = {
+ {
+ .tuner = 0,
+ .type = V4L2_TUNER_ADC,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 20000000,
+ .rangehigh = 20000000,
+ },
+};
+
+static const struct v4l2_frequency_band bands_rf[] = {
+ {
+ .tuner = 1,
+ .type = V4L2_TUNER_RF,
+ .index = 0,
+ .capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS,
+ .rangelow = 24000000,
+ .rangehigh = 1750000000,
+ },
+};
+
+/* stream formats */
+struct airspy_format {
+ char *name;
+ u32 pixelformat;
+ u32 buffersize;
+};
+
+/* format descriptions for capture and preview */
+static struct airspy_format formats[] = {
+ {
+ .name = "Real U12LE",
+ .pixelformat = V4L2_SDR_FMT_RU12LE,
+ .buffersize = BULK_BUFFER_SIZE,
+ },
+};
+
+static const unsigned int NUM_FORMATS = ARRAY_SIZE(formats);
+
+/* intermediate buffers with raw data from the USB device */
+struct airspy_frame_buf {
+ struct vb2_buffer vb; /* common v4l buffer stuff -- must be first */
+ struct list_head list;
+};
+
+struct airspy {
+#define POWER_ON (1 << 1)
+#define URB_BUF (1 << 2)
+#define USB_STATE_URB_BUF (1 << 3)
+ unsigned long flags;
+
+ struct usb_device *udev;
+ struct video_device vdev;
+ struct v4l2_device v4l2_dev;
+
+ /* videobuf2 queue and queued buffers list */
+ struct vb2_queue vb_queue;
+ struct list_head queued_bufs;
+ spinlock_t queued_bufs_lock; /* Protects queued_bufs */
+ unsigned sequence; /* Buffer sequence counter */
+ unsigned int vb_full; /* vb is full and packets dropped */
+
+ /* Note if taking both locks v4l2_lock must always be locked first! */
+ struct mutex v4l2_lock; /* Protects everything else */
+ struct mutex vb_queue_lock; /* Protects vb_queue and capt_file */
+
+ struct urb *urb_list[MAX_BULK_BUFS];
+ int buf_num;
+ unsigned long buf_size;
+ u8 *buf_list[MAX_BULK_BUFS];
+ dma_addr_t dma_addr[MAX_BULK_BUFS];
+ int urbs_initialized;
+ int urbs_submitted;
+
+ /* USB control message buffer */
+ #define BUF_SIZE 24
+ u8 buf[BUF_SIZE];
+
+ /* Current configuration */
+ unsigned int f_adc;
+ unsigned int f_rf;
+ u32 pixelformat;
+ u32 buffersize;
+
+ /* Controls */
+ struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *lna_gain_auto;
+ struct v4l2_ctrl *lna_gain;
+ struct v4l2_ctrl *mixer_gain_auto;
+ struct v4l2_ctrl *mixer_gain;
+ struct v4l2_ctrl *if_gain;
+
+ /* Sample rate calc */
+ unsigned long jiffies_next;
+ unsigned int sample;
+ unsigned int sample_measured;
+};
+
+#define airspy_dbg_usb_control_msg(_udev, _r, _t, _v, _i, _b, _l) { \
+ char *_direction; \
+ if (_t & USB_DIR_IN) \
+ _direction = "<<<"; \
+ else \
+ _direction = ">>>"; \
+ dev_dbg(&_udev->dev, "%s: %02x %02x %02x %02x %02x %02x %02x %02x " \
+ "%s %*ph\n", __func__, _t, _r, _v & 0xff, _v >> 8, \
+ _i & 0xff, _i >> 8, _l & 0xff, _l >> 8, _direction, \
+ _l, _b); \
+}
+
+/* execute firmware command */
+static int airspy_ctrl_msg(struct airspy *s, u8 request, u16 value, u16 index,
+ u8 *data, u16 size)
+{
+ int ret;
+ unsigned int pipe;
+ u8 requesttype;
+
+ switch (request) {
+ case CMD_RECEIVER_MODE:
+ case CMD_SET_FREQ:
+ pipe = usb_sndctrlpipe(s->udev, 0);
+ requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
+ break;
+ case CMD_BOARD_ID_READ:
+ case CMD_VERSION_STRING_READ:
+ case CMD_BOARD_PARTID_SERIALNO_READ:
+ case CMD_SET_LNA_GAIN:
+ case CMD_SET_MIXER_GAIN:
+ case CMD_SET_VGA_GAIN:
+ case CMD_SET_LNA_AGC:
+ case CMD_SET_MIXER_AGC:
+ pipe = usb_rcvctrlpipe(s->udev, 0);
+ requesttype = (USB_TYPE_VENDOR | USB_DIR_IN);
+ break;
+ default:
+ dev_err(&s->udev->dev, "Unknown command %02x\n", request);
+ ret = -EINVAL;
+ goto err;
+ }
+
+ /* write request */
+ if (!(requesttype & USB_DIR_IN))
+ memcpy(s->buf, data, size);
+
+ ret = usb_control_msg(s->udev, pipe, request, requesttype, value,
+ index, s->buf, size, 1000);
+ airspy_dbg_usb_control_msg(s->udev, request, requesttype, value,
+ index, s->buf, size);
+ if (ret < 0) {
+ dev_err(&s->udev->dev,
+ "usb_control_msg() failed %d request %02x\n",
+ ret, request);
+ goto err;
+ }
+
+ /* read request */
+ if (requesttype & USB_DIR_IN)
+ memcpy(data, s->buf, size);
+
+ return 0;
+err:
+ return ret;
+}
+
+/* Private functions */
+static struct airspy_frame_buf *airspy_get_next_fill_buf(struct airspy *s)
+{
+ unsigned long flags = 0;
+ struct airspy_frame_buf *buf = NULL;
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ if (list_empty(&s->queued_bufs))
+ goto leave;
+
+ buf = list_entry(s->queued_bufs.next,
+ struct airspy_frame_buf, list);
+ list_del(&buf->list);
+leave:
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+ return buf;
+}
+
+static unsigned int airspy_convert_stream(struct airspy *s,
+ void *dst, void *src, unsigned int src_len)
+{
+ unsigned int dst_len;
+
+ if (s->pixelformat == V4L2_SDR_FMT_RU12LE) {
+ memcpy(dst, src, src_len);
+ dst_len = src_len;
+ } else {
+ dst_len = 0;
+ }
+
+ /* calculate samping rate and output it in 10 seconds intervals */
+ if (unlikely(time_is_before_jiffies(s->jiffies_next))) {
+ #define MSECS 10000UL
+ unsigned int samples = s->sample - s->sample_measured;
+ s->jiffies_next = jiffies + msecs_to_jiffies(MSECS);
+ s->sample_measured = s->sample;
+ dev_dbg(&s->udev->dev,
+ "slen=%d samples=%u msecs=%lu sample rate=%lu\n",
+ src_len, samples, MSECS,
+ samples * 1000UL / MSECS);
+ }
+
+ /* total number of samples */
+ s->sample += src_len / 2;
+
+ return dst_len;
+}
+
+/*
+ * This gets called for the bulk stream pipe. This is done in interrupt
+ * time, so it has to be fast, not crash, and not stall. Neat.
+ */
+static void airspy_urb_complete(struct urb *urb)
+{
+ struct airspy *s = urb->context;
+ struct airspy_frame_buf *fbuf;
+
+ dev_dbg_ratelimited(&s->udev->dev,
+ "%s: status=%d length=%d/%d errors=%d\n",
+ __func__, urb->status, urb->actual_length,
+ urb->transfer_buffer_length, urb->error_count);
+
+ switch (urb->status) {
+ case 0: /* success */
+ case -ETIMEDOUT: /* NAK */
+ break;
+ case -ECONNRESET: /* kill */
+ case -ENOENT:
+ case -ESHUTDOWN:
+ return;
+ default: /* error */
+ dev_err_ratelimited(&s->udev->dev, "URB failed %d\n",
+ urb->status);
+ break;
+ }
+
+ if (likely(urb->actual_length > 0)) {
+ void *ptr;
+ unsigned int len;
+ /* get free framebuffer */
+ fbuf = airspy_get_next_fill_buf(s);
+ if (unlikely(fbuf == NULL)) {
+ s->vb_full++;
+ dev_notice_ratelimited(&s->udev->dev,
+ "videobuf is full, %d packets dropped\n",
+ s->vb_full);
+ goto skip;
+ }
+
+ /* fill framebuffer */
+ ptr = vb2_plane_vaddr(&fbuf->vb, 0);
+ len = airspy_convert_stream(s, ptr, urb->transfer_buffer,
+ urb->actual_length);
+ vb2_set_plane_payload(&fbuf->vb, 0, len);
+ v4l2_get_timestamp(&fbuf->vb.v4l2_buf.timestamp);
+ fbuf->vb.v4l2_buf.sequence = s->sequence++;
+ vb2_buffer_done(&fbuf->vb, VB2_BUF_STATE_DONE);
+ }
+skip:
+ usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+static int airspy_kill_urbs(struct airspy *s)
+{
+ int i;
+
+ for (i = s->urbs_submitted - 1; i >= 0; i--) {
+ dev_dbg(&s->udev->dev, "%s: kill urb=%d\n", __func__, i);
+ /* stop the URB */
+ usb_kill_urb(s->urb_list[i]);
+ }
+ s->urbs_submitted = 0;
+
+ return 0;
+}
+
+static int airspy_submit_urbs(struct airspy *s)
+{
+ int i, ret;
+
+ for (i = 0; i < s->urbs_initialized; i++) {
+ dev_dbg(&s->udev->dev, "%s: submit urb=%d\n", __func__, i);
+ ret = usb_submit_urb(s->urb_list[i], GFP_ATOMIC);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Could not submit URB no. %d - get them all back\n",
+ i);
+ airspy_kill_urbs(s);
+ return ret;
+ }
+ s->urbs_submitted++;
+ }
+
+ return 0;
+}
+
+static int airspy_free_stream_bufs(struct airspy *s)
+{
+ if (s->flags & USB_STATE_URB_BUF) {
+ while (s->buf_num) {
+ s->buf_num--;
+ dev_dbg(&s->udev->dev, "%s: free buf=%d\n",
+ __func__, s->buf_num);
+ usb_free_coherent(s->udev, s->buf_size,
+ s->buf_list[s->buf_num],
+ s->dma_addr[s->buf_num]);
+ }
+ }
+ s->flags &= ~USB_STATE_URB_BUF;
+
+ return 0;
+}
+
+static int airspy_alloc_stream_bufs(struct airspy *s)
+{
+ s->buf_num = 0;
+ s->buf_size = BULK_BUFFER_SIZE;
+
+ dev_dbg(&s->udev->dev,
+ "%s: all in all I will use %u bytes for streaming\n",
+ __func__, MAX_BULK_BUFS * BULK_BUFFER_SIZE);
+
+ for (s->buf_num = 0; s->buf_num < MAX_BULK_BUFS; s->buf_num++) {
+ s->buf_list[s->buf_num] = usb_alloc_coherent(s->udev,
+ BULK_BUFFER_SIZE, GFP_ATOMIC,
+ &s->dma_addr[s->buf_num]);
+ if (!s->buf_list[s->buf_num]) {
+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d failed\n",
+ __func__, s->buf_num);
+ airspy_free_stream_bufs(s);
+ return -ENOMEM;
+ }
+
+ dev_dbg(&s->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+ __func__, s->buf_num,
+ s->buf_list[s->buf_num],
+ (long long)s->dma_addr[s->buf_num]);
+ s->flags |= USB_STATE_URB_BUF;
+ }
+
+ return 0;
+}
+
+static int airspy_free_urbs(struct airspy *s)
+{
+ int i;
+
+ airspy_kill_urbs(s);
+
+ for (i = s->urbs_initialized - 1; i >= 0; i--) {
+ if (s->urb_list[i]) {
+ dev_dbg(&s->udev->dev, "%s: free urb=%d\n",
+ __func__, i);
+ /* free the URBs */
+ usb_free_urb(s->urb_list[i]);
+ }
+ }
+ s->urbs_initialized = 0;
+
+ return 0;
+}
+
+static int airspy_alloc_urbs(struct airspy *s)
+{
+ int i, j;
+
+ /* allocate the URBs */
+ for (i = 0; i < MAX_BULK_BUFS; i++) {
+ dev_dbg(&s->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+ s->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+ if (!s->urb_list[i]) {
+ dev_dbg(&s->udev->dev, "%s: failed\n", __func__);
+ for (j = 0; j < i; j++)
+ usb_free_urb(s->urb_list[j]);
+ return -ENOMEM;
+ }
+ usb_fill_bulk_urb(s->urb_list[i],
+ s->udev,
+ usb_rcvbulkpipe(s->udev, 0x81),
+ s->buf_list[i],
+ BULK_BUFFER_SIZE,
+ airspy_urb_complete, s);
+
+ s->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+ s->urb_list[i]->transfer_dma = s->dma_addr[i];
+ s->urbs_initialized++;
+ }
+
+ return 0;
+}
+
+/* Must be called with vb_queue_lock hold */
+static void airspy_cleanup_queued_bufs(struct airspy *s)
+{
+ unsigned long flags = 0;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ while (!list_empty(&s->queued_bufs)) {
+ struct airspy_frame_buf *buf;
+ buf = list_entry(s->queued_bufs.next,
+ struct airspy_frame_buf, list);
+ list_del(&buf->list);
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ }
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+/* The user yanked out the cable... */
+static void airspy_disconnect(struct usb_interface *intf)
+{
+ struct v4l2_device *v = usb_get_intfdata(intf);
+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ mutex_lock(&s->vb_queue_lock);
+ mutex_lock(&s->v4l2_lock);
+ /* No need to keep the urbs around after disconnection */
+ s->udev = NULL;
+ v4l2_device_disconnect(&s->v4l2_dev);
+ video_unregister_device(&s->vdev);
+ mutex_unlock(&s->v4l2_lock);
+ mutex_unlock(&s->vb_queue_lock);
+
+ v4l2_device_put(&s->v4l2_dev);
+}
+
+/* Videobuf2 operations */
+static int airspy_queue_setup(struct vb2_queue *vq,
+ const struct v4l2_format *fmt, unsigned int *nbuffers,
+ unsigned int *nplanes, unsigned int sizes[], void *alloc_ctxs[])
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+
+ dev_dbg(&s->udev->dev, "%s: *nbuffers=%d\n", __func__, *nbuffers);
+
+ /* Need at least 8 buffers */
+ if (vq->num_buffers + *nbuffers < 8)
+ *nbuffers = 8 - vq->num_buffers;
+ *nplanes = 1;
+ sizes[0] = PAGE_ALIGN(s->buffersize);
+
+ dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
+ __func__, *nbuffers, sizes[0]);
+ return 0;
+}
+
+static void airspy_buf_queue(struct vb2_buffer *vb)
+{
+ struct airspy *s = vb2_get_drv_priv(vb->vb2_queue);
+ struct airspy_frame_buf *buf =
+ container_of(vb, struct airspy_frame_buf, vb);
+ unsigned long flags = 0;
+
+ /* Check the device has not disconnected between prep and queuing */
+ if (unlikely(!s->udev)) {
+ vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+ return;
+ }
+
+ spin_lock_irqsave(&s->queued_bufs_lock, flags);
+ list_add_tail(&buf->list, &s->queued_bufs);
+ spin_unlock_irqrestore(&s->queued_bufs_lock, flags);
+}
+
+static int airspy_start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ if (!s->udev)
+ return -ENODEV;
+
+ mutex_lock(&s->v4l2_lock);
+
+ set_bit(POWER_ON, &s->flags);
+
+ s->sequence = 0;
+
+ ret = airspy_alloc_stream_bufs(s);
+ if (ret)
+ goto err;
+
+ ret = airspy_alloc_urbs(s);
+ if (ret)
+ goto err;
+
+ ret = airspy_submit_urbs(s);
+ if (ret)
+ goto err;
+
+ /* start hardware streaming */
+ ret = airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 1, 0, NULL, 0);
+ if (ret)
+ goto err;
+err:
+ mutex_unlock(&s->v4l2_lock);
+
+ return ret;
+}
+
+static void airspy_stop_streaming(struct vb2_queue *vq)
+{
+ struct airspy *s = vb2_get_drv_priv(vq);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ mutex_lock(&s->v4l2_lock);
+
+ /* stop hardware streaming */
+ airspy_ctrl_msg(s, CMD_RECEIVER_MODE, 0, 0, NULL, 0);
+
+ airspy_kill_urbs(s);
+ airspy_free_urbs(s);
+ airspy_free_stream_bufs(s);
+
+ airspy_cleanup_queued_bufs(s);
+
+ clear_bit(POWER_ON, &s->flags);
+
+ mutex_unlock(&s->v4l2_lock);
+}
+
+static struct vb2_ops airspy_vb2_ops = {
+ .queue_setup = airspy_queue_setup,
+ .buf_queue = airspy_buf_queue,
+ .start_streaming = airspy_start_streaming,
+ .stop_streaming = airspy_stop_streaming,
+ .wait_prepare = vb2_ops_wait_prepare,
+ .wait_finish = vb2_ops_wait_finish,
+};
+
+static int airspy_querycap(struct file *file, void *fh,
+ struct v4l2_capability *cap)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s:\n", __func__);
+
+ strlcpy(cap->driver, KBUILD_MODNAME, sizeof(cap->driver));
+ strlcpy(cap->card, s->vdev.name, sizeof(cap->card));
+ usb_make_path(s->udev, cap->bus_info, sizeof(cap->bus_info));
+ cap->device_caps = V4L2_CAP_SDR_CAPTURE | V4L2_CAP_STREAMING |
+ V4L2_CAP_READWRITE | V4L2_CAP_TUNER;
+ cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+ return 0;
+}
+
+static int airspy_enum_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_fmtdesc *f)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
+
+ if (f->index >= NUM_FORMATS)
+ return -EINVAL;
+
+ strlcpy(f->description, formats[f->index].name, sizeof(f->description));
+ f->pixelformat = formats[f->index].pixelformat;
+
+ return 0;
+}
+
+static int airspy_g_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&s->pixelformat);
+
+ f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+
+ return 0;
+}
+
+static int airspy_s_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+ struct vb2_queue *q = &s->vb_queue;
+ int i;
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.sdr.pixelformat);
+
+ if (vb2_is_busy(q))
+ return -EBUSY;
+
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
+ return 0;
+ }
+ }
+
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
+
+ return 0;
+}
+
+static int airspy_try_fmt_sdr_cap(struct file *file, void *priv,
+ struct v4l2_format *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int i;
+
+ dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
+ (char *)&f->fmt.sdr.pixelformat);
+
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
+ for (i = 0; i < NUM_FORMATS; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
+ return 0;
+ }
+ }
+
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
+
+ return 0;
+}
+
+static int airspy_s_tuner(struct file *file, void *priv,
+ const struct v4l2_tuner *v)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+ if (v->index == 0)
+ ret = 0;
+ else if (v->index == 1)
+ ret = 0;
+ else
+ ret = -EINVAL;
+
+ return ret;
+}
+
+static int airspy_g_tuner(struct file *file, void *priv, struct v4l2_tuner *v)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+
+ dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, v->index);
+
+ if (v->index == 0) {
+ strlcpy(v->name, "AirSpy ADC", sizeof(v->name));
+ v->type = V4L2_TUNER_ADC;
+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ v->rangelow = bands[0].rangelow;
+ v->rangehigh = bands[0].rangehigh;
+ ret = 0;
+ } else if (v->index == 1) {
+ strlcpy(v->name, "AirSpy RF", sizeof(v->name));
+ v->type = V4L2_TUNER_RF;
+ v->capability = V4L2_TUNER_CAP_1HZ | V4L2_TUNER_CAP_FREQ_BANDS;
+ v->rangelow = bands_rf[0].rangelow;
+ v->rangehigh = bands_rf[0].rangehigh;
+ ret = 0;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_g_frequency(struct file *file, void *priv,
+ struct v4l2_frequency *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret = 0;
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d\n",
+ __func__, f->tuner, f->type);
+
+ if (f->tuner == 0) {
+ f->type = V4L2_TUNER_ADC;
+ f->frequency = s->f_adc;
+ ret = 0;
+ } else if (f->tuner == 1) {
+ f->type = V4L2_TUNER_RF;
+ f->frequency = s->f_rf;
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_s_frequency(struct file *file, void *priv,
+ const struct v4l2_frequency *f)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+ u8 buf[4];
+
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d frequency=%u\n",
+ __func__, f->tuner, f->type, f->frequency);
+
+ if (f->tuner == 0) {
+ s->f_adc = clamp_t(unsigned int, f->frequency,
+ bands[0].rangelow,
+ bands[0].rangehigh);
+ dev_dbg(&s->udev->dev, "%s: ADC frequency=%u Hz\n",
+ __func__, s->f_adc);
+ ret = 0;
+ } else if (f->tuner == 1) {
+ s->f_rf = clamp_t(unsigned int, f->frequency,
+ bands_rf[0].rangelow,
+ bands_rf[0].rangehigh);
+ dev_dbg(&s->udev->dev, "%s: RF frequency=%u Hz\n",
+ __func__, s->f_rf);
+ buf[0] = (s->f_rf >> 0) & 0xff;
+ buf[1] = (s->f_rf >> 8) & 0xff;
+ buf[2] = (s->f_rf >> 16) & 0xff;
+ buf[3] = (s->f_rf >> 24) & 0xff;
+ ret = airspy_ctrl_msg(s, CMD_SET_FREQ, 0, 0, buf, 4);
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static int airspy_enum_freq_bands(struct file *file, void *priv,
+ struct v4l2_frequency_band *band)
+{
+ struct airspy *s = video_drvdata(file);
+ int ret;
+ dev_dbg(&s->udev->dev, "%s: tuner=%d type=%d index=%d\n",
+ __func__, band->tuner, band->type, band->index);
+
+ if (band->tuner == 0) {
+ if (band->index >= ARRAY_SIZE(bands)) {
+ ret = -EINVAL;
+ } else {
+ *band = bands[band->index];
+ ret = 0;
+ }
+ } else if (band->tuner == 1) {
+ if (band->index >= ARRAY_SIZE(bands_rf)) {
+ ret = -EINVAL;
+ } else {
+ *band = bands_rf[band->index];
+ ret = 0;
+ }
+ } else {
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ioctl_ops airspy_ioctl_ops = {
+ .vidioc_querycap = airspy_querycap,
+
+ .vidioc_enum_fmt_sdr_cap = airspy_enum_fmt_sdr_cap,
+ .vidioc_g_fmt_sdr_cap = airspy_g_fmt_sdr_cap,
+ .vidioc_s_fmt_sdr_cap = airspy_s_fmt_sdr_cap,
+ .vidioc_try_fmt_sdr_cap = airspy_try_fmt_sdr_cap,
+
+ .vidioc_reqbufs = vb2_ioctl_reqbufs,
+ .vidioc_create_bufs = vb2_ioctl_create_bufs,
+ .vidioc_prepare_buf = vb2_ioctl_prepare_buf,
+ .vidioc_querybuf = vb2_ioctl_querybuf,
+ .vidioc_qbuf = vb2_ioctl_qbuf,
+ .vidioc_dqbuf = vb2_ioctl_dqbuf,
+
+ .vidioc_streamon = vb2_ioctl_streamon,
+ .vidioc_streamoff = vb2_ioctl_streamoff,
+
+ .vidioc_g_tuner = airspy_g_tuner,
+ .vidioc_s_tuner = airspy_s_tuner,
+
+ .vidioc_g_frequency = airspy_g_frequency,
+ .vidioc_s_frequency = airspy_s_frequency,
+ .vidioc_enum_freq_bands = airspy_enum_freq_bands,
+
+ .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+ .vidioc_log_status = v4l2_ctrl_log_status,
+};
+
+static const struct v4l2_file_operations airspy_fops = {
+ .owner = THIS_MODULE,
+ .open = v4l2_fh_open,
+ .release = vb2_fop_release,
+ .read = vb2_fop_read,
+ .poll = vb2_fop_poll,
+ .mmap = vb2_fop_mmap,
+ .unlocked_ioctl = video_ioctl2,
+};
+
+static struct video_device airspy_template = {
+ .name = "AirSpy SDR",
+ .release = video_device_release_empty,
+ .fops = &airspy_fops,
+ .ioctl_ops = &airspy_ioctl_ops,
+};
+
+static void airspy_video_release(struct v4l2_device *v)
+{
+ struct airspy *s = container_of(v, struct airspy, v4l2_dev);
+
+ v4l2_ctrl_handler_free(&s->hdl);
+ v4l2_device_unregister(&s->v4l2_dev);
+ kfree(s);
+}
+
+static int airspy_set_lna_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: lna auto=%d->%d val=%d->%d\n",
+ __func__, s->lna_gain_auto->cur.val,
+ s->lna_gain_auto->val, s->lna_gain->cur.val,
+ s->lna_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_AGC, 0, s->lna_gain_auto->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+
+ if (s->lna_gain_auto->val == false) {
+ ret = airspy_ctrl_msg(s, CMD_SET_LNA_GAIN, 0, s->lna_gain->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_set_mixer_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: mixer auto=%d->%d val=%d->%d\n",
+ __func__, s->mixer_gain_auto->cur.val,
+ s->mixer_gain_auto->val, s->mixer_gain->cur.val,
+ s->mixer_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_AGC, 0, s->mixer_gain_auto->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+
+ if (s->mixer_gain_auto->val == false) {
+ ret = airspy_ctrl_msg(s, CMD_SET_MIXER_GAIN, 0,
+ s->mixer_gain->val, &u8tmp, 1);
+ if (ret)
+ goto err;
+ }
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_set_if_gain(struct airspy *s)
+{
+ int ret;
+ u8 u8tmp;
+
+ dev_dbg(&s->udev->dev, "%s: val=%d->%d\n",
+ __func__, s->if_gain->cur.val, s->if_gain->val);
+
+ ret = airspy_ctrl_msg(s, CMD_SET_VGA_GAIN, 0, s->if_gain->val,
+ &u8tmp, 1);
+ if (ret)
+ goto err;
+err:
+ if (ret)
+ dev_dbg(&s->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+ return ret;
+}
+
+static int airspy_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct airspy *s = container_of(ctrl->handler, struct airspy, hdl);
+ int ret;
+
+ switch (ctrl->id) {
+ case V4L2_CID_RF_TUNER_LNA_GAIN_AUTO:
+ case V4L2_CID_RF_TUNER_LNA_GAIN:
+ ret = airspy_set_lna_gain(s);
+ break;
+ case V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO:
+ case V4L2_CID_RF_TUNER_MIXER_GAIN:
+ ret = airspy_set_mixer_gain(s);
+ break;
+ case V4L2_CID_RF_TUNER_IF_GAIN:
+ ret = airspy_set_if_gain(s);
+ break;
+ default:
+ dev_dbg(&s->udev->dev, "%s: unknown ctrl: id=%d name=%s\n",
+ __func__, ctrl->id, ctrl->name);
+ ret = -EINVAL;
+ }
+
+ return ret;
+}
+
+static const struct v4l2_ctrl_ops airspy_ctrl_ops = {
+ .s_ctrl = airspy_s_ctrl,
+};
+
+static int airspy_probe(struct usb_interface *intf,
+ const struct usb_device_id *id)
+{
+ struct usb_device *udev = interface_to_usbdev(intf);
+ struct airspy *s = NULL;
+ int ret;
+ u8 u8tmp, buf[BUF_SIZE];
+
+ s = kzalloc(sizeof(struct airspy), GFP_KERNEL);
+ if (s == NULL) {
+ dev_err(&udev->dev,
+ "Could not allocate memory for airspy state\n");
+ return -ENOMEM;
+ }
+
+ mutex_init(&s->v4l2_lock);
+ mutex_init(&s->vb_queue_lock);
+ spin_lock_init(&s->queued_bufs_lock);
+ INIT_LIST_HEAD(&s->queued_bufs);
+ s->udev = udev;
+ s->f_adc = bands[0].rangelow;
+ s->f_rf = bands_rf[0].rangelow;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+
+ /* Detect device */
+ ret = airspy_ctrl_msg(s, CMD_BOARD_ID_READ, 0, 0, &u8tmp, 1);
+ if (ret == 0)
+ ret = airspy_ctrl_msg(s, CMD_VERSION_STRING_READ, 0, 0,
+ buf, BUF_SIZE);
+ if (ret) {
+ dev_err(&s->udev->dev, "Could not detect board\n");
+ goto err_free_mem;
+ }
+
+ buf[BUF_SIZE - 1] = '\0';
+
+ dev_info(&s->udev->dev, "Board ID: %02x\n", u8tmp);
+ dev_info(&s->udev->dev, "Firmware version: %s\n", buf);
+
+ /* Init videobuf2 queue structure */
+ s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
+ s->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
+ s->vb_queue.drv_priv = s;
+ s->vb_queue.buf_struct_size = sizeof(struct airspy_frame_buf);
+ s->vb_queue.ops = &airspy_vb2_ops;
+ s->vb_queue.mem_ops = &vb2_vmalloc_memops;
+ s->vb_queue.timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
+ ret = vb2_queue_init(&s->vb_queue);
+ if (ret) {
+ dev_err(&s->udev->dev, "Could not initialize vb2 queue\n");
+ goto err_free_mem;
+ }
+
+ /* Init video_device structure */
+ s->vdev = airspy_template;
+ s->vdev.queue = &s->vb_queue;
+ s->vdev.queue->lock = &s->vb_queue_lock;
+ video_set_drvdata(&s->vdev, s);
+
+ /* Register the v4l2_device structure */
+ s->v4l2_dev.release = airspy_video_release;
+ ret = v4l2_device_register(&intf->dev, &s->v4l2_dev);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Failed to register v4l2-device (%d)\n", ret);
+ goto err_free_mem;
+ }
+
+ /* Register controls */
+ v4l2_ctrl_handler_init(&s->hdl, 5);
+ s->lna_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_LNA_GAIN_AUTO, 0, 1, 1, 0);
+ s->lna_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_LNA_GAIN, 0, 14, 1, 8);
+ v4l2_ctrl_auto_cluster(2, &s->lna_gain_auto, 0, false);
+ s->mixer_gain_auto = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_MIXER_GAIN_AUTO, 0, 1, 1, 0);
+ s->mixer_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_MIXER_GAIN, 0, 15, 1, 8);
+ v4l2_ctrl_auto_cluster(2, &s->mixer_gain_auto, 0, false);
+ s->if_gain = v4l2_ctrl_new_std(&s->hdl, &airspy_ctrl_ops,
+ V4L2_CID_RF_TUNER_IF_GAIN, 0, 15, 1, 0);
+ if (s->hdl.error) {
+ ret = s->hdl.error;
+ dev_err(&s->udev->dev, "Could not initialize controls\n");
+ goto err_free_controls;
+ }
+
+ v4l2_ctrl_handler_setup(&s->hdl);
+
+ s->v4l2_dev.ctrl_handler = &s->hdl;
+ s->vdev.v4l2_dev = &s->v4l2_dev;
+ s->vdev.lock = &s->v4l2_lock;
+
+ ret = video_register_device(&s->vdev, VFL_TYPE_SDR, -1);
+ if (ret) {
+ dev_err(&s->udev->dev,
+ "Failed to register as video device (%d)\n",
+ ret);
+ goto err_unregister_v4l2_dev;
+ }
+ dev_info(&s->udev->dev, "Registered as %s\n",
+ video_device_node_name(&s->vdev));
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
+ return 0;
+
+err_free_controls:
+ v4l2_ctrl_handler_free(&s->hdl);
+err_unregister_v4l2_dev:
+ v4l2_device_unregister(&s->v4l2_dev);
+err_free_mem:
+ kfree(s);
+ return ret;
+}
+
+/* USB device ID list */
+static struct usb_device_id airspy_id_table[] = {
+ { USB_DEVICE(0x1d50, 0x60a1) }, /* AirSpy */
+ { }
+};
+MODULE_DEVICE_TABLE(usb, airspy_id_table);
+
+/* USB subsystem interface */
+static struct usb_driver airspy_driver = {
+ .name = KBUILD_MODNAME,
+ .probe = airspy_probe,
+ .disconnect = airspy_disconnect,
+ .id_table = airspy_id_table,
+};
+
+module_usb_driver(airspy_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("AirSpy SDR");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/au0828/Kconfig b/drivers/media/usb/au0828/Kconfig
index 953a37c613b1..fe48403eadd0 100644
--- a/drivers/media/usb/au0828/Kconfig
+++ b/drivers/media/usb/au0828/Kconfig
@@ -20,6 +20,7 @@ config VIDEO_AU0828_V4L2
bool "Auvitek AU0828 v4l2 analog video support"
depends on VIDEO_AU0828 && VIDEO_V4L2
select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
+ select VIDEO_TUNER
default y
---help---
This is a video4linux driver for Auvitek's USB device.
diff --git a/drivers/media/usb/au0828/au0828-video.c b/drivers/media/usb/au0828/au0828-video.c
index 9038194513c5..98f7ea1d6d63 100644
--- a/drivers/media/usb/au0828/au0828-video.c
+++ b/drivers/media/usb/au0828/au0828-video.c
@@ -787,23 +787,40 @@ static int au0828_i2s_init(struct au0828_dev *dev)
/*
* Auvitek au0828 analog stream enable
- * Please set interface0 to AS5 before enable the stream
*/
static int au0828_analog_stream_enable(struct au0828_dev *d)
{
+ struct usb_interface *iface;
+ int ret, h, w;
+
dprintk(1, "au0828_analog_stream_enable called\n");
+
+ iface = usb_ifnum_to_if(d->usbdev, 0);
+ if (iface && iface->cur_altsetting->desc.bAlternateSetting != 5) {
+ dprintk(1, "Changing intf#0 to alt 5\n");
+ /* set au0828 interface0 to AS5 here again */
+ ret = usb_set_interface(d->usbdev, 0, 5);
+ if (ret < 0) {
+ printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
+ return -EBUSY;
+ }
+ }
+
+ h = d->height / 2 + 2;
+ w = d->width * 2;
+
au0828_writereg(d, AU0828_SENSORCTRL_VBI_103, 0x00);
au0828_writereg(d, 0x106, 0x00);
/* set x position */
au0828_writereg(d, 0x110, 0x00);
au0828_writereg(d, 0x111, 0x00);
- au0828_writereg(d, 0x114, 0xa0);
- au0828_writereg(d, 0x115, 0x05);
+ au0828_writereg(d, 0x114, w & 0xff);
+ au0828_writereg(d, 0x115, w >> 8);
/* set y position */
au0828_writereg(d, 0x112, 0x00);
au0828_writereg(d, 0x113, 0x00);
- au0828_writereg(d, 0x116, 0xf2);
- au0828_writereg(d, 0x117, 0x00);
+ au0828_writereg(d, 0x116, h & 0xff);
+ au0828_writereg(d, 0x117, h >> 8);
au0828_writereg(d, AU0828_SENSORCTRL_100, 0xb3);
return 0;
@@ -1002,15 +1019,6 @@ static int au0828_v4l2_open(struct file *filp)
return -ERESTARTSYS;
}
if (dev->users == 0) {
- /* set au0828 interface0 to AS5 here again */
- ret = usb_set_interface(dev->usbdev, 0, 5);
- if (ret < 0) {
- mutex_unlock(&dev->lock);
- printk(KERN_INFO "Au0828 can't set alternate to 5!\n");
- kfree(fh);
- return -EBUSY;
- }
-
au0828_analog_stream_enable(dev);
au0828_analog_stream_reset(dev);
@@ -1252,13 +1260,6 @@ static int au0828_set_format(struct au0828_dev *dev, unsigned int cmd,
}
}
- /* set au0828 interface0 to AS5 here again */
- ret = usb_set_interface(dev->usbdev, 0, 5);
- if (ret < 0) {
- printk(KERN_INFO "Au0828 can't set alt setting to 5!\n");
- return -EBUSY;
- }
-
au0828_analog_stream_enable(dev);
return 0;
@@ -1364,9 +1365,11 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id norm)
i2c_gate_ctrl(dev, 1);
- /* FIXME: when we support something other than NTSC, we are going to
- have to make the au0828 bridge adjust the size of its capture
- buffer, which is currently hardcoded at 720x480 */
+ /*
+ * FIXME: when we support something other than 60Hz standards,
+ * we are going to have to make the au0828 bridge adjust the size
+ * of its capture buffer, which is currently hardcoded at 720x480
+ */
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_std, norm);
@@ -1723,6 +1726,7 @@ static int vidioc_streamoff(struct file *file, void *priv,
dev->vid_timeout_running = 0;
del_timer_sync(&dev->vid_timeout);
+ au0828_analog_stream_disable(dev);
v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
rc = au0828_stream_interrupt(dev);
if (rc != 0)
@@ -1915,7 +1919,7 @@ static const struct video_device au0828_video_template = {
.fops = &au0828_v4l_fops,
.release = video_device_release,
.ioctl_ops = &video_ioctl_ops,
- .tvnorms = V4L2_STD_NTSC_M,
+ .tvnorms = V4L2_STD_NTSC_M | V4L2_STD_PAL_M,
};
/**************************************************************************/
@@ -1928,7 +1932,8 @@ int au0828_analog_register(struct au0828_dev *dev,
struct usb_endpoint_descriptor *endpoint;
int i, ret;
- dprintk(1, "au0828_analog_register called!\n");
+ dprintk(1, "au0828_analog_register called for intf#%d!\n",
+ interface->cur_altsetting->desc.bInterfaceNumber);
/* set au0828 usb interface0 to as5 */
retval = usb_set_interface(dev->usbdev,
@@ -1952,6 +1957,9 @@ int au0828_analog_register(struct au0828_dev *dev,
dev->max_pkt_size = (tmp & 0x07ff) *
(((tmp & 0x1800) >> 11) + 1);
dev->isoc_in_endpointaddr = endpoint->bEndpointAddress;
+ dprintk(1,
+ "Found isoc endpoint 0x%02x, max size = %d\n",
+ dev->isoc_in_endpointaddr, dev->max_pkt_size);
}
}
if (!(dev->isoc_in_endpointaddr)) {
@@ -2008,14 +2016,12 @@ int au0828_analog_register(struct au0828_dev *dev,
*dev->vdev = au0828_video_template;
dev->vdev->v4l2_dev = &dev->v4l2_dev;
dev->vdev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev->flags);
strcpy(dev->vdev->name, "au0828a video");
/* Setup the VBI device */
*dev->vbi_dev = au0828_video_template;
dev->vbi_dev->v4l2_dev = &dev->v4l2_dev;
dev->vbi_dev->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vbi_dev->flags);
strcpy(dev->vbi_dev->name, "au0828a vbi");
/* Register the v4l2 device */
diff --git a/drivers/media/usb/cpia2/cpia2_v4l.c b/drivers/media/usb/cpia2/cpia2_v4l.c
index d5d42b6e94be..9caea8344547 100644
--- a/drivers/media/usb/cpia2/cpia2_v4l.c
+++ b/drivers/media/usb/cpia2/cpia2_v4l.c
@@ -1169,7 +1169,6 @@ int cpia2_register_camera(struct camera_data *cam)
cam->vdev.lock = &cam->v4l2_lock;
cam->vdev.ctrl_handler = hdl;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
reset_camera_struct_v4l(cam);
diff --git a/drivers/media/usb/cx231xx/cx231xx-417.c b/drivers/media/usb/cx231xx/cx231xx-417.c
index 30a0c69fb42f..459bb0e98971 100644
--- a/drivers/media/usb/cx231xx/cx231xx-417.c
+++ b/drivers/media/usb/cx231xx/cx231xx-417.c
@@ -1563,7 +1563,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.width = dev->ts1.width;
f->fmt.pix.height = dev->ts1.height;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
dprintk(1, "VIDIOC_G_FMT: w: %d, h: %d\n",
dev->ts1.width, dev->ts1.height);
dprintk(3, "exit vidioc_g_fmt_vid_cap()\n");
@@ -1582,7 +1581,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage = mpeglines * mpeglinesize;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
- f->fmt.pix.priv = 0;
dprintk(1, "VIDIOC_TRY_FMT: w: %d, h: %d\n",
dev->ts1.width, dev->ts1.height);
dprintk(3, "exit vidioc_try_fmt_vid_cap()\n");
@@ -1923,7 +1921,6 @@ static struct video_device *cx231xx_video_dev_alloc(
vfd->v4l2_dev = &dev->v4l2_dev;
vfd->lock = &dev->lock;
vfd->release = video_device_release;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
vfd->ctrl_handler = &dev->mpeg_ctrl_handler.hdl;
video_set_drvdata(vfd, dev);
if (dev->tuner_type == TUNER_ABSENT) {
diff --git a/drivers/media/usb/cx231xx/cx231xx-video.c b/drivers/media/usb/cx231xx/cx231xx-video.c
index 1f8751379e24..3b3ada6562ca 100644
--- a/drivers/media/usb/cx231xx/cx231xx-video.c
+++ b/drivers/media/usb/cx231xx/cx231xx-video.c
@@ -208,7 +208,7 @@ static inline void get_next_buf(struct cx231xx_dmaqueue *dma_q,
static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
- int i, rc = 1;
+ int i;
unsigned char *p_buffer;
u32 bytes_parsed = 0, buffer_size = 0;
u8 sav_eav = 0;
@@ -299,13 +299,12 @@ static inline int cx231xx_isoc_copy(struct cx231xx *dev, struct urb *urb)
bytes_parsed = 0;
}
- return rc;
+ return 1;
}
static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
{
struct cx231xx_dmaqueue *dma_q = urb->context;
- int rc = 1;
unsigned char *p_buffer;
u32 bytes_parsed = 0, buffer_size = 0;
u8 sav_eav = 0;
@@ -379,7 +378,7 @@ static inline int cx231xx_bulk_copy(struct cx231xx *dev, struct urb *urb)
bytes_parsed = 0;
}
- return rc;
+ return 1;
}
@@ -886,7 +885,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -931,7 +929,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.sizeimage = f->fmt.pix.bytesperline * height;
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -1620,7 +1617,7 @@ static int radio_s_tuner(struct file *file, void *priv, const struct v4l2_tuner
*/
static int cx231xx_v4l2_open(struct file *filp)
{
- int errCode = 0, radio = 0;
+ int radio = 0;
struct video_device *vdev = video_devdata(filp);
struct cx231xx *dev = video_drvdata(filp);
struct cx231xx_fh *fh;
@@ -1718,7 +1715,7 @@ static int cx231xx_v4l2_open(struct file *filp)
mutex_unlock(&dev->lock);
v4l2_fh_add(&fh->fh);
- return errCode;
+ return 0;
}
/*
@@ -2066,7 +2063,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
vfd->release = video_device_release;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/dvb-usb-v2/Kconfig b/drivers/media/usb/dvb-usb-v2/Kconfig
index 037e519bbaa2..66645b02c854 100644
--- a/drivers/media/usb/dvb-usb-v2/Kconfig
+++ b/drivers/media/usb/dvb-usb-v2/Kconfig
@@ -129,6 +129,7 @@ config DVB_USB_RTL28XXU
depends on DVB_USB_V2 && I2C_MUX
select DVB_RTL2830
select DVB_RTL2832
+ select DVB_RTL2832_SDR if (MEDIA_SUBDRV_AUTOSELECT && MEDIA_SDR_SUPPORT)
select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
diff --git a/drivers/media/usb/dvb-usb-v2/lmedm04.c b/drivers/media/usb/dvb-usb-v2/lmedm04.c
index f674dc024d06..7d685bc8c2c0 100644
--- a/drivers/media/usb/dvb-usb-v2/lmedm04.c
+++ b/drivers/media/usb/dvb-usb-v2/lmedm04.c
@@ -125,14 +125,13 @@ DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
#define TUNER_RS2000 0x4
struct lme2510_state {
+ unsigned long int_urb_due;
u8 id;
u8 tuner_config;
u8 signal_lock;
u8 signal_level;
u8 signal_sn;
u8 time_key;
- u8 last_key;
- u8 key_timeout;
u8 i2c_talk_onoff;
u8 i2c_gate;
u8 i2c_tuner_gate_w;
@@ -323,7 +322,7 @@ static void lme2510_int_response(struct urb *lme_urb)
}
break;
case TUNER_RS2000:
- if (ibuf[1] == 0x3 && ibuf[6] == 0xff)
+ if (ibuf[2] & 0x1)
st->signal_lock = 0xff;
else
st->signal_lock = 0x00;
@@ -343,7 +342,12 @@ static void lme2510_int_response(struct urb *lme_urb)
break;
}
}
+
usb_submit_urb(lme_urb, GFP_ATOMIC);
+
+ /* interrupt urb is due every 48 msecs while streaming
+ * add 12msecs for system lag */
+ st->int_urb_due = jiffies + msecs_to_jiffies(60);
}
static int lme2510_int_read(struct dvb_usb_adapter *adap)
@@ -584,14 +588,13 @@ static int lme2510_msg(struct dvb_usb_device *d,
switch (wbuf[3]) {
case 0x8c:
rbuf[0] = 0x55;
- rbuf[1] = 0xff;
- if (st->last_key == st->time_key) {
- st->key_timeout++;
- if (st->key_timeout > 5)
- rbuf[1] = 0;
- } else
- st->key_timeout = 0;
- st->last_key = st->time_key;
+ rbuf[1] = st->signal_lock;
+
+ /* If int_urb_due overdue
+ * set rbuf[1] to 0 to clear lock */
+ if (time_after(jiffies, st->int_urb_due))
+ rbuf[1] = 0;
+
break;
default:
lme2510_usb_talk(d, wbuf, wlen, rbuf, rlen);
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
index c7304fa8ab73..b8a707e57b99 100644
--- a/drivers/media/usb/dvb-usb-v2/mxl111sf.c
+++ b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
@@ -129,7 +129,7 @@ int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
u8 addr, u8 mask, u8 data)
{
int ret;
- u8 val;
+ u8 val = 0;
if (mask != 0xff) {
ret = mxl111sf_read_reg(state, addr, &val);
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
index c5d95662e2e1..10aef2188fbe 100644
--- a/drivers/media/usb/dvb-usb/Kconfig
+++ b/drivers/media/usb/dvb-usb/Kconfig
@@ -117,10 +117,12 @@ config DVB_USB_CXUSB
select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT
select DVB_LGS8GXX if MEDIA_SUBDRV_AUTOSELECT
+ select DVB_SI2168 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
select MEDIA_TUNER_MAX2165 if MEDIA_SUBDRV_AUTOSELECT
+ select MEDIA_TUNER_SI2157 if MEDIA_SUBDRV_AUTOSELECT
help
Say Y here to support the Conexant USB2.0 hybrid reference design.
Currently, only DVB and ATSC modes are supported, analog mode
@@ -128,6 +130,7 @@ config DVB_USB_CXUSB
Medion MD95700 hybrid USB2.0 device.
DViCO FusionHDTV (Bluebird) USB2.0 devices
+ TechnoTrend TVStick CT2-4400
config DVB_USB_M920X
tristate "Uli m920x DVB-T USB2.0 support"
diff --git a/drivers/media/usb/dvb-usb/cxusb.c b/drivers/media/usb/dvb-usb/cxusb.c
index a1c641e18362..b7461ac1ce74 100644
--- a/drivers/media/usb/dvb-usb/cxusb.c
+++ b/drivers/media/usb/dvb-usb/cxusb.c
@@ -42,6 +42,8 @@
#include "dib0070.h"
#include "lgs8gxx.h"
#include "atbm8830.h"
+#include "si2168.h"
+#include "si2157.h"
/* Max transfer size done by I2C transfer functions */
#define MAX_XFER_SIZE 64
@@ -144,6 +146,22 @@ static int cxusb_d680_dmb_gpio_tuner(struct dvb_usb_device *d,
}
}
+static int cxusb_tt_ct2_4400_gpio_tuner(struct dvb_usb_device *d, int onoff)
+{
+ u8 o[2], i;
+ int rc;
+
+ o[0] = 0x83;
+ o[1] = onoff;
+ rc = cxusb_ctrl_msg(d, CMD_GPIO_WRITE, o, 2, &i, 1);
+
+ if (rc) {
+ deb_info("gpio_write failed.\n");
+ return -EIO;
+ }
+ return 0;
+}
+
/* I2C */
static int cxusb_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
int num)
@@ -505,6 +523,30 @@ static int cxusb_d680_dmb_rc_query(struct dvb_usb_device *d, u32 *event,
return 0;
}
+static int cxusb_tt_ct2_4400_rc_query(struct dvb_usb_device *d)
+{
+ u8 i[2];
+ int ret;
+ u32 cmd, keycode;
+ u8 rc5_cmd, rc5_addr, rc5_toggle;
+
+ ret = cxusb_ctrl_msg(d, 0x10, NULL, 0, i, 2);
+ if (ret)
+ return ret;
+
+ cmd = (i[0] << 8) | i[1];
+
+ if (cmd != 0xffff) {
+ rc5_cmd = cmd & 0x3F; /* bits 1-6 for command */
+ rc5_addr = (cmd & 0x07C0) >> 6; /* bits 7-11 for address */
+ rc5_toggle = (cmd & 0x0800) >> 11; /* bit 12 for toggle */
+ keycode = (rc5_addr << 8) | rc5_cmd;
+ rc_keydown(d->rc_dev, keycode, rc5_toggle);
+ }
+
+ return 0;
+}
+
static struct rc_map_table rc_map_dvico_mce_table[] = {
{ 0xfe02, KEY_TV },
{ 0xfe0e, KEY_MP3 },
@@ -1070,8 +1112,15 @@ static struct dib7000p_config cxusb_dualdig4_rev2_config = {
.hostbus_diversity = 1,
};
+struct dib0700_adapter_state {
+ int (*set_param_save)(struct dvb_frontend *);
+ struct dib7000p_ops dib7000p_ops;
+};
+
static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
if (usb_set_interface(adap->dev->udev, 0, 1) < 0)
err("set interface failed");
@@ -1079,14 +1128,17 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
cxusb_bluebird_gpio_pulse(adap->dev, 0x02, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
- &cxusb_dualdig4_rev2_config) < 0) {
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ &cxusb_dualdig4_rev2_config) < 0) {
printk(KERN_WARNING "Unable to enumerate dib7000p\n");
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
- &cxusb_dualdig4_rev2_config);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
+ &cxusb_dualdig4_rev2_config);
if (adap->fe_adap[0].fe == NULL)
return -EIO;
@@ -1095,7 +1147,10 @@ static int cxusb_dualdig4_rev2_frontend_attach(struct dvb_usb_adapter *adap)
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
{
- return dib7000p_set_gpio(fe, 8, 0, !onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
}
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
@@ -1110,10 +1165,6 @@ static struct dib0070_config dib7070p_dib0070_config = {
.clock_khz = 12000,
};
-struct dib0700_adapter_state {
- int (*set_param_save) (struct dvb_frontend *);
-};
-
static int dib7070_set_param_override(struct dvb_frontend *fe)
{
struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -1128,7 +1179,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
case BAND_UHF: offset = 550; break;
}
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
@@ -1136,8 +1187,14 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
static int cxusb_dualdig4_rev2_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c =
- dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ struct i2c_adapter *tun_i2c;
+
+ /*
+ * No need to call dvb7000p_attach here, as it was called
+ * already, as frontend_attach method is called first, and
+ * tuner_attach is only called on sucess.
+ */
+ tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
@@ -1286,6 +1343,74 @@ static int cxusb_mygica_d689_frontend_attach(struct dvb_usb_adapter *adap)
return 0;
}
+static int cxusb_tt_ct2_4400_attach(struct dvb_usb_adapter *adap)
+{
+ struct dvb_usb_device *d = adap->dev;
+ struct cxusb_state *st = d->priv;
+ struct i2c_adapter *adapter;
+ struct i2c_client *client_demod;
+ struct i2c_client *client_tuner;
+ struct i2c_board_info info;
+ struct si2168_config si2168_config;
+ struct si2157_config si2157_config;
+
+ /* reset the tuner */
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 0) < 0) {
+ err("clear tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+ if (cxusb_tt_ct2_4400_gpio_tuner(d, 1) < 0) {
+ err("set tuner gpio failed");
+ return -EIO;
+ }
+ msleep(100);
+
+ /* attach frontend */
+ si2168_config.i2c_adapter = &adapter;
+ si2168_config.fe = &adap->fe_adap[0].fe;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2168", I2C_NAME_SIZE);
+ info.addr = 0x64;
+ info.platform_data = &si2168_config;
+ request_module(info.type);
+ client_demod = i2c_new_device(&d->i2c_adap, &info);
+ if (client_demod == NULL || client_demod->dev.driver == NULL)
+ return -ENODEV;
+
+ if (!try_module_get(client_demod->dev.driver->owner)) {
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_demod = client_demod;
+
+ /* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
+ si2157_config.fe = adap->fe_adap[0].fe;
+ memset(&info, 0, sizeof(struct i2c_board_info));
+ strlcpy(info.type, "si2157", I2C_NAME_SIZE);
+ info.addr = 0x60;
+ info.platform_data = &si2157_config;
+ request_module(info.type);
+ client_tuner = i2c_new_device(adapter, &info);
+ if (client_tuner == NULL || client_tuner->dev.driver == NULL) {
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+ if (!try_module_get(client_tuner->dev.driver->owner)) {
+ i2c_unregister_device(client_tuner);
+ module_put(client_demod->dev.driver->owner);
+ i2c_unregister_device(client_demod);
+ return -ENODEV;
+ }
+
+ st->i2c_client_tuner = client_tuner;
+
+ return 0;
+}
+
/*
* DViCO has shipped two devices with the same USB ID, but only one of them
* needs a firmware download. Check the device class details to see if they
@@ -1367,6 +1492,7 @@ static struct dvb_usb_device_properties cxusb_bluebird_nano2_needsfirmware_prope
static struct dvb_usb_device_properties cxusb_aver_a868r_properties;
static struct dvb_usb_device_properties cxusb_d680_dmb_properties;
static struct dvb_usb_device_properties cxusb_mygica_d689_properties;
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties;
static int cxusb_probe(struct usb_interface *intf,
const struct usb_device_id *id)
@@ -1397,12 +1523,37 @@ static int cxusb_probe(struct usb_interface *intf,
THIS_MODULE, NULL, adapter_nr) ||
0 == dvb_usb_device_init(intf, &cxusb_mygica_d689_properties,
THIS_MODULE, NULL, adapter_nr) ||
+ 0 == dvb_usb_device_init(intf, &cxusb_tt_ct2_4400_properties,
+ THIS_MODULE, NULL, adapter_nr) ||
0)
return 0;
return -EINVAL;
}
+static void cxusb_disconnect(struct usb_interface *intf)
+{
+ struct dvb_usb_device *d = usb_get_intfdata(intf);
+ struct cxusb_state *st = d->priv;
+ struct i2c_client *client;
+
+ /* remove I2C client for tuner */
+ client = st->i2c_client_tuner;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ /* remove I2C client for demodulator */
+ client = st->i2c_client_demod;
+ if (client) {
+ module_put(client->dev.driver->owner);
+ i2c_unregister_device(client);
+ }
+
+ dvb_usb_device_exit(intf);
+}
+
static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_MEDION, USB_PID_MEDION_MD95700) },
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_LG064F_COLD) },
@@ -1424,6 +1575,7 @@ static struct usb_device_id cxusb_table [] = {
{ USB_DEVICE(USB_VID_DVICO, USB_PID_DVICO_BLUEBIRD_DUAL_4_REV_2) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_CONEXANT_D680_DMB) },
{ USB_DEVICE(USB_VID_CONEXANT, USB_PID_MYGICA_D689) },
+ { USB_DEVICE(USB_VID_TECHNOTREND, USB_PID_TECHNOTREND_TVSTICK_CT2_4400) },
{} /* Terminating entry */
};
MODULE_DEVICE_TABLE (usb, cxusb_table);
@@ -2070,10 +2222,63 @@ static struct dvb_usb_device_properties cxusb_mygica_d689_properties = {
}
};
+static struct dvb_usb_device_properties cxusb_tt_ct2_4400_properties = {
+ .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+
+ .usb_ctrl = CYPRESS_FX2,
+
+ .size_of_priv = sizeof(struct cxusb_state),
+
+ .num_adapters = 1,
+ .adapter = {
+ {
+ .num_frontends = 1,
+ .fe = {{
+ .streaming_ctrl = cxusb_streaming_ctrl,
+ /* both frontend and tuner attached in the
+ same function */
+ .frontend_attach = cxusb_tt_ct2_4400_attach,
+
+ /* parameter for the MPEG2-data transfer */
+ .stream = {
+ .type = USB_BULK,
+ .count = 8,
+ .endpoint = 0x82,
+ .u = {
+ .bulk = {
+ .buffersize = 4096,
+ }
+ }
+ },
+ } },
+ },
+ },
+
+ .i2c_algo = &cxusb_i2c_algo,
+ .generic_bulk_ctrl_endpoint = 0x01,
+ .generic_bulk_ctrl_endpoint_response = 0x81,
+
+ .rc.core = {
+ .rc_codes = RC_MAP_TT_1500,
+ .allowed_protos = RC_BIT_RC5,
+ .rc_query = cxusb_tt_ct2_4400_rc_query,
+ .rc_interval = 150,
+ },
+
+ .num_device_descs = 1,
+ .devices = {
+ {
+ "TechnoTrend TVStick CT2-4400",
+ { NULL },
+ { &cxusb_table[20], NULL },
+ },
+ }
+};
+
static struct usb_driver cxusb_driver = {
.name = "dvb_usb_cxusb",
.probe = cxusb_probe,
- .disconnect = dvb_usb_device_exit,
+ .disconnect = cxusb_disconnect,
.id_table = cxusb_table,
};
diff --git a/drivers/media/usb/dvb-usb/cxusb.h b/drivers/media/usb/dvb-usb/cxusb.h
index 1a51eafd31b9..527ff7905e15 100644
--- a/drivers/media/usb/dvb-usb/cxusb.h
+++ b/drivers/media/usb/dvb-usb/cxusb.h
@@ -30,6 +30,8 @@
struct cxusb_state {
u8 gpio_write_state[3];
+ struct i2c_client *i2c_client_demod;
+ struct i2c_client *i2c_client_tuner;
};
#endif
diff --git a/drivers/media/usb/dvb-usb/dib0700_devices.c b/drivers/media/usb/dvb-usb/dib0700_devices.c
index 10e0db8d1850..501947eaacfe 100644
--- a/drivers/media/usb/dvb-usb/dib0700_devices.c
+++ b/drivers/media/usb/dvb-usb/dib0700_devices.c
@@ -32,6 +32,8 @@ MODULE_PARM_DESC(force_lna_activation, "force the activation of Low-Noise-Amplif
struct dib0700_adapter_state {
int (*set_param_save) (struct dvb_frontend *);
const struct firmware *frontend_firmware;
+ struct dib7000p_ops dib7000p_ops;
+ struct dib8000_ops dib8000_ops;
};
/* Hauppauge Nova-T 500 (aka Bristol)
@@ -262,6 +264,11 @@ static struct mt2266_config stk7700d_mt2266_config[2] = {
static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (adap->id == 0) {
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
@@ -272,16 +279,16 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe =
- dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80 + (adap->id << 1),
&stk7700d_dib7000p_mt2266_config[adap->id]);
@@ -290,6 +297,11 @@ static int stk7700P2_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (adap->id == 0) {
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
@@ -301,16 +313,16 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7700d_dib7000p_mt2266_config)
!= 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe =
- dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80 + (adap->id << 1),
&stk7700d_dib7000p_mt2266_config[adap->id]);
@@ -320,7 +332,10 @@ static int stk7700d_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700d_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct dib0700_adapter_state *state = adap->priv;
+
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
+ DIBX000_I2C_INTERFACE_TUNER, 1);
return dvb_attach(mt2266_attach, adap->fe_adap[0].fe, tun_i2c,
&stk7700d_mt2266_config[adap->id]) == NULL ? -ENODEV : 0;
}
@@ -397,12 +412,14 @@ static int stk7700ph_xc3028_callback(void *ptr, int component,
int command, int arg)
{
struct dvb_usb_adapter *adap = ptr;
+ struct dib0700_adapter_state *state = adap->priv;
switch (command) {
case XC2028_TUNER_RESET:
/* Send the tuner in then out of reset */
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0); msleep(10);
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+ msleep(10);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
break;
case XC2028_RESET_CLK:
break;
@@ -428,12 +445,16 @@ static struct xc2028_config stk7700ph_xc3028_config = {
static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *desc = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
if (desc->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
desc->idProduct == cpu_to_le16(USB_PID_PINNACLE_EXPRESSCARD_320CX))
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
else
- dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
+ dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(20);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
dib0700_set_gpio(adap->dev, GPIO4, GPIO_OUT, 1);
@@ -445,14 +466,15 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
msleep(10);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&stk7700ph_dib7700_xc3028_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&stk7700ph_dib7700_xc3028_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -461,8 +483,9 @@ static int stk7700ph_frontend_attach(struct dvb_usb_adapter *adap)
static int stk7700ph_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
stk7700ph_xc3028_config.i2c_adap = tun_i2c;
@@ -673,6 +696,11 @@ static struct dib7000p_config stk7700p_dib7000p_config = {
static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
/* unless there is no real power management in DVB - we leave the device on GPIO6 */
dib0700_set_gpio(adap->dev, GPIO10, GPIO_OUT, 0);
@@ -689,11 +717,14 @@ static int stk7700p_frontend_attach(struct dvb_usb_adapter *adap)
st->mt2060_if1[0] = 1220;
- if (dib7000pc_detection(&adap->dev->i2c_adap)) {
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
+ if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap)) {
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 18, &stk7700p_dib7000p_config);
st->is_dib7000pc = 1;
- } else
+ } else {
+ dvb_detach(&state->dib7000p_ops);
+ memset(&state->dib7000p_ops, 0, sizeof(state->dib7000p_ops));
adap->fe_adap[0].fe = dvb_attach(dib7000m_attach, &adap->dev->i2c_adap, 18, &stk7700p_dib7000m_config);
+ }
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -707,14 +738,16 @@ static int stk7700p_tuner_attach(struct dvb_usb_adapter *adap)
struct i2c_adapter *prim_i2c = &adap->dev->i2c_adap;
struct dib0700_state *st = adap->dev->priv;
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
s8 a;
int if1=1220;
+
if (adap->dev->udev->descriptor.idVendor == cpu_to_le16(USB_VID_HAUPPAUGE) &&
adap->dev->udev->descriptor.idProduct == cpu_to_le16(USB_PID_HAUPPAUGE_NOVA_T_STICK)) {
if (!eeprom_read(prim_i2c,0x58,&a)) if1=1220+a;
}
if (st->is_dib7000pc)
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
else
tun_i2c = dib7000m_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
@@ -767,14 +800,20 @@ static struct dibx000_agc_config dib7070_agc_config = {
static int dib7070_tuner_reset(struct dvb_frontend *fe, int onoff)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("reset: %d", onoff);
- return dib7000p_set_gpio(fe, 8, 0, !onoff);
+ return state->dib7000p_ops.set_gpio(fe, 8, 0, !onoff);
}
static int dib7070_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("sleep: %d", onoff);
- return dib7000p_set_gpio(fe, 9, 0, onoff);
+ return state->dib7000p_ops.set_gpio(fe, 9, 0, onoff);
}
static struct dib0070_config dib7070p_dib0070_config[2] = {
@@ -818,7 +857,7 @@ static int dib7070_set_param_override(struct dvb_frontend *fe)
default: offset = 550; break;
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
@@ -832,39 +871,39 @@ static int dib7770_set_param_override(struct dvb_frontend *fe)
u8 band = BAND_OF_FREQUENCY(p->frequency/1000);
switch (band) {
case BAND_VHF:
- dib7000p_set_gpio(fe, 0, 0, 1);
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 1);
offset = 850;
break;
case BAND_UHF:
default:
- dib7000p_set_gpio(fe, 0, 0, 0);
+ state->dib7000p_ops.set_gpio(fe, 0, 0, 0);
offset = 250;
break;
}
deb_info("WBD for DiB7000P: %d\n", offset + dib0070_wbd_offset(fe));
- dib7000p_set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
+ state->dib7000p_ops.set_wbd_ref(fe, offset + dib0070_wbd_offset(fe));
return state->set_param_save(fe);
}
static int dib7770p_tuner_attach(struct dvb_usb_adapter *adap)
{
- struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ struct dib0700_adapter_state *st = adap->priv;
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
- if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
- &dib7770p_dib0070_config) == NULL)
- return -ENODEV;
+ if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c,
+ &dib7770p_dib0070_config) == NULL)
+ return -ENODEV;
- st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
- adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
- return 0;
+ st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
+ adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7770_set_param_override;
+ return 0;
}
static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
if (dvb_attach(dib0070_attach, adap->fe_adap[0].fe, tun_i2c, &dib7070p_dib0070_config[0]) == NULL)
@@ -882,28 +921,33 @@ static int dib7070p_tuner_attach(struct dvb_usb_adapter *adap)
static int stk7700p_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
+ struct dib0700_adapter_state *state = adapter->priv;
struct dib0700_state *st = adapter->dev->priv;
+
if (st->is_dib7000pc)
- return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
return dib7000m_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk7700p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
struct dib0700_state *st = adapter->dev->priv;
+ struct dib0700_adapter_state *state = adapter->priv;
if (st->is_dib7000pc)
- return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
return dib7000m_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static int stk70x0p_pid_filter(struct dvb_usb_adapter *adapter, int index, u16 pid, int onoff)
{
- return dib7000p_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+ return state->dib7000p_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk70x0p_pid_filter_ctrl(struct dvb_usb_adapter *adapter, int onoff)
{
- return dib7000p_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+ return state->dib7000p_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
static struct dibx000_bandwidth_config dib7070_bw_config_12_mhz = {
@@ -936,6 +980,11 @@ static struct dib7000p_config dib7070p_dib7000p_config = {
static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -954,14 +1003,15 @@ static int stk7070p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&dib7070p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&dib7070p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -988,6 +1038,11 @@ static struct dib7000p_config dib7770p_dib7000p_config = {
static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct usb_device_descriptor *p = &adap->dev->udev->descriptor;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
if (p->idVendor == cpu_to_le16(USB_VID_PINNACLE) &&
p->idProduct == cpu_to_le16(USB_PID_PINNACLE_PCTV72E))
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -1006,14 +1061,15 @@ static int stk7770p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
&dib7770p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80,
&dib7770p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -1161,12 +1217,18 @@ static struct dib8000_config dib807x_dib8000_config[2] = {
static int dib80xx_tuner_reset(struct dvb_frontend *fe, int onoff)
{
- return dib8000_set_gpio(fe, 5, 0, !onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.set_gpio(fe, 5, 0, !onoff);
}
static int dib80xx_tuner_sleep(struct dvb_frontend *fe, int onoff)
{
- return dib8000_set_gpio(fe, 0, 0, onoff);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.set_gpio(fe, 0, 0, onoff);
}
static const struct dib0070_wbd_gain_cfg dib8070_wbd_gain_cfg[] = {
@@ -1223,7 +1285,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe)
offset += 250; break;
}
deb_info("WBD for DiB8000: %d\n", offset);
- dib8000_set_wbd_ref(fe, offset);
+ state->dib8000_ops.set_wbd_ref(fe, offset);
return state->set_param_save(fe);
}
@@ -1231,7 +1293,7 @@ static int dib807x_set_param_override(struct dvb_frontend *fe)
static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe,
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (adap->id == 0) {
@@ -1252,18 +1314,27 @@ static int dib807x_tuner_attach(struct dvb_usb_adapter *adap)
static int stk80xx_pid_filter(struct dvb_usb_adapter *adapter, int index,
u16 pid, int onoff)
{
- return dib8000_pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+
+ return state->dib8000_ops.pid_filter(adapter->fe_adap[0].fe, index, pid, onoff);
}
static int stk80xx_pid_filter_ctrl(struct dvb_usb_adapter *adapter,
int onoff)
{
- return dib8000_pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
+ struct dib0700_adapter_state *state = adapter->priv;
+
+ return state->dib8000_ops.pid_filter_ctrl(adapter->fe_adap[0].fe, onoff);
}
/* STK807x */
static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1279,10 +1350,10 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18,
0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1291,6 +1362,11 @@ static int stk807x_frontend_attach(struct dvb_usb_adapter *adap)
/* STK807xPVR */
static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(30);
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
@@ -1309,9 +1385,9 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x22, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80,
&dib807x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1319,10 +1395,15 @@ static int stk807xpvr_frontend_attach0(struct dvb_usb_adapter *adap)
static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
/* initialize IC 1 */
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x12, 0x82, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82,
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82,
&dib807x_dib8000_config[1]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -1331,104 +1412,121 @@ static int stk807xpvr_frontend_attach1(struct dvb_usb_adapter *adap)
/* STK8096GP */
static struct dibx000_agc_config dib8090_agc_config[2] = {
{
- BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
+ .band_caps = BAND_UHF | BAND_VHF | BAND_LBAND | BAND_SBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
- (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
- 787,
- 10,
-
- 0,
- 118,
-
- 0,
- 3530,
- 1,
- 5,
+ .inv_gain = 787,
+ .time_stabiliz = 10,
- 65535,
- 0,
+ .alpha_level = 0,
+ .thlock = 118,
- 65535,
- 0,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
- 0,
- 32,
- 114,
- 143,
- 144,
- 114,
- 227,
- 116,
- 117,
+ .agc1_max = 65535,
+ .agc1_min = 0,
- 28,
- 26,
- 31,
- 51,
+ .agc2_max = 65535,
+ .agc2_min = 0,
- 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 32,
+ .agc1_pt3 = 114,
+ .agc1_slope1 = 143,
+ .agc1_slope2 = 144,
+ .agc2_pt1 = 114,
+ .agc2_pt2 = 227,
+ .agc2_slope1 = 116,
+ .agc2_slope2 = 117,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
},
{
- BAND_CBAND,
+ .band_caps = BAND_CBAND,
/* P_agc_use_sd_mod1=0, P_agc_use_sd_mod2=0, P_agc_freq_pwm_div=1,
* P_agc_inv_pwm1=0, P_agc_inv_pwm2=0, P_agc_inh_dc_rv_est=0,
* P_agc_time_est=3, P_agc_freeze=0, P_agc_nb_est=5, P_agc_write=0 */
- (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
+ .setup = (0 << 15) | (0 << 14) | (5 << 11) | (0 << 10) | (0 << 9) | (0 << 8)
| (3 << 5) | (0 << 4) | (5 << 1) | (0 << 0),
- 787,
- 10,
-
- 0,
- 118,
+ .inv_gain = 787,
+ .time_stabiliz = 10,
- 0,
- 3530,
- 1,
- 5,
-
- 0,
- 0,
+ .alpha_level = 0,
+ .thlock = 118,
- 65535,
- 0,
+ .wbd_inv = 0,
+ .wbd_ref = 3530,
+ .wbd_sel = 1,
+ .wbd_alpha = 5,
- 0,
- 32,
- 114,
- 143,
- 144,
- 114,
- 227,
- 116,
- 117,
+ .agc1_max = 0,
+ .agc1_min = 0,
- 28,
- 26,
- 31,
- 51,
+ .agc2_max = 65535,
+ .agc2_min = 0,
- 0,
+ .agc1_pt1 = 0,
+ .agc1_pt2 = 32,
+ .agc1_pt3 = 114,
+ .agc1_slope1 = 143,
+ .agc1_slope2 = 144,
+ .agc2_pt1 = 114,
+ .agc2_pt2 = 227,
+ .agc2_slope1 = 116,
+ .agc2_slope2 = 117,
+
+ .alpha_mant = 28,
+ .alpha_exp = 26,
+ .beta_mant = 31,
+ .beta_exp = 51,
+
+ .perform_agc_softsplit = 0,
}
};
static struct dibx000_bandwidth_config dib8090_pll_config_12mhz = {
- 54000, 13500,
- 1, 18, 3, 1, 0,
- 0, 0, 1, 1, 2,
- (3 << 14) | (1 << 12) | (599 << 0),
- (0 << 25) | 0,
- 20199727,
- 12000000,
+ .internal = 54000,
+ .sampling = 13500,
+
+ .pll_prediv = 1,
+ .pll_ratio = 18,
+ .pll_range = 3,
+ .pll_reset = 1,
+ .pll_bypass = 0,
+
+ .enable_refdiv = 0,
+ .bypclk_div = 0,
+ .IO_CLK_en_core = 1,
+ .ADClkSrc = 1,
+ .modulo = 2,
+
+ .sad_cfg = (3 << 14) | (1 << 12) | (599 << 0),
+
+ .ifreq = (0 << 25) | 0,
+ .timf = 20199727,
+
+ .xtal_hz = 12000000,
};
static int dib8090_get_adc_power(struct dvb_frontend *fe)
{
- return dib8000_get_adc_power(fe, 1);
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ return state->dib8000_ops.get_adc_power(fe, 1);
}
static void dib8090_agc_control(struct dvb_frontend *fe, u8 restart)
@@ -1551,10 +1649,10 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
default:
deb_info("Warning : Rf frequency (%iHz) is not in the supported range, using VHF switch ", fe->dtv_property_cache.frequency);
case BAND_VHF:
- dib8000_set_gpio(fe, 3, 0, 1);
+ state->dib8000_ops.set_gpio(fe, 3, 0, 1);
break;
case BAND_UHF:
- dib8000_set_gpio(fe, 3, 0, 0);
+ state->dib8000_ops.set_gpio(fe, 3, 0, 0);
break;
}
@@ -1568,7 +1666,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
}
/** Update PLL if needed ratio **/
- dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
/** Get optimize PLL ratio to remove spurious **/
pll_ratio = dib8090_compute_pll_parameters(fe);
@@ -1582,14 +1680,14 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
timf = 18179756;
/** Update ratio **/
- dib8000_update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
+ state->dib8000_ops.update_pll(fe, &dib8090_pll_config_12mhz, fe->dtv_property_cache.bandwidth_hz / 1000, pll_ratio);
- dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, timf);
+ state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, timf);
if (band != BAND_CBAND) {
/* dib0090_get_wbd_target is returning any possible temperature compensated wbd-target */
target = (dib0090_get_wbd_target(fe) * 8 * 18 / 33 + 1) / 2;
- dib8000_set_wbd_ref(fe, target);
+ state->dib8000_ops.set_wbd_ref(fe, target);
}
if (band == BAND_CBAND) {
@@ -1601,18 +1699,18 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
msleep(ret);
tune_state = dib0090_get_tune_state(fe);
if (tune_state == CT_AGC_STEP_0)
- dib8000_set_gpio(fe, 6, 0, 1);
+ state->dib8000_ops.set_gpio(fe, 6, 0, 1);
else if (tune_state == CT_AGC_STEP_1) {
dib0090_get_current_gain(fe, NULL, NULL, &rf_gain_limit, &ltgain);
if (rf_gain_limit < 2000) /* activate the external attenuator in case of very high input power */
- dib8000_set_gpio(fe, 6, 0, 0);
+ state->dib8000_ops.set_gpio(fe, 6, 0, 0);
}
} while (tune_state < CT_AGC_STOP);
deb_info("switching to PWM AGC\n");
dib0090_pwm_gain_reset(fe);
- dib8000_pwm_agc_reset(fe);
- dib8000_set_tune_state(fe, CT_DEMOD_START);
+ state->dib8000_ops.pwm_agc_reset(fe);
+ state->dib8000_ops.set_tune_state(fe, CT_DEMOD_START);
} else {
/* for everything else than CBAND we are using standard AGC */
deb_info("not tuning in CBAND - standard AGC startup\n");
@@ -1625,7 +1723,7 @@ static int dib8096_set_param_override(struct dvb_frontend *fe)
static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
@@ -1637,6 +1735,11 @@ static int dib809x_tuner_attach(struct dvb_usb_adapter *adap)
static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -1652,9 +1755,9 @@ static int stk809x_frontend_attach(struct dvb_usb_adapter *adap)
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 18, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -1663,16 +1766,16 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c;
- struct dvb_frontend *fe_slave = dib8000_get_slave_frontend(adap->fe_adap[0].fe, 1);
+ struct dvb_frontend *fe_slave = st->dib8000_ops.get_slave_frontend(adap->fe_adap[0].fe, 1);
if (fe_slave) {
- tun_i2c = dib8000_get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = st->dib8000_ops.get_i2c_master(fe_slave, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, fe_slave, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
fe_slave->dvb = adap->fe_adap[0].fe->dvb;
fe_slave->ops.tuner_ops.set_params = dib8096_set_param_override;
}
- tun_i2c = dib8000_get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
+ tun_i2c = st->dib8000_ops.get_i2c_master(adap->fe_adap[0].fe, DIBX000_I2C_INTERFACE_TUNER, 1);
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &dib809x_dib0090_config) == NULL)
return -ENODEV;
@@ -1685,6 +1788,10 @@ static int nim8096md_tuner_attach(struct dvb_usb_adapter *adap)
static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_frontend *fe_slave;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
msleep(20);
@@ -1703,14 +1810,18 @@ static int nim8096md_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18, 0x80, 0);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x80, &dib809x_dib8000_config[0]);
if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- fe_slave = dvb_attach(dib8000_attach, &adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
- dib8000_set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
+ /* Needed to increment refcount */
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
+
+ fe_slave = state->dib8000_ops.init(&adap->dev->i2c_adap, 0x82, &dib809x_dib8000_config[1]);
+ state->dib8000_ops.set_slave_frontend(adap->fe_adap[0].fe, fe_slave);
return fe_slave == NULL ? -ENODEV : 0;
}
@@ -1845,7 +1956,7 @@ static struct dib0090_wbd_slope dib8096p_wbd_table[] = {
{ 0xFFFF, 0, 0, 0, 0, 0},
};
-static const struct dib0090_config tfe8096p_dib0090_config = {
+static struct dib0090_config tfe8096p_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -1853,8 +1964,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib8096p_tuner_sleep,
- .sleep = dib8096p_tuner_sleep,
.freq_offset_khz_uhf = -143,
.freq_offset_khz_vhf = -143,
@@ -1871,8 +1980,6 @@ static const struct dib0090_config tfe8096p_dib0090_config = {
.fref_clock_ratio = 1,
- .wbd = dib8096p_wbd_table,
-
.ls_cfg_pad_drv = 0,
.data_tx_drv = 0,
.low_if = NULL,
@@ -1983,15 +2090,15 @@ static int dib8096p_agc_startup(struct dvb_frontend *fe)
/* dib0090_get_wbd_target is returning any possible
temperature compensated wbd-target */
target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
- dib8000_set_wbd_ref(fe, target);
+ state->dib8000_ops.set_wbd_ref(fe, target);
if (dib8096p_get_best_sampling(fe, &adc) == 0) {
pll.pll_ratio = adc.pll_loopdiv;
pll.pll_prediv = adc.pll_prediv;
dib0700_set_i2c_speed(adap->dev, 200);
- dib8000_update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
- dib8000_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+ state->dib8000_ops.update_pll(fe, &pll, fe->dtv_property_cache.bandwidth_hz / 1000, 0);
+ state->dib8000_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
dib0700_set_i2c_speed(adap->dev, 1000);
}
return 0;
@@ -2001,6 +2108,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
u32 fw_version;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib8000_attach, &state->dib8000_ops))
+ return -ENODEV;
dib0700_get_version(adap->dev, NULL, NULL, &fw_version, NULL);
if (fw_version >= 0x10200)
@@ -2021,10 +2132,10 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- dib8000_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
+ state->dib8000_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, 0x80, 1);
- adap->fe_adap[0].fe = dvb_attach(dib8000_attach,
- &adap->dev->i2c_adap, 0x80, &tfe8096p_dib8000_config);
+ adap->fe_adap[0].fe = state->dib8000_ops.init(&adap->dev->i2c_adap,
+ 0x80, &tfe8096p_dib8000_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -2032,13 +2143,17 @@ static int tfe8096p_frontend_attach(struct dvb_usb_adapter *adap)
static int tfe8096p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib8096p_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib8000_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe8096p_dib0090_config.reset = st->dib8000_ops.tuner_sleep;
+ tfe8096p_dib0090_config.sleep = st->dib8000_ops.tuner_sleep;
+ tfe8096p_dib0090_config.wbd = dib8096p_wbd_table;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
&tfe8096p_dib0090_config) == NULL)
return -ENODEV;
- dib8000_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib8000_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib8096p_agc_startup;
@@ -2479,14 +2594,14 @@ static int dib7090_agc_startup(struct dvb_frontend *fe)
memset(&pll, 0, sizeof(struct dibx000_bandwidth_config));
dib0090_pwm_gain_reset(fe);
target = (dib0090_get_wbd_target(fe) * 8 + 1) / 2;
- dib7000p_set_wbd_ref(fe, target);
+ state->dib7000p_ops.set_wbd_ref(fe, target);
if (dib7090p_get_best_sampling(fe, &adc) == 0) {
pll.pll_ratio = adc.pll_loopdiv;
pll.pll_prediv = adc.pll_prediv;
- dib7000p_update_pll(fe, &pll);
- dib7000p_ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
+ state->dib7000p_ops.update_pll(fe, &pll);
+ state->dib7000p_ops.ctrl_timf(fe, DEMOD_TIMF_SET, adc.timf);
}
return 0;
}
@@ -2501,14 +2616,17 @@ static int dib7090_agc_restart(struct dvb_frontend *fe, u8 restart)
static int tfe7790p_update_lna(struct dvb_frontend *fe, u16 agc_global)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("update LNA: agc global=%i", agc_global);
if (agc_global < 25000) {
- dib7000p_set_gpio(fe, 8, 0, 0);
- dib7000p_set_agc1_min(fe, 0);
+ state->dib7000p_ops.set_gpio(fe, 8, 0, 0);
+ state->dib7000p_ops.set_agc1_min(fe, 0);
} else {
- dib7000p_set_gpio(fe, 8, 0, 1);
- dib7000p_set_agc1_min(fe, 32768);
+ state->dib7000p_ops.set_gpio(fe, 8, 0, 1);
+ state->dib7000p_ops.set_agc1_min(fe, 32768);
}
return 0;
@@ -2644,13 +2762,16 @@ static struct dib7000p_config nim7090_dib7000p_config = {
static int tfe7090p_pvr_update_lna(struct dvb_frontend *fe, u16 agc_global)
{
+ struct dvb_usb_adapter *adap = fe->dvb->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
deb_info("TFE7090P-PVR update LNA: agc global=%i", agc_global);
if (agc_global < 25000) {
- dib7000p_set_gpio(fe, 5, 0, 0);
- dib7000p_set_agc1_min(fe, 0);
+ state->dib7000p_ops.set_gpio(fe, 5, 0, 0);
+ state->dib7000p_ops.set_agc1_min(fe, 0);
} else {
- dib7000p_set_gpio(fe, 5, 0, 1);
- dib7000p_set_agc1_min(fe, 32768);
+ state->dib7000p_ops.set_gpio(fe, 5, 0, 1);
+ state->dib7000p_ops.set_agc1_min(fe, 32768);
}
return 0;
@@ -2714,7 +2835,7 @@ static struct dib7000p_config tfe7090pvr_dib7000p_config[2] = {
}
};
-static const struct dib0090_config nim7090_dib0090_config = {
+static struct dib0090_config nim7090_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -2722,14 +2843,10 @@ static const struct dib0090_config nim7090_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2776,7 +2893,7 @@ static struct dib7000p_config tfe7790p_dib7000p_config = {
.enMpegOutput = 1,
};
-static const struct dib0090_config tfe7790p_dib0090_config = {
+static struct dib0090_config tfe7790p_dib0090_config = {
.io.clock_khz = 12000,
.io.pll_bypass = 0,
.io.pll_range = 0,
@@ -2784,14 +2901,10 @@ static const struct dib0090_config tfe7790p_dib0090_config = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 0,
.freq_offset_khz_vhf = 0,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2813,7 +2926,7 @@ static const struct dib0090_config tfe7790p_dib0090_config = {
.force_crystal_mode = 1,
};
-static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
+static struct dib0090_config tfe7090pvr_dib0090_config[2] = {
{
.io.clock_khz = 12000,
.io.pll_bypass = 0,
@@ -2822,14 +2935,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = 50,
.freq_offset_khz_vhf = 70,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2854,14 +2963,10 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
.io.pll_loopdiv = 6,
.io.adc_clock_ratio = 0,
.io.pll_int_loop_filt = 0,
- .reset = dib7090_tuner_sleep,
- .sleep = dib7090_tuner_sleep,
.freq_offset_khz_uhf = -50,
.freq_offset_khz_vhf = -70,
- .get_adc_power = dib7090_get_adc_power,
-
.clkouttobamse = 1,
.analog_output = 0,
@@ -2883,6 +2988,11 @@ static const struct dib0090_config tfe7090pvr_dib0090_config[2] = {
static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 1);
msleep(20);
dib0700_set_gpio(adap->dev, GPIO9, GPIO_OUT, 1);
@@ -2895,11 +3005,12 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x10, &nim7090_dib7000p_config) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &nim7090_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -2907,12 +3018,16 @@ static int nim7090_frontend_attach(struct dvb_usb_adapter *adap)
static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ nim7090_dib0090_config.reset = st->dib7000p_ops.tuner_sleep,
+ nim7090_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep,
+ nim7090_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &nim7090_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2922,6 +3037,10 @@ static int nim7090_tuner_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* The TFE7090 requires the dib0700 to not be in master mode */
st->disable_streaming_master_mode = 1;
@@ -2939,17 +3058,18 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
/* initialize IC 0 */
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 1, 0x20, &tfe7090pvr_dib7000p_config[0]) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
dib0700_set_i2c_speed(adap->dev, 340);
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x90, &tfe7090pvr_dib7000p_config[0]);
if (adap->fe_adap[0].fe == NULL)
return -ENODEV;
- dib7090_slave_reset(adap->fe_adap[0].fe);
+ state->dib7000p_ops.slave_reset(adap->fe_adap[0].fe);
return 0;
}
@@ -2957,19 +3077,24 @@ static int tfe7090pvr_frontend0_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *i2c;
+ struct dib0700_adapter_state *state = adap->priv;
if (adap->dev->adapter[0].fe_adap[0].fe == NULL) {
err("the master dib7090 has to be initialized first");
return -ENODEV; /* the master device has not been initialized */
}
- i2c = dib7000p_get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
- if (dib7000p_i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n", __func__);
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ i2c = state->dib7000p_ops.get_i2c_master(adap->dev->adapter[0].fe_adap[0].fe, DIBX000_I2C_INTERFACE_GPIO_6_7, 1);
+ if (state->dib7000p_ops.i2c_enumeration(i2c, 1, 0x10, &tfe7090pvr_dib7000p_config[1]) != 0) {
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n", __func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(i2c, 0x92, &tfe7090pvr_dib7000p_config[1]);
dib0700_set_i2c_speed(adap->dev, 200);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -2978,12 +3103,16 @@ static int tfe7090pvr_frontend1_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe7090pvr_dib0090_config[0].reset = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[0].sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[0].get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[0]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -2993,12 +3122,16 @@ static int tfe7090pvr_tuner0_attach(struct dvb_usb_adapter *adap)
static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
- struct i2c_adapter *tun_i2c = dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ struct i2c_adapter *tun_i2c = st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+ tfe7090pvr_dib0090_config[1].reset = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[1].sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7090pvr_dib0090_config[1].get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c, &tfe7090pvr_dib0090_config[1]) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3008,6 +3141,10 @@ static int tfe7090pvr_tuner1_attach(struct dvb_usb_adapter *adap)
static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* The TFE7790P requires the dib0700 to not be in master mode */
st->disable_streaming_master_mode = 1;
@@ -3024,13 +3161,14 @@ static int tfe7790p_frontend_attach(struct dvb_usb_adapter *adap)
msleep(20);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap,
1, 0x10, &tfe7790p_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap,
0x80, &tfe7790p_dib7000p_config);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
@@ -3040,13 +3178,18 @@ static int tfe7790p_tuner_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_adapter_state *st = adap->priv;
struct i2c_adapter *tun_i2c =
- dib7090_get_i2c_tuner(adap->fe_adap[0].fe);
+ st->dib7000p_ops.get_i2c_tuner(adap->fe_adap[0].fe);
+
+
+ tfe7790p_dib0090_config.reset = st->dib7000p_ops.tuner_sleep;
+ tfe7790p_dib0090_config.sleep = st->dib7000p_ops.tuner_sleep;
+ tfe7790p_dib0090_config.get_adc_power = st->dib7000p_ops.get_adc_power;
if (dvb_attach(dib0090_register, adap->fe_adap[0].fe, tun_i2c,
&tfe7790p_dib0090_config) == NULL)
return -ENODEV;
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ st->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
st->set_param_save = adap->fe_adap[0].fe->ops.tuner_ops.set_params;
adap->fe_adap[0].fe->ops.tuner_ops.set_params = dib7090_agc_startup;
@@ -3103,25 +3246,36 @@ static void stk7070pd_init(struct dvb_usb_device *dev)
static int stk7070pd_frontend_attach0(struct dvb_usb_adapter *adap)
{
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
stk7070pd_init(adap->dev);
msleep(10);
dib0700_set_gpio(adap->dev, GPIO0, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&adap->dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x80, &stk7070pd_dib7000p_config[0]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
static int stk7070pd_frontend_attach1(struct dvb_usb_adapter *adap)
{
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
+
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x82, &stk7070pd_dib7000p_config[1]);
return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
}
@@ -3164,6 +3318,10 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dvb_usb_device *dev = adap->dev;
struct dib0700_state *st = dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
if (adap->id == 0) {
stk7070pd_init(dev);
@@ -3173,15 +3331,16 @@ static int novatd_frontend_attach(struct dvb_usb_adapter *adap)
dib0700_set_gpio(dev, GPIO1, GPIO_OUT, 0);
dib0700_set_gpio(dev, GPIO2, GPIO_OUT, 1);
- if (dib7000p_i2c_enumeration(&dev->i2c_adap, 2, 18,
+ if (state->dib7000p_ops.i2c_enumeration(&dev->i2c_adap, 2, 18,
stk7070pd_dib7000p_config) != 0) {
- err("%s: dib7000p_i2c_enumeration failed. Cannot continue\n",
+ err("%s: state->dib7000p_ops.i2c_enumeration failed. Cannot continue\n",
__func__);
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &dev->i2c_adap,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&dev->i2c_adap,
adap->id == 0 ? 0x80 : 0x82,
&stk7070pd_dib7000p_config[adap->id]);
@@ -3291,12 +3450,13 @@ static int dib0700_xc4000_tuner_callback(void *priv, int component,
int command, int arg)
{
struct dvb_usb_adapter *adap = priv;
+ struct dib0700_adapter_state *state = adap->priv;
if (command == XC4000_TUNER_RESET) {
/* Reset the tuner */
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 0);
msleep(10);
- dib7000p_set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
+ state->dib7000p_ops.set_gpio(adap->fe_adap[0].fe, 8, 0, 1);
} else {
err("xc4000: unknown tuner callback command: %d\n", command);
return -EINVAL;
@@ -3374,6 +3534,10 @@ static struct dib7000p_config pctv_340e_config = {
static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
{
struct dib0700_state *st = adap->dev->priv;
+ struct dib0700_adapter_state *state = adap->priv;
+
+ if (!dvb_attach(dib7000p_attach, &state->dib7000p_ops))
+ return -ENODEV;
/* Power Supply on */
dib0700_set_gpio(adap->dev, GPIO6, GPIO_OUT, 0);
@@ -3397,12 +3561,13 @@ static int pctv340e_frontend_attach(struct dvb_usb_adapter *adap)
msleep(500);
- if (dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
+ if (state->dib7000p_ops.dib7000pc_detection(&adap->dev->i2c_adap) == 0) {
/* Demodulator not found for some reason? */
+ dvb_detach(&state->dib7000p_ops);
return -ENODEV;
}
- adap->fe_adap[0].fe = dvb_attach(dib7000p_attach, &adap->dev->i2c_adap, 0x12,
+ adap->fe_adap[0].fe = state->dib7000p_ops.init(&adap->dev->i2c_adap, 0x12,
&pctv_340e_config);
st->is_dib7000pc = 1;
@@ -3420,9 +3585,10 @@ static struct xc4000_config dib7000p_xc4000_tunerconfig = {
static int xc4000_tuner_attach(struct dvb_usb_adapter *adap)
{
struct i2c_adapter *tun_i2c;
+ struct dib0700_adapter_state *state = adap->priv;
/* The xc4000 is not on the main i2c bus */
- tun_i2c = dib7000p_get_i2c_master(adap->fe_adap[0].fe,
+ tun_i2c = state->dib7000p_ops.get_i2c_master(adap->fe_adap[0].fe,
DIBX000_I2C_INTERFACE_TUNER, 1);
if (tun_i2c == NULL) {
printk(KERN_ERR "Could not reach tuner i2c bus\n");
diff --git a/drivers/media/usb/dvb-usb/technisat-usb2.c b/drivers/media/usb/dvb-usb/technisat-usb2.c
index d947e0379008..6b0b8b6b9e2a 100644
--- a/drivers/media/usb/dvb-usb/technisat-usb2.c
+++ b/drivers/media/usb/dvb-usb/technisat-usb2.c
@@ -710,7 +710,7 @@ static struct dvb_usb_device_properties technisat_usb2_devices = {
.isoc = {
.framesperurb = 32,
.framesize = 2048,
- .interval = 3,
+ .interval = 1,
}
}
},
diff --git a/drivers/media/usb/em28xx/em28xx-cards.c b/drivers/media/usb/em28xx/em28xx-cards.c
index 15ad47045553..9da812b8a786 100644
--- a/drivers/media/usb/em28xx/em28xx-cards.c
+++ b/drivers/media/usb/em28xx/em28xx-cards.c
@@ -2280,6 +2280,8 @@ struct usb_device_id em28xx_id_table[] = {
.driver_info = EM2820_BOARD_UNKNOWN },
{ USB_DEVICE(0xeb1a, 0x2875),
.driver_info = EM2820_BOARD_UNKNOWN },
+ { USB_DEVICE(0xeb1a, 0x2885), /* MSI Digivox Trio */
+ .driver_info = EM2884_BOARD_TERRATEC_H5 },
{ USB_DEVICE(0xeb1a, 0xe300),
.driver_info = EM2861_BOARD_KWORLD_PVRTV_300U },
{ USB_DEVICE(0xeb1a, 0xe303),
diff --git a/drivers/media/usb/em28xx/em28xx-dvb.c b/drivers/media/usb/em28xx/em28xx-dvb.c
index a121ed9561fd..96a0bdbecfad 100644
--- a/drivers/media/usb/em28xx/em28xx-dvb.c
+++ b/drivers/media/usb/em28xx/em28xx-dvb.c
@@ -1545,6 +1545,7 @@ static int em28xx_dvb_init(struct em28xx *dev)
dvb->i2c_client_demod = client;
/* attach tuner */
+ memset(&si2157_config, 0, sizeof(si2157_config));
si2157_config.fe = dvb->fe[0];
memset(&info, 0, sizeof(struct i2c_board_info));
strlcpy(info.type, "si2157", I2C_NAME_SIZE);
diff --git a/drivers/media/usb/em28xx/em28xx-video.c b/drivers/media/usb/em28xx/em28xx-video.c
index f6b49c98e2c9..3f8b5aa7669a 100644
--- a/drivers/media/usb/em28xx/em28xx-video.c
+++ b/drivers/media/usb/em28xx/em28xx-video.c
@@ -2208,7 +2208,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
vfd->v4l2_dev = &dev->v4l2->v4l2_dev;
vfd->debug = video_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
if (dev->board.is_webcam)
vfd->tvnorms = 0;
diff --git a/drivers/media/usb/gspca/autogain_functions.c b/drivers/media/usb/gspca/autogain_functions.c
index 67db674bb044..0e9ee8b50bb7 100644
--- a/drivers/media/usb/gspca/autogain_functions.c
+++ b/drivers/media/usb/gspca/autogain_functions.c
@@ -121,9 +121,9 @@ int gspca_coarse_grained_expo_autogain(
orig_gain = gain = v4l2_ctrl_g_ctrl(gspca_dev->gain);
orig_exposure = exposure = v4l2_ctrl_g_ctrl(gspca_dev->exposure);
- gain_low = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+ gain_low = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
5 * 2 + gspca_dev->gain->minimum;
- gain_high = (gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
+ gain_high = (s32)(gspca_dev->gain->maximum - gspca_dev->gain->minimum) /
5 * 4 + gspca_dev->gain->minimum;
/* If we are of a multiple of deadzone, do multiple steps to reach the
diff --git a/drivers/media/usb/gspca/gspca.c b/drivers/media/usb/gspca/gspca.c
index f3a7ace0fac9..e8cf23c91cef 100644
--- a/drivers/media/usb/gspca/gspca.c
+++ b/drivers/media/usb/gspca/gspca.c
@@ -603,10 +603,13 @@ static void gspca_stream_off(struct gspca_dev *gspca_dev)
}
/*
- * look for an input transfer endpoint in an alternate setting
+ * look for an input transfer endpoint in an alternate setting.
+ *
+ * If xfer_ep is invalid, return the first valid ep found, otherwise
+ * look for exactly the ep with address equal to xfer_ep.
*/
static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
- int xfer)
+ int xfer, int xfer_ep)
{
struct usb_host_endpoint *ep;
int i, attr;
@@ -616,7 +619,8 @@ static struct usb_host_endpoint *alt_xfer(struct usb_host_interface *alt,
attr = ep->desc.bmAttributes & USB_ENDPOINT_XFERTYPE_MASK;
if (attr == xfer
&& ep->desc.wMaxPacketSize != 0
- && usb_endpoint_dir_in(&ep->desc))
+ && usb_endpoint_dir_in(&ep->desc)
+ && (xfer_ep < 0 || ep->desc.bEndpointAddress == xfer_ep))
return ep;
}
return NULL;
@@ -689,7 +693,8 @@ static int build_isoc_ep_tb(struct gspca_dev *gspca_dev,
found = 0;
for (j = 0; j < nbalt; j++) {
ep = alt_xfer(&intf->altsetting[j],
- USB_ENDPOINT_XFER_ISOC);
+ USB_ENDPOINT_XFER_ISOC,
+ gspca_dev->xfer_ep);
if (ep == NULL)
continue;
if (ep->desc.bInterval == 0) {
@@ -862,7 +867,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
/* if bulk or the subdriver forced an altsetting, get the endpoint */
if (gspca_dev->alt != 0) {
gspca_dev->alt--; /* (previous version compatibility) */
- ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer);
+ ep = alt_xfer(&intf->altsetting[gspca_dev->alt], xfer,
+ gspca_dev->xfer_ep);
if (ep == NULL) {
pr_err("bad altsetting %d\n", gspca_dev->alt);
return -EIO;
@@ -904,7 +910,8 @@ static int gspca_init_transfer(struct gspca_dev *gspca_dev)
if (!gspca_dev->cam.no_urb_create) {
PDEBUG(D_STREAM, "init transfer alt %d", alt);
ret = create_urbs(gspca_dev,
- alt_xfer(&intf->altsetting[alt], xfer));
+ alt_xfer(&intf->altsetting[alt], xfer,
+ gspca_dev->xfer_ep));
if (ret < 0) {
destroy_urbs(gspca_dev);
goto out;
@@ -1102,8 +1109,8 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
struct gspca_dev *gspca_dev = video_drvdata(file);
fmt->fmt.pix = gspca_dev->pixfmt;
- /* some drivers use priv internally, zero it before giving it to
- userspace */
+ /* some drivers use priv internally, zero it before giving it back to
+ the core */
fmt->fmt.pix.priv = 0;
return 0;
}
@@ -1139,8 +1146,8 @@ static int try_fmt_vid_cap(struct gspca_dev *gspca_dev,
fmt->fmt.pix.height = h;
gspca_dev->sd_desc->try_fmt(gspca_dev, fmt);
}
- /* some drivers use priv internally, zero it before giving it to
- userspace */
+ /* some drivers use priv internally, zero it before giving it back to
+ the core */
fmt->fmt.pix.priv = 0;
return mode; /* used when s_fmt */
}
@@ -2030,6 +2037,7 @@ int gspca_dev_probe2(struct usb_interface *intf,
}
gspca_dev->dev = dev;
gspca_dev->iface = intf->cur_altsetting->desc.bInterfaceNumber;
+ gspca_dev->xfer_ep = -1;
/* check if any audio device */
if (dev->actconfig->desc.bNumInterfaces != 1) {
@@ -2058,7 +2066,6 @@ int gspca_dev_probe2(struct usb_interface *intf,
gspca_dev->vdev = gspca_template;
gspca_dev->vdev.v4l2_dev = &gspca_dev->v4l2_dev;
video_set_drvdata(&gspca_dev->vdev, gspca_dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &gspca_dev->vdev.flags);
gspca_dev->module = module;
gspca_dev->present = 1;
diff --git a/drivers/media/usb/gspca/gspca.h b/drivers/media/usb/gspca/gspca.h
index 300642dc1a17..f06253cd7469 100644
--- a/drivers/media/usb/gspca/gspca.h
+++ b/drivers/media/usb/gspca/gspca.h
@@ -205,6 +205,7 @@ struct gspca_dev {
char memory; /* memory type (V4L2_MEMORY_xxx) */
__u8 iface; /* USB interface number */
__u8 alt; /* USB alternate setting */
+ int xfer_ep; /* USB transfer endpoint address */
u8 audio; /* presence of audio device */
/* (*) These variables are proteced by both usb_lock and queue_lock,
diff --git a/drivers/media/usb/gspca/kinect.c b/drivers/media/usb/gspca/kinect.c
index 081f05162809..45bc1f51c5d8 100644
--- a/drivers/media/usb/gspca/kinect.c
+++ b/drivers/media/usb/gspca/kinect.c
@@ -36,6 +36,8 @@ MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
MODULE_DESCRIPTION("GSPCA/Kinect Sensor Device USB Camera Driver");
MODULE_LICENSE("GPL");
+static bool depth_mode;
+
struct pkt_hdr {
uint8_t magic[2];
uint8_t pad;
@@ -73,6 +75,14 @@ struct sd {
#define FPS_HIGH 0x0100
+static const struct v4l2_pix_format depth_camera_mode[] = {
+ {640, 480, V4L2_PIX_FMT_Y10BPACK, V4L2_FIELD_NONE,
+ .bytesperline = 640 * 10 / 8,
+ .sizeimage = 640 * 480 * 10 / 8,
+ .colorspace = V4L2_COLORSPACE_SRGB,
+ .priv = MODE_640x488 | FORMAT_Y10B},
+};
+
static const struct v4l2_pix_format video_camera_mode[] = {
{640, 480, V4L2_PIX_FMT_SGRBG8, V4L2_FIELD_NONE,
.bytesperline = 640,
@@ -219,7 +229,7 @@ static int write_register(struct gspca_dev *gspca_dev, uint16_t reg,
}
/* this function is called at probe time */
-static int sd_config(struct gspca_dev *gspca_dev,
+static int sd_config_video(struct gspca_dev *gspca_dev,
const struct usb_device_id *id)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -227,8 +237,6 @@ static int sd_config(struct gspca_dev *gspca_dev,
sd->cam_tag = 0;
- /* Only video stream is supported for now,
- * which has stream flag = 0x80 */
sd->stream_flag = 0x80;
cam = &gspca_dev->cam;
@@ -236,6 +244,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
cam->cam_mode = video_camera_mode;
cam->nmodes = ARRAY_SIZE(video_camera_mode);
+ gspca_dev->xfer_ep = 0x81;
+
#if 0
/* Setting those values is not needed for video stream */
cam->npkt = 15;
@@ -245,6 +255,26 @@ static int sd_config(struct gspca_dev *gspca_dev,
return 0;
}
+static int sd_config_depth(struct gspca_dev *gspca_dev,
+ const struct usb_device_id *id)
+{
+ struct sd *sd = (struct sd *) gspca_dev;
+ struct cam *cam;
+
+ sd->cam_tag = 0;
+
+ sd->stream_flag = 0x70;
+
+ cam = &gspca_dev->cam;
+
+ cam->cam_mode = depth_camera_mode;
+ cam->nmodes = ARRAY_SIZE(depth_camera_mode);
+
+ gspca_dev->xfer_ep = 0x82;
+
+ return 0;
+}
+
/* this function is called at probe and resume time */
static int sd_init(struct gspca_dev *gspca_dev)
{
@@ -253,7 +283,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
return 0;
}
-static int sd_start(struct gspca_dev *gspca_dev)
+static int sd_start_video(struct gspca_dev *gspca_dev)
{
int mode;
uint8_t fmt_reg, fmt_val;
@@ -325,12 +355,39 @@ static int sd_start(struct gspca_dev *gspca_dev)
return 0;
}
-static void sd_stopN(struct gspca_dev *gspca_dev)
+static int sd_start_depth(struct gspca_dev *gspca_dev)
+{
+ /* turn off IR-reset function */
+ write_register(gspca_dev, 0x105, 0x00);
+
+ /* reset depth stream */
+ write_register(gspca_dev, 0x06, 0x00);
+ /* Depth Stream Format 0x03: 11 bit stream | 0x02: 10 bit */
+ write_register(gspca_dev, 0x12, 0x02);
+ /* Depth Stream Resolution 1: standard (640x480) */
+ write_register(gspca_dev, 0x13, 0x01);
+ /* Depth Framerate / 0x1e (30): 30 fps */
+ write_register(gspca_dev, 0x14, 0x1e);
+ /* Depth Stream Control / 2: Open Depth Stream */
+ write_register(gspca_dev, 0x06, 0x02);
+ /* disable depth hflip / LSB = 0: Smoothing Disabled */
+ write_register(gspca_dev, 0x17, 0x00);
+
+ return 0;
+}
+
+static void sd_stopN_video(struct gspca_dev *gspca_dev)
{
/* reset video stream */
write_register(gspca_dev, 0x05, 0x00);
}
+static void sd_stopN_depth(struct gspca_dev *gspca_dev)
+{
+ /* reset depth stream */
+ write_register(gspca_dev, 0x06, 0x00);
+}
+
static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
{
struct sd *sd = (struct sd *) gspca_dev;
@@ -366,12 +423,24 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev, u8 *__data, int len)
}
/* sub-driver description */
-static const struct sd_desc sd_desc = {
+static const struct sd_desc sd_desc_video = {
.name = MODULE_NAME,
- .config = sd_config,
+ .config = sd_config_video,
.init = sd_init,
- .start = sd_start,
- .stopN = sd_stopN,
+ .start = sd_start_video,
+ .stopN = sd_stopN_video,
+ .pkt_scan = sd_pkt_scan,
+ /*
+ .get_streamparm = sd_get_streamparm,
+ .set_streamparm = sd_set_streamparm,
+ */
+};
+static const struct sd_desc sd_desc_depth = {
+ .name = MODULE_NAME,
+ .config = sd_config_depth,
+ .init = sd_init,
+ .start = sd_start_depth,
+ .stopN = sd_stopN_depth,
.pkt_scan = sd_pkt_scan,
/*
.get_streamparm = sd_get_streamparm,
@@ -391,8 +460,12 @@ MODULE_DEVICE_TABLE(usb, device_table);
/* -- device connect -- */
static int sd_probe(struct usb_interface *intf, const struct usb_device_id *id)
{
- return gspca_dev_probe(intf, id, &sd_desc, sizeof(struct sd),
- THIS_MODULE);
+ if (depth_mode)
+ return gspca_dev_probe(intf, id, &sd_desc_depth,
+ sizeof(struct sd), THIS_MODULE);
+ else
+ return gspca_dev_probe(intf, id, &sd_desc_video,
+ sizeof(struct sd), THIS_MODULE);
}
static struct usb_driver sd_driver = {
@@ -408,3 +481,6 @@ static struct usb_driver sd_driver = {
};
module_usb_driver(sd_driver);
+
+module_param(depth_mode, bool, 0644);
+MODULE_PARM_DESC(depth_mode, "0=video 1=depth");
diff --git a/drivers/media/usb/gspca/pac7302.c b/drivers/media/usb/gspca/pac7302.c
index 339adce7c7a5..8b08bd0172f4 100644
--- a/drivers/media/usb/gspca/pac7302.c
+++ b/drivers/media/usb/gspca/pac7302.c
@@ -394,9 +394,9 @@ static void setbrightcont(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 10; i++) {
v = max[i];
- v += (sd->brightness->val - sd->brightness->maximum)
- * 150 / sd->brightness->maximum; /* 200 ? */
- v -= delta[i] * sd->contrast->val / sd->contrast->maximum;
+ v += (sd->brightness->val - (s32)sd->brightness->maximum)
+ * 150 / (s32)sd->brightness->maximum; /* 200 ? */
+ v -= delta[i] * sd->contrast->val / (s32)sd->contrast->maximum;
if (v < 0)
v = 0;
else if (v > 0xff)
@@ -419,7 +419,7 @@ static void setcolors(struct gspca_dev *gspca_dev)
reg_w(gspca_dev, 0x11, 0x01);
reg_w(gspca_dev, 0xff, 0x00); /* page 0 */
for (i = 0; i < 9; i++) {
- v = a[i] * sd->saturation->val / sd->saturation->maximum;
+ v = a[i] * sd->saturation->val / (s32)sd->saturation->maximum;
v += b[i];
reg_w(gspca_dev, 0x0f + 2 * i, (v >> 8) & 0x07);
reg_w(gspca_dev, 0x0f + 2 * i + 1, v);
diff --git a/drivers/media/usb/gspca/sonixb.c b/drivers/media/usb/gspca/sonixb.c
index ecbcb39feb71..6696b2ec34e9 100644
--- a/drivers/media/usb/gspca/sonixb.c
+++ b/drivers/media/usb/gspca/sonixb.c
@@ -913,7 +913,7 @@ static void do_autogain(struct gspca_dev *gspca_dev)
desired_avg_lum, deadzone))
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
} else {
- int gain_knee = gspca_dev->gain->maximum * 9 / 10;
+ int gain_knee = (s32)gspca_dev->gain->maximum * 9 / 10;
if (gspca_expo_autogain(gspca_dev, avg_lum, desired_avg_lum,
deadzone, gain_knee, sd->exposure_knee))
sd->autogain_ignore_frames = AUTOGAIN_IGNORE_FRAMES;
diff --git a/drivers/media/usb/hdpvr/hdpvr-video.c b/drivers/media/usb/hdpvr/hdpvr-video.c
index 6bce01a674f9..59d15fd242ba 100644
--- a/drivers/media/usb/hdpvr/hdpvr-video.c
+++ b/drivers/media/usb/hdpvr/hdpvr-video.c
@@ -1022,14 +1022,13 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *_fh,
f->fmt.pix.pixelformat = V4L2_PIX_FMT_MPEG;
f->fmt.pix.sizeimage = dev->bulk_in_size;
f->fmt.pix.bytesperline = 0;
- f->fmt.pix.priv = 0;
if (f->fmt.pix.width == 720) {
/* SDTV formats */
f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
f->fmt.pix.field = V4L2_FIELD_INTERLACED;
} else {
/* HDTV formats */
- f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE240M;
+ f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
f->fmt.pix.field = V4L2_FIELD_NONE;
}
return 0;
@@ -1240,7 +1239,6 @@ int hdpvr_register_videodev(struct hdpvr_device *dev, struct device *parent,
strcpy(dev->video_dev->name, "Hauppauge HD PVR");
dev->video_dev->v4l2_dev = &dev->v4l2_dev;
video_set_drvdata(dev->video_dev, dev);
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->video_dev->flags);
res = video_register_device(dev->video_dev, VFL_TYPE_GRABBER, devnum);
if (res < 0) {
diff --git a/drivers/media/usb/msi2500/Kconfig b/drivers/media/usb/msi2500/Kconfig
new file mode 100644
index 000000000000..9eff8a76ff0e
--- /dev/null
+++ b/drivers/media/usb/msi2500/Kconfig
@@ -0,0 +1,5 @@
+config USB_MSI2500
+ tristate "Mirics MSi2500"
+ depends on VIDEO_V4L2 && SPI
+ select VIDEOBUF2_VMALLOC
+ select MEDIA_TUNER_MSI001
diff --git a/drivers/media/usb/msi2500/Makefile b/drivers/media/usb/msi2500/Makefile
new file mode 100644
index 000000000000..b3bc2e53707f
--- /dev/null
+++ b/drivers/media/usb/msi2500/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_USB_MSI2500) += msi2500.o
diff --git a/drivers/staging/media/msi3101/sdr-msi3101.c b/drivers/media/usb/msi2500/msi2500.c
index 08d0d096b881..483dc6e6642d 100644
--- a/drivers/staging/media/msi3101/sdr-msi3101.c
+++ b/drivers/media/usb/msi2500/msi2500.c
@@ -34,6 +34,10 @@
#include <media/videobuf2-vmalloc.h>
#include <linux/spi/spi.h>
+static bool msi3101_emulated_fmt;
+module_param_named(emulated_formats, msi3101_emulated_fmt, bool, 0644);
+MODULE_PARM_DESC(emulated_formats, "enable emulated formats (disappears in future)");
+
/*
* iConfiguration 0
* bInterfaceNumber 0
@@ -52,9 +56,7 @@
#define MAX_ISOC_ERRORS 20
/* TODO: These should be moved to V4L2 API */
-#define V4L2_PIX_FMT_SDR_S8 v4l2_fourcc('D', 'S', '0', '8') /* signed 8-bit */
#define V4L2_PIX_FMT_SDR_S12 v4l2_fourcc('D', 'S', '1', '2') /* signed 12-bit */
-#define V4L2_PIX_FMT_SDR_S14 v4l2_fourcc('D', 'S', '1', '4') /* signed 14-bit */
#define V4L2_PIX_FMT_SDR_MSI2500_384 v4l2_fourcc('M', '3', '8', '4') /* Mirics MSi2500 format 384 */
static const struct v4l2_frequency_band bands[] = {
@@ -72,30 +74,35 @@ static const struct v4l2_frequency_band bands[] = {
struct msi3101_format {
char *name;
u32 pixelformat;
+ u32 buffersize;
};
/* format descriptions for capture and preview */
static struct msi3101_format formats[] = {
{
- .name = "IQ U8",
- .pixelformat = V4L2_SDR_FMT_CU8,
- }, {
- .name = "IQ U16LE",
- .pixelformat = V4L2_SDR_FMT_CU16LE,
+ .name = "Complex S8",
+ .pixelformat = V4L2_SDR_FMT_CS8,
+ .buffersize = 3 * 1008,
#if 0
}, {
- .name = "8-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_S8,
- }, {
.name = "10+2-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_MSI2500_384,
}, {
.name = "12-bit signed",
.pixelformat = V4L2_PIX_FMT_SDR_S12,
- }, {
- .name = "14-bit signed",
- .pixelformat = V4L2_PIX_FMT_SDR_S14,
#endif
+ }, {
+ .name = "Complex S14LE",
+ .pixelformat = V4L2_SDR_FMT_CS14LE,
+ .buffersize = 3 * 1008,
+ }, {
+ .name = "Complex U8 (emulated)",
+ .pixelformat = V4L2_SDR_FMT_CU8,
+ .buffersize = 3 * 1008,
+ }, {
+ .name = "Complex U16LE (emulated)",
+ .pixelformat = V4L2_SDR_FMT_CU16LE,
+ .buffersize = 3 * 1008,
},
};
@@ -127,6 +134,8 @@ struct msi3101_state {
unsigned int f_adc;
u32 pixelformat;
+ u32 buffersize;
+ unsigned int num_formats;
unsigned int isoc_errors; /* number of contiguous ISOC errors */
unsigned int vb_full; /* vb is full and packets dropped */
@@ -833,13 +842,7 @@ static int msi3101_queue_setup(struct vb2_queue *vq,
/* Absolute min and max number of buffers available for mmap() */
*nbuffers = clamp_t(unsigned int, *nbuffers, 8, 32);
*nplanes = 1;
- /*
- * 3, wMaxPacketSize 3x 1024 bytes
- * 504, max IQ sample pairs per 1024 frame
- * 2, two samples, I and Q
- * 2, 16-bit is enough for single sample
- */
- sizes[0] = PAGE_ALIGN(3 * 504 * 2 * 2);
+ sizes[0] = PAGE_ALIGN(s->buffersize);
dev_dbg(&s->udev->dev, "%s: nbuffers=%d sizes[0]=%d\n",
__func__, *nbuffers, sizes[0]);
return 0;
@@ -928,7 +931,7 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
s->convert_stream = msi3101_convert_stream_252_u16;
reg7 = 0x00009407;
break;
- case V4L2_PIX_FMT_SDR_S8:
+ case V4L2_SDR_FMT_CS8:
s->convert_stream = msi3101_convert_stream_504;
reg7 = 0x000c9407;
break;
@@ -940,7 +943,7 @@ static int msi3101_set_usb_adc(struct msi3101_state *s)
s->convert_stream = msi3101_convert_stream_336;
reg7 = 0x00008507;
break;
- case V4L2_PIX_FMT_SDR_S14:
+ case V4L2_SDR_FMT_CS14LE:
s->convert_stream = msi3101_convert_stream_252;
reg7 = 0x00009407;
break;
@@ -1115,7 +1118,7 @@ static int msi3101_enum_fmt_sdr_cap(struct file *file, void *priv,
struct msi3101_state *s = video_drvdata(file);
dev_dbg(&s->udev->dev, "%s: index=%d\n", __func__, f->index);
- if (f->index >= NUM_FORMATS)
+ if (f->index >= s->num_formats)
return -EINVAL;
strlcpy(f->description, formats[f->index].name, sizeof(f->description));
@@ -1131,8 +1134,9 @@ static int msi3101_g_fmt_sdr_cap(struct file *file, void *priv,
dev_dbg(&s->udev->dev, "%s: pixelformat fourcc %4.4s\n", __func__,
(char *)&s->pixelformat);
- memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
f->fmt.sdr.pixelformat = s->pixelformat;
+ f->fmt.sdr.buffersize = s->buffersize;
+ memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
return 0;
}
@@ -1150,15 +1154,19 @@ static int msi3101_s_fmt_sdr_cap(struct file *file, void *priv,
return -EBUSY;
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
+ for (i = 0; i < s->num_formats; i++) {
if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
- s->pixelformat = f->fmt.sdr.pixelformat;
+ s->pixelformat = formats[i].pixelformat;
+ s->buffersize = formats[i].buffersize;
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
}
}
- f->fmt.sdr.pixelformat = formats[0].pixelformat;
s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1172,12 +1180,15 @@ static int msi3101_try_fmt_sdr_cap(struct file *file, void *priv,
(char *)&f->fmt.sdr.pixelformat);
memset(f->fmt.sdr.reserved, 0, sizeof(f->fmt.sdr.reserved));
- for (i = 0; i < NUM_FORMATS; i++) {
- if (formats[i].pixelformat == f->fmt.sdr.pixelformat)
+ for (i = 0; i < s->num_formats; i++) {
+ if (formats[i].pixelformat == f->fmt.sdr.pixelformat) {
+ f->fmt.sdr.buffersize = formats[i].buffersize;
return 0;
+ }
}
f->fmt.sdr.pixelformat = formats[0].pixelformat;
+ f->fmt.sdr.buffersize = formats[0].buffersize;
return 0;
}
@@ -1398,7 +1409,11 @@ static int msi3101_probe(struct usb_interface *intf,
INIT_LIST_HEAD(&s->queued_bufs);
s->udev = udev;
s->f_adc = bands[0].rangelow;
- s->pixelformat = V4L2_SDR_FMT_CU8;
+ s->pixelformat = formats[0].pixelformat;
+ s->buffersize = formats[0].buffersize;
+ s->num_formats = NUM_FORMATS;
+ if (msi3101_emulated_fmt == false)
+ s->num_formats -= 2;
/* Init videobuf2 queue structure */
s->vb_queue.type = V4L2_BUF_TYPE_SDR_CAPTURE;
@@ -1418,7 +1433,6 @@ static int msi3101_probe(struct usb_interface *intf,
s->vdev = msi3101_template;
s->vdev.queue = &s->vb_queue;
s->vdev.queue->lock = &s->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &s->vdev.flags);
video_set_drvdata(&s->vdev, s);
/* Register the v4l2_device structure */
@@ -1481,6 +1495,9 @@ static int msi3101_probe(struct usb_interface *intf,
}
dev_info(&s->udev->dev, "Registered as %s\n",
video_device_node_name(&s->vdev));
+ dev_notice(&s->udev->dev,
+ "%s: SDR API is still slightly experimental and functionality changes may follow\n",
+ KBUILD_MODNAME);
return 0;
diff --git a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index 7c280f35eea9..1b158f1167ed 100644
--- a/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
+++ b/drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
@@ -951,15 +951,9 @@ static long pvr2_v4l2_ioctl(struct file *file,
if (ret < 0) {
if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%ld", ret);
- } else {
- if (pvrusb2_debug & PVR2_TRACE_V4LIOCTL) {
- pvr2_trace(PVR2_TRACE_V4LIOCTL,
- "pvr2_v4l2_do_ioctl failure, ret=%ld"
- " command was:", ret);
- v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw),
- cmd);
- }
+ "pvr2_v4l2_do_ioctl failure, ret=%ld"
+ " command was:", ret);
+ v4l_printk_ioctl(pvr2_hdw_get_driver_name(hdw), cmd);
}
} else {
pvr2_trace(PVR2_TRACE_V4LIOCTL,
diff --git a/drivers/media/usb/pwc/pwc-if.c b/drivers/media/usb/pwc/pwc-if.c
index a73b0bced96f..15b754da4a2c 100644
--- a/drivers/media/usb/pwc/pwc-if.c
+++ b/drivers/media/usb/pwc/pwc-if.c
@@ -1013,7 +1013,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
strcpy(pdev->vdev.name, name);
pdev->vdev.queue = &pdev->vb_queue;
pdev->vdev.queue->lock = &pdev->vb_queue_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &pdev->vdev.flags);
video_set_drvdata(&pdev->vdev, pdev);
pdev->release = le16_to_cpu(udev->descriptor.bcdDevice);
diff --git a/drivers/media/usb/s2255/s2255drv.c b/drivers/media/usb/s2255/s2255drv.c
index a44466bc7b86..2c901861034a 100644
--- a/drivers/media/usb/s2255/s2255drv.c
+++ b/drivers/media/usb/s2255/s2255drv.c
@@ -1676,7 +1676,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
vc->vdev.ctrl_handler = &vc->hdl;
vc->vdev.lock = &dev->lock;
vc->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &vc->vdev.flags);
video_set_drvdata(&vc->vdev, vc);
if (video_nr == -1)
ret = video_register_device(&vc->vdev,
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
index 5461341a31cb..233054311a62 100644
--- a/drivers/media/usb/stk1160/stk1160-v4l.c
+++ b/drivers/media/usb/stk1160/stk1160-v4l.c
@@ -671,7 +671,6 @@ int stk1160_video_register(struct stk1160 *dev)
/* This will be used to set video_device parent */
dev->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
/* NTSC is default */
dev->norm = V4L2_STD_NTSC_M;
diff --git a/drivers/media/usb/stkwebcam/stk-webcam.c b/drivers/media/usb/stkwebcam/stk-webcam.c
index be77482c3070..3588dc38db87 100644
--- a/drivers/media/usb/stkwebcam/stk-webcam.c
+++ b/drivers/media/usb/stkwebcam/stk-webcam.c
@@ -923,7 +923,6 @@ static int stk_vidioc_g_fmt_vid_cap(struct file *filp,
pix_format->bytesperline = 2 * pix_format->width;
pix_format->sizeimage = pix_format->bytesperline
* pix_format->height;
- pix_format->priv = 0;
return 0;
}
@@ -967,7 +966,6 @@ static int stk_try_fmt_vid_cap(struct file *filp,
fmtd->fmt.pix.bytesperline = 2 * fmtd->fmt.pix.width;
fmtd->fmt.pix.sizeimage = fmtd->fmt.pix.bytesperline
* fmtd->fmt.pix.height;
- fmtd->fmt.pix.priv = 0;
return 0;
}
@@ -1266,7 +1264,6 @@ static int stk_register_video_device(struct stk_camera *dev)
dev->vdev.lock = &dev->lock;
dev->vdev.debug = debug;
dev->vdev.v4l2_dev = &dev->v4l2_dev;
- set_bit(V4L2_FL_USE_FH_PRIO, &dev->vdev.flags);
video_set_drvdata(&dev->vdev, dev);
err = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
if (err)
diff --git a/drivers/media/usb/tlg2300/pd-main.c b/drivers/media/usb/tlg2300/pd-main.c
index 3316caa4733b..b31f4791b8ff 100644
--- a/drivers/media/usb/tlg2300/pd-main.c
+++ b/drivers/media/usb/tlg2300/pd-main.c
@@ -476,6 +476,8 @@ err_audio:
err_video:
v4l2_device_unregister(&pd->v4l2_dev);
err_v4l2:
+ usb_put_intf(pd->interface);
+ usb_put_dev(pd->udev);
kfree(pd);
return ret;
}
diff --git a/drivers/media/usb/tlg2300/pd-radio.c b/drivers/media/usb/tlg2300/pd-radio.c
index ea6070ba835e..b391194a840c 100644
--- a/drivers/media/usb/tlg2300/pd-radio.c
+++ b/drivers/media/usb/tlg2300/pd-radio.c
@@ -327,7 +327,6 @@ int poseidon_fm_init(struct poseidon *p)
}
vfd->v4l2_dev = &p->v4l2_dev;
vfd->ctrl_handler = hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
video_set_drvdata(vfd, p);
return video_register_device(vfd, VFL_TYPE_RADIO, -1);
}
diff --git a/drivers/media/usb/tlg2300/pd-video.c b/drivers/media/usb/tlg2300/pd-video.c
index 8df668d06552..8cd7f02fcf9f 100644
--- a/drivers/media/usb/tlg2300/pd-video.c
+++ b/drivers/media/usb/tlg2300/pd-video.c
@@ -1321,7 +1321,6 @@ static void init_video_context(struct running_context *context)
.bytesperline = 720 * 2,
.sizeimage = 720 * 576 * 2,
.colorspace = V4L2_COLORSPACE_SMPTE170M,
- .priv = 0
};
}
diff --git a/drivers/media/usb/tm6000/tm6000-video.c b/drivers/media/usb/tm6000/tm6000-video.c
index e6b3d5d83d43..793577fc4633 100644
--- a/drivers/media/usb/tm6000/tm6000-video.c
+++ b/drivers/media/usb/tm6000/tm6000-video.c
@@ -918,7 +918,6 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
(f->fmt.pix.width * fh->fmt->depth) >> 3;
f->fmt.pix.sizeimage =
f->fmt.pix.height * f->fmt.pix.bytesperline;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -959,7 +958,6 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.width &= ~0x01;
f->fmt.pix.field = field;
- f->fmt.pix.priv = 0;
f->fmt.pix.bytesperline =
(f->fmt.pix.width * fmt->depth) >> 3;
@@ -1626,7 +1624,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
vfd->release = video_device_release;
vfd->debug = tm6000_debug;
vfd->lock = &dev->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
diff --git a/drivers/media/usb/usbtv/usbtv-core.c b/drivers/media/usb/usbtv/usbtv-core.c
index 2f87ddfa469f..473fab81b602 100644
--- a/drivers/media/usb/usbtv/usbtv-core.c
+++ b/drivers/media/usb/usbtv/usbtv-core.c
@@ -91,6 +91,8 @@ static int usbtv_probe(struct usb_interface *intf,
return 0;
usbtv_video_fail:
+ usb_set_intfdata(intf, NULL);
+ usb_put_dev(usbtv->udev);
kfree(usbtv);
return ret;
diff --git a/drivers/media/usb/usbtv/usbtv-video.c b/drivers/media/usb/usbtv/usbtv-video.c
index 2967e808408b..030c5854b4b3 100644
--- a/drivers/media/usb/usbtv/usbtv-video.c
+++ b/drivers/media/usb/usbtv/usbtv-video.c
@@ -701,7 +701,6 @@ int usbtv_video_init(struct usbtv *usbtv)
usbtv->vdev.tvnorms = USBTV_TV_STD;
usbtv->vdev.queue = &usbtv->vb2q;
usbtv->vdev.lock = &usbtv->v4l2_lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &usbtv->vdev.flags);
video_set_drvdata(&usbtv->vdev, usbtv);
ret = video_register_device(&usbtv->vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
diff --git a/drivers/media/usb/usbvision/usbvision-core.c b/drivers/media/usb/usbvision/usbvision-core.c
index 816b1cffab7d..302aa07c458f 100644
--- a/drivers/media/usb/usbvision/usbvision-core.c
+++ b/drivers/media/usb/usbvision/usbvision-core.c
@@ -1463,8 +1463,6 @@ static int usbvision_write_reg_irq(struct usb_usbvision *usbvision, int address,
static int usbvision_init_compression(struct usb_usbvision *usbvision)
{
- int err_code = 0;
-
usbvision->last_isoc_frame_num = -1;
usbvision->isoc_data_count = 0;
usbvision->isoc_packet_count = 0;
@@ -1475,7 +1473,7 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision)
usbvision->request_intra = 1;
usbvision->isoc_measure_bandwidth_count = 0;
- return err_code;
+ return 0;
}
/* this function measures the used bandwidth since last call
@@ -1484,11 +1482,9 @@ static int usbvision_init_compression(struct usb_usbvision *usbvision)
*/
static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
{
- int err_code = 0;
-
if (usbvision->isoc_measure_bandwidth_count < 2) { /* this gives an average bandwidth of 3 frames */
usbvision->isoc_measure_bandwidth_count++;
- return err_code;
+ return 0;
}
if ((usbvision->isoc_packet_size > 0) && (usbvision->isoc_packet_count > 0)) {
usbvision->used_bandwidth = usbvision->isoc_data_count /
@@ -1499,7 +1495,7 @@ static int usbvision_measure_bandwidth(struct usb_usbvision *usbvision)
usbvision->isoc_data_count = 0;
usbvision->isoc_packet_count = 0;
usbvision->isoc_skip_count = 0;
- return err_code;
+ return 0;
}
static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
@@ -1546,26 +1542,24 @@ static int usbvision_adjust_compression(struct usb_usbvision *usbvision)
static int usbvision_request_intra(struct usb_usbvision *usbvision)
{
- int err_code = 0;
unsigned char buffer[1];
PDEBUG(DBG_IRQ, "");
usbvision->request_intra = 1;
buffer[0] = 1;
usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
- return err_code;
+ return 0;
}
static int usbvision_unrequest_intra(struct usb_usbvision *usbvision)
{
- int err_code = 0;
unsigned char buffer[1];
PDEBUG(DBG_IRQ, "");
usbvision->request_intra = 0;
buffer[0] = 0;
usbvision_write_reg_irq(usbvision, USBVISION_FORCE_INTRA, buffer, 1);
- return err_code;
+ return 0;
}
/*******************************
diff --git a/drivers/media/usb/uvc/uvc_driver.c b/drivers/media/usb/uvc/uvc_driver.c
index ad47c5cb539a..f8135f4e3b52 100644
--- a/drivers/media/usb/uvc/uvc_driver.c
+++ b/drivers/media/usb/uvc/uvc_driver.c
@@ -1746,7 +1746,6 @@ static int uvc_register_video(struct uvc_device *dev,
vdev->fops = &uvc_fops;
vdev->release = uvc_release;
vdev->prio = &stream->chain->prio;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
vdev->vfl_dir = VFL_DIR_TX;
strlcpy(vdev->name, dev->name, sizeof vdev->name);
diff --git a/drivers/media/usb/zr364xx/zr364xx.c b/drivers/media/usb/zr364xx/zr364xx.c
index 74d56df3347f..5c006277b8b1 100644
--- a/drivers/media/usb/zr364xx/zr364xx.c
+++ b/drivers/media/usb/zr364xx/zr364xx.c
@@ -806,7 +806,6 @@ static int zr364xx_vidioc_try_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
DBG("%s: V4L2_PIX_FMT_%s (%d) ok!\n", __func__,
decode_fourcc(f->fmt.pix.pixelformat, pixelformat_name),
f->fmt.pix.field);
@@ -829,7 +828,6 @@ static int zr364xx_vidioc_g_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
return 0;
}
@@ -866,7 +864,6 @@ static int zr364xx_vidioc_s_fmt_vid_cap(struct file *file, void *priv,
f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
f->fmt.pix.colorspace = V4L2_COLORSPACE_JPEG;
- f->fmt.pix.priv = 0;
cam->vb_vidq.field = f->fmt.pix.field;
if (f->fmt.pix.width == 160 && f->fmt.pix.height == 120)
@@ -1456,7 +1453,6 @@ static int zr364xx_probe(struct usb_interface *intf,
cam->vdev.lock = &cam->lock;
cam->vdev.v4l2_dev = &cam->v4l2_dev;
cam->vdev.ctrl_handler = &cam->ctrl_handler;
- set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
video_set_drvdata(&cam->vdev, cam);
if (debug)
cam->vdev.debug = V4L2_DEBUG_IOCTL | V4L2_DEBUG_IOCTL_ARG;
diff --git a/drivers/media/v4l2-core/v4l2-common.c b/drivers/media/v4l2-core/v4l2-common.c
index 433d6d77942e..ccaa38f65cf1 100644
--- a/drivers/media/v4l2-core/v4l2-common.c
+++ b/drivers/media/v4l2-core/v4l2-common.c
@@ -111,9 +111,13 @@ int v4l2_ctrl_check(struct v4l2_ext_control *ctrl, struct v4l2_queryctrl *qctrl,
EXPORT_SYMBOL(v4l2_ctrl_check);
/* Fill in a struct v4l2_queryctrl */
-int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 min, s32 max, s32 step, s32 def)
+int v4l2_ctrl_query_fill(struct v4l2_queryctrl *qctrl, s32 _min, s32 _max, s32 _step, s32 _def)
{
const char *name;
+ s64 min = _min;
+ s64 max = _max;
+ u64 step = _step;
+ s64 def = _def;
v4l2_ctrl_fill(qctrl->id, &name, &qctrl->type,
&min, &max, &step, &def, &qctrl->flags);
diff --git a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 7e2411c36419..cca6c2f76b3a 100644
--- a/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
+++ b/drivers/media/v4l2-core/v4l2-compat-ioctl32.c
@@ -540,7 +540,16 @@ struct v4l2_framebuffer32 {
__u32 capability;
__u32 flags;
compat_caddr_t base;
- struct v4l2_pix_format fmt;
+ struct {
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ __u32 field;
+ __u32 bytesperline;
+ __u32 sizeimage;
+ __u32 colorspace;
+ __u32 priv;
+ } fmt;
};
static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_framebuffer32 __user *up)
@@ -550,10 +559,10 @@ static int get_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_framebuffer32)) ||
get_user(tmp, &up->base) ||
get_user(kp->capability, &up->capability) ||
- get_user(kp->flags, &up->flags))
+ get_user(kp->flags, &up->flags) ||
+ copy_from_user(&kp->fmt, &up->fmt, sizeof(up->fmt)))
return -EFAULT;
kp->base = compat_ptr(tmp);
- get_v4l2_pix_format(&kp->fmt, &up->fmt);
return 0;
}
@@ -564,9 +573,9 @@ static int put_v4l2_framebuffer32(struct v4l2_framebuffer *kp, struct v4l2_frame
if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_framebuffer32)) ||
put_user(tmp, &up->base) ||
put_user(kp->capability, &up->capability) ||
- put_user(kp->flags, &up->flags))
+ put_user(kp->flags, &up->flags) ||
+ copy_to_user(&up->fmt, &kp->fmt, sizeof(up->fmt)))
return -EFAULT;
- put_v4l2_pix_format(&kp->fmt, &up->fmt);
return 0;
}
diff --git a/drivers/media/v4l2-core/v4l2-ctrls.c b/drivers/media/v4l2-core/v4l2-ctrls.c
index 55c683254102..004e7e82e1e0 100644
--- a/drivers/media/v4l2-core/v4l2-ctrls.c
+++ b/drivers/media/v4l2-core/v4l2-ctrls.c
@@ -462,6 +462,13 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
"RGB full range (0-255)",
NULL,
};
+ static const char * const detect_md_mode[] = {
+ "Disabled",
+ "Global",
+ "Threshold Grid",
+ "Region Grid",
+ NULL,
+ };
switch (id) {
@@ -553,6 +560,8 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
case V4L2_CID_DV_TX_RGB_RANGE:
case V4L2_CID_DV_RX_RGB_RANGE:
return dv_rgb_range;
+ case V4L2_CID_DETECT_MD_MODE:
+ return detect_md_mode;
default:
return NULL;
@@ -592,7 +601,7 @@ const char *v4l2_ctrl_get_name(u32 id)
{
switch (id) {
/* USER controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_USER_CLASS: return "User Controls";
case V4L2_CID_BRIGHTNESS: return "Brightness";
case V4L2_CID_CONTRAST: return "Contrast";
@@ -754,7 +763,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_MPEG_VIDEO_VPX_PROFILE: return "VPX Profile";
/* CAMERA controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_CAMERA_CLASS: return "Camera Controls";
case V4L2_CID_EXPOSURE_AUTO: return "Auto Exposure";
case V4L2_CID_EXPOSURE_ABSOLUTE: return "Exposure Time, Absolute";
@@ -788,8 +797,8 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_AUTO_FOCUS_STATUS: return "Auto Focus, Status";
case V4L2_CID_AUTO_FOCUS_RANGE: return "Auto Focus, Range";
- /* FM Radio Modulator control */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* FM Radio Modulator controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_FM_TX_CLASS: return "FM Radio Modulator Controls";
case V4L2_CID_RDS_TX_DEVIATION: return "RDS Signal Deviation";
case V4L2_CID_RDS_TX_PI: return "RDS Program ID";
@@ -812,6 +821,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_TUNE_ANTENNA_CAPACITOR: return "Tune Antenna Capacitor";
/* Flash controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_FLASH_CLASS: return "Flash Controls";
case V4L2_CID_FLASH_LED_MODE: return "LED Mode";
case V4L2_CID_FLASH_STROBE_SOURCE: return "Strobe Source";
@@ -827,7 +837,7 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_FLASH_READY: return "Ready to Strobe";
/* JPEG encoder controls */
- /* Keep the order of the 'case's the same as in videodev2.h! */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_JPEG_CLASS: return "JPEG Compression Controls";
case V4L2_CID_JPEG_CHROMA_SUBSAMPLING: return "Chroma Subsampling";
case V4L2_CID_JPEG_RESTART_INTERVAL: return "Restart Interval";
@@ -835,18 +845,21 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_JPEG_ACTIVE_MARKER: return "Active Markers";
/* Image source controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_IMAGE_SOURCE_CLASS: return "Image Source Controls";
case V4L2_CID_VBLANK: return "Vertical Blanking";
case V4L2_CID_HBLANK: return "Horizontal Blanking";
case V4L2_CID_ANALOGUE_GAIN: return "Analogue Gain";
/* Image processing controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_IMAGE_PROC_CLASS: return "Image Processing Controls";
case V4L2_CID_LINK_FREQ: return "Link Frequency";
case V4L2_CID_PIXEL_RATE: return "Pixel Rate";
case V4L2_CID_TEST_PATTERN: return "Test Pattern";
/* DV controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
case V4L2_CID_DV_CLASS: return "Digital Video Controls";
case V4L2_CID_DV_TX_HOTPLUG: return "Hotplug Present";
case V4L2_CID_DV_TX_RXSENSE: return "RxSense Present";
@@ -870,6 +883,15 @@ const char *v4l2_ctrl_get_name(u32 id)
case V4L2_CID_RF_TUNER_BANDWIDTH_AUTO: return "Bandwidth, Auto";
case V4L2_CID_RF_TUNER_BANDWIDTH: return "Bandwidth";
case V4L2_CID_RF_TUNER_PLL_LOCK: return "PLL Lock";
+
+ /* Detection controls */
+ /* Keep the order of the 'case's the same as in v4l2-controls.h! */
+ case V4L2_CID_DETECT_CLASS: return "Detection Controls";
+ case V4L2_CID_DETECT_MD_MODE: return "Motion Detection Mode";
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD: return "MD Global Threshold";
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID: return "MD Threshold Grid";
+ case V4L2_CID_DETECT_MD_REGION_GRID: return "MD Region Grid";
+
default:
return NULL;
}
@@ -877,7 +899,7 @@ const char *v4l2_ctrl_get_name(u32 id)
EXPORT_SYMBOL(v4l2_ctrl_get_name);
void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
- s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags)
+ s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags)
{
*name = v4l2_ctrl_get_name(id);
*flags = 0;
@@ -988,6 +1010,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_TEST_PATTERN:
case V4L2_CID_TUNE_DEEMPHASIS:
case V4L2_CID_MPEG_VIDEO_VPX_GOLDEN_FRAME_SEL:
+ case V4L2_CID_DETECT_MD_MODE:
*type = V4L2_CTRL_TYPE_MENU;
break;
case V4L2_CID_LINK_FREQ:
@@ -1014,6 +1037,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_DV_CLASS:
case V4L2_CID_FM_RX_CLASS:
case V4L2_CID_RF_TUNER_CLASS:
+ case V4L2_CID_DETECT_CLASS:
*type = V4L2_CTRL_TYPE_CTRL_CLASS;
/* You can neither read not write these */
*flags |= V4L2_CTRL_FLAG_READ_ONLY | V4L2_CTRL_FLAG_WRITE_ONLY;
@@ -1041,14 +1065,29 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
*type = V4L2_CTRL_TYPE_INTEGER;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
break;
- case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
case V4L2_CID_MPEG_VIDEO_DEC_PTS:
- *flags |= V4L2_CTRL_FLAG_VOLATILE;
- /* Fall through */
+ *type = V4L2_CTRL_TYPE_INTEGER64;
+ *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+ *min = *def = 0;
+ *max = 0x1ffffffffLL;
+ *step = 1;
+ break;
+ case V4L2_CID_MPEG_VIDEO_DEC_FRAME:
+ *type = V4L2_CTRL_TYPE_INTEGER64;
+ *flags |= V4L2_CTRL_FLAG_VOLATILE | V4L2_CTRL_FLAG_READ_ONLY;
+ *min = *def = 0;
+ *max = 0x7fffffffffffffffLL;
+ *step = 1;
+ break;
case V4L2_CID_PIXEL_RATE:
*type = V4L2_CTRL_TYPE_INTEGER64;
*flags |= V4L2_CTRL_FLAG_READ_ONLY;
- *min = *max = *step = *def = 0;
+ break;
+ case V4L2_CID_DETECT_MD_REGION_GRID:
+ *type = V4L2_CTRL_TYPE_U8;
+ break;
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+ *type = V4L2_CTRL_TYPE_U16;
break;
default:
*type = V4L2_CTRL_TYPE_INTEGER;
@@ -1090,6 +1129,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
case V4L2_CID_RF_TUNER_MIXER_GAIN:
case V4L2_CID_RF_TUNER_IF_GAIN:
case V4L2_CID_RF_TUNER_BANDWIDTH:
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
*flags |= V4L2_CTRL_FLAG_SLIDER;
break;
case V4L2_CID_PAN_RELATIVE:
@@ -1115,20 +1155,6 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
}
EXPORT_SYMBOL(v4l2_ctrl_fill);
-/* Helper function to determine whether the control type is compatible with
- VIDIOC_G/S_CTRL. */
-static bool type_is_int(const struct v4l2_ctrl *ctrl)
-{
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER64:
- case V4L2_CTRL_TYPE_STRING:
- /* Nope, these need v4l2_ext_control */
- return false;
- default:
- return true;
- }
-}
-
static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 changes)
{
memset(ev->reserved, 0, sizeof(ev->reserved));
@@ -1137,10 +1163,10 @@ static void fill_event(struct v4l2_event *ev, struct v4l2_ctrl *ctrl, u32 change
ev->u.ctrl.changes = changes;
ev->u.ctrl.type = ctrl->type;
ev->u.ctrl.flags = ctrl->flags;
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+ if (ctrl->is_ptr)
ev->u.ctrl.value64 = 0;
else
- ev->u.ctrl.value64 = ctrl->cur.val64;
+ ev->u.ctrl.value64 = *ctrl->p_cur.p_s64;
ev->u.ctrl.minimum = ctrl->minimum;
ev->u.ctrl.maximum = ctrl->maximum;
if (ctrl->type == V4L2_CTRL_TYPE_MENU
@@ -1166,42 +1192,273 @@ static void send_event(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 changes)
v4l2_event_queue_fh(sev->fh, &ev);
}
-/* Helper function: copy the current control value back to the caller */
-static int cur_to_user(struct v4l2_ext_control *c,
- struct v4l2_ctrl *ctrl)
+static bool std_equal(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr1,
+ union v4l2_ctrl_ptr ptr2)
+{
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_BUTTON:
+ return false;
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ /* strings are always 0-terminated */
+ return !strcmp(ptr1.p_char + idx, ptr2.p_char + idx);
+ case V4L2_CTRL_TYPE_INTEGER64:
+ return ptr1.p_s64[idx] == ptr2.p_s64[idx];
+ case V4L2_CTRL_TYPE_U8:
+ return ptr1.p_u8[idx] == ptr2.p_u8[idx];
+ case V4L2_CTRL_TYPE_U16:
+ return ptr1.p_u16[idx] == ptr2.p_u16[idx];
+ default:
+ if (ctrl->is_int)
+ return ptr1.p_s32[idx] == ptr2.p_s32[idx];
+ idx *= ctrl->elem_size;
+ return !memcmp(ptr1.p + idx, ptr2.p + idx, ctrl->elem_size);
+ }
+}
+
+static void std_init(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ memset(ptr.p_char + idx, ' ', ctrl->minimum);
+ ptr.p_char[idx + ctrl->minimum] = '\0';
+ break;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ ptr.p_s64[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ ptr.p_s32[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ ptr.p_u8[idx] = ctrl->default_value;
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ ptr.p_u16[idx] = ctrl->default_value;
+ break;
+ default:
+ idx *= ctrl->elem_size;
+ memset(ptr.p + idx, 0, ctrl->elem_size);
+ break;
+ }
+}
+
+static void std_log(const struct v4l2_ctrl *ctrl)
+{
+ union v4l2_ctrl_ptr ptr = ctrl->p_cur;
+
+ if (ctrl->is_array) {
+ unsigned i;
+
+ for (i = 0; i < ctrl->nr_of_dims; i++)
+ pr_cont("[%u]", ctrl->dims[i]);
+ pr_cont(" ");
+ }
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ pr_cont("%d", *ptr.p_s32);
+ break;
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ pr_cont("%s", *ptr.p_s32 ? "true" : "false");
+ break;
+ case V4L2_CTRL_TYPE_MENU:
+ pr_cont("%s", ctrl->qmenu[*ptr.p_s32]);
+ break;
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ pr_cont("%lld", ctrl->qmenu_int[*ptr.p_s32]);
+ break;
+ case V4L2_CTRL_TYPE_BITMASK:
+ pr_cont("0x%08x", *ptr.p_s32);
+ break;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ pr_cont("%lld", *ptr.p_s64);
+ break;
+ case V4L2_CTRL_TYPE_STRING:
+ pr_cont("%s", ptr.p_char);
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ pr_cont("%u", (unsigned)*ptr.p_u8);
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ pr_cont("%u", (unsigned)*ptr.p_u16);
+ break;
+ default:
+ pr_cont("unknown type %d", ctrl->type);
+ break;
+ }
+}
+
+/*
+ * Round towards the closest legal value. Be careful when we are
+ * close to the maximum range of the control type to prevent
+ * wrap-arounds.
+ */
+#define ROUND_TO_RANGE(val, offset_type, ctrl) \
+({ \
+ offset_type offset; \
+ if ((ctrl)->maximum >= 0 && \
+ val >= (ctrl)->maximum - ((ctrl)->step / 2)) \
+ val = (ctrl)->maximum; \
+ else \
+ val += (ctrl)->step / 2; \
+ val = clamp_t(typeof(val), val, \
+ (ctrl)->minimum, (ctrl)->maximum); \
+ offset = (val) - (ctrl)->minimum; \
+ offset = (ctrl)->step * (offset / (s32)(ctrl)->step); \
+ val = (ctrl)->minimum + offset; \
+ 0; \
+})
+
+/* Validate a new control */
+static int std_validate(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr)
+{
+ size_t len;
+ u64 offset;
+ s64 val;
+
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ return ROUND_TO_RANGE(ptr.p_s32[idx], u32, ctrl);
+ case V4L2_CTRL_TYPE_INTEGER64:
+ /*
+ * We can't use the ROUND_TO_RANGE define here due to
+ * the u64 divide that needs special care.
+ */
+ val = ptr.p_s64[idx];
+ if (ctrl->maximum >= 0 && val >= ctrl->maximum - ctrl->step / 2)
+ val = ctrl->maximum;
+ else
+ val += ctrl->step / 2;
+ val = clamp_t(s64, val, ctrl->minimum, ctrl->maximum);
+ offset = val - ctrl->minimum;
+ do_div(offset, ctrl->step);
+ ptr.p_s64[idx] = ctrl->minimum + offset * ctrl->step;
+ return 0;
+ case V4L2_CTRL_TYPE_U8:
+ return ROUND_TO_RANGE(ptr.p_u8[idx], u8, ctrl);
+ case V4L2_CTRL_TYPE_U16:
+ return ROUND_TO_RANGE(ptr.p_u16[idx], u16, ctrl);
+
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ ptr.p_s32[idx] = !!ptr.p_s32[idx];
+ return 0;
+
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ if (ptr.p_s32[idx] < ctrl->minimum || ptr.p_s32[idx] > ctrl->maximum)
+ return -ERANGE;
+ if (ctrl->menu_skip_mask & (1 << ptr.p_s32[idx]))
+ return -EINVAL;
+ if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
+ ctrl->qmenu[ptr.p_s32[idx]][0] == '\0')
+ return -EINVAL;
+ return 0;
+
+ case V4L2_CTRL_TYPE_BITMASK:
+ ptr.p_s32[idx] &= ctrl->maximum;
+ return 0;
+
+ case V4L2_CTRL_TYPE_BUTTON:
+ case V4L2_CTRL_TYPE_CTRL_CLASS:
+ ptr.p_s32[idx] = 0;
+ return 0;
+
+ case V4L2_CTRL_TYPE_STRING:
+ idx *= ctrl->elem_size;
+ len = strlen(ptr.p_char + idx);
+ if (len < ctrl->minimum)
+ return -ERANGE;
+ if ((len - (u32)ctrl->minimum) % (u32)ctrl->step)
+ return -ERANGE;
+ return 0;
+
+ default:
+ return -EINVAL;
+ }
+}
+
+static const struct v4l2_ctrl_type_ops std_type_ops = {
+ .equal = std_equal,
+ .init = std_init,
+ .log = std_log,
+ .validate = std_validate,
+};
+
+/* Helper function: copy the given control value back to the caller */
+static int ptr_to_user(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr ptr)
{
u32 len;
+ if (ctrl->is_ptr && !ctrl->is_string)
+ return copy_to_user(c->ptr, ptr.p, c->size) ?
+ -EFAULT : 0;
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_STRING:
- len = strlen(ctrl->cur.string);
+ len = strlen(ptr.p_char);
if (c->size < len + 1) {
- c->size = len + 1;
+ c->size = ctrl->elem_size;
return -ENOSPC;
}
- return copy_to_user(c->string, ctrl->cur.string,
- len + 1) ? -EFAULT : 0;
+ return copy_to_user(c->string, ptr.p_char, len + 1) ?
+ -EFAULT : 0;
case V4L2_CTRL_TYPE_INTEGER64:
- c->value64 = ctrl->cur.val64;
+ c->value64 = *ptr.p_s64;
break;
default:
- c->value = ctrl->cur.val;
+ c->value = *ptr.p_s32;
break;
}
return 0;
}
-/* Helper function: copy the caller-provider value as the new control value */
-static int user_to_new(struct v4l2_ext_control *c,
+/* Helper function: copy the current control value back to the caller */
+static int cur_to_user(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl)
+{
+ return ptr_to_user(c, ctrl, ctrl->p_cur);
+}
+
+/* Helper function: copy the new control value back to the caller */
+static int new_to_user(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
+ return ptr_to_user(c, ctrl, ctrl->p_new);
+}
+
+/* Helper function: copy the caller-provider value to the given control value */
+static int user_to_ptr(struct v4l2_ext_control *c,
+ struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr ptr)
+{
int ret;
u32 size;
ctrl->is_new = 1;
+ if (ctrl->is_ptr && !ctrl->is_string) {
+ unsigned idx;
+
+ ret = copy_from_user(ptr.p, c->ptr, c->size) ? -EFAULT : 0;
+ if (ret || !ctrl->is_array)
+ return ret;
+ for (idx = c->size / ctrl->elem_size; idx < ctrl->elems; idx++)
+ ctrl->type_ops->init(ctrl, idx, ptr);
+ return 0;
+ }
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER64:
- ctrl->val64 = c->value64;
+ *ptr.p_s64 = c->value64;
break;
case V4L2_CTRL_TYPE_STRING:
size = c->size;
@@ -1209,74 +1466,53 @@ static int user_to_new(struct v4l2_ext_control *c,
return -ERANGE;
if (size > ctrl->maximum + 1)
size = ctrl->maximum + 1;
- ret = copy_from_user(ctrl->string, c->string, size);
+ ret = copy_from_user(ptr.p_char, c->string, size) ? -EFAULT : 0;
if (!ret) {
- char last = ctrl->string[size - 1];
+ char last = ptr.p_char[size - 1];
- ctrl->string[size - 1] = 0;
+ ptr.p_char[size - 1] = 0;
/* If the string was longer than ctrl->maximum,
then return an error. */
- if (strlen(ctrl->string) == ctrl->maximum && last)
+ if (strlen(ptr.p_char) == ctrl->maximum && last)
return -ERANGE;
}
- return ret ? -EFAULT : 0;
+ return ret;
default:
- ctrl->val = c->value;
+ *ptr.p_s32 = c->value;
break;
}
return 0;
}
-/* Helper function: copy the new control value back to the caller */
-static int new_to_user(struct v4l2_ext_control *c,
+/* Helper function: copy the caller-provider value as the new control value */
+static int user_to_new(struct v4l2_ext_control *c,
struct v4l2_ctrl *ctrl)
{
- u32 len;
+ return user_to_ptr(c, ctrl, ctrl->p_new);
+}
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_STRING:
- len = strlen(ctrl->string);
- if (c->size < len + 1) {
- c->size = ctrl->maximum + 1;
- return -ENOSPC;
- }
- return copy_to_user(c->string, ctrl->string,
- len + 1) ? -EFAULT : 0;
- case V4L2_CTRL_TYPE_INTEGER64:
- c->value64 = ctrl->val64;
- break;
- default:
- c->value = ctrl->val;
- break;
- }
- return 0;
+/* Copy the one value to another. */
+static void ptr_to_ptr(struct v4l2_ctrl *ctrl,
+ union v4l2_ctrl_ptr from, union v4l2_ctrl_ptr to)
+{
+ if (ctrl == NULL)
+ return;
+ memcpy(to.p, from.p, ctrl->elems * ctrl->elem_size);
}
/* Copy the new value to the current value. */
static void new_to_cur(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, u32 ch_flags)
{
- bool changed = false;
+ bool changed;
if (ctrl == NULL)
return;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BUTTON:
- changed = true;
- break;
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- changed = strcmp(ctrl->string, ctrl->cur.string);
- strcpy(ctrl->cur.string, ctrl->string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- changed = ctrl->val64 != ctrl->cur.val64;
- ctrl->cur.val64 = ctrl->val64;
- break;
- default:
- changed = ctrl->val != ctrl->cur.val;
- ctrl->cur.val = ctrl->val;
- break;
- }
+
+ /* has_changed is set by cluster_changed */
+ changed = ctrl->has_changed;
+ if (changed)
+ ptr_to_ptr(ctrl, ctrl->p_new, ctrl->p_cur);
+
if (ch_flags & V4L2_EVENT_CTRL_CH_FLAGS) {
/* Note: CH_FLAGS is only set for auto clusters. */
ctrl->flags &=
@@ -1305,62 +1541,46 @@ static void cur_to_new(struct v4l2_ctrl *ctrl)
{
if (ctrl == NULL)
return;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- strcpy(ctrl->string, ctrl->cur.string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- ctrl->val64 = ctrl->cur.val64;
- break;
- default:
- ctrl->val = ctrl->cur.val;
- break;
- }
+ ptr_to_ptr(ctrl, ctrl->p_cur, ctrl->p_new);
}
/* Return non-zero if one or more of the controls in the cluster has a new
value that differs from the current value. */
static int cluster_changed(struct v4l2_ctrl *master)
{
- int diff = 0;
+ bool changed = false;
+ unsigned idx;
int i;
- for (i = 0; !diff && i < master->ncontrols; i++) {
+ for (i = 0; i < master->ncontrols; i++) {
struct v4l2_ctrl *ctrl = master->cluster[i];
+ bool ctrl_changed = false;
if (ctrl == NULL)
continue;
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_BUTTON:
- /* Button controls are always 'different' */
- return 1;
- case V4L2_CTRL_TYPE_STRING:
- /* strings are always 0-terminated */
- diff = strcmp(ctrl->string, ctrl->cur.string);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- diff = ctrl->val64 != ctrl->cur.val64;
- break;
- default:
- diff = ctrl->val != ctrl->cur.val;
- break;
- }
+ for (idx = 0; !ctrl_changed && idx < ctrl->elems; idx++)
+ ctrl_changed = !ctrl->type_ops->equal(ctrl, idx,
+ ctrl->p_cur, ctrl->p_new);
+ ctrl->has_changed = ctrl_changed;
+ changed |= ctrl->has_changed;
}
- return diff;
+ return changed;
}
/* Control range checking */
static int check_range(enum v4l2_ctrl_type type,
- s32 min, s32 max, u32 step, s32 def)
+ s64 min, s64 max, u64 step, s64 def)
{
switch (type) {
case V4L2_CTRL_TYPE_BOOLEAN:
if (step != 1 || max > 1 || min < 0)
return -ERANGE;
/* fall through */
+ case V4L2_CTRL_TYPE_U8:
+ case V4L2_CTRL_TYPE_U16:
case V4L2_CTRL_TYPE_INTEGER:
- if (step <= 0 || min > max || def < min || def > max)
+ case V4L2_CTRL_TYPE_INTEGER64:
+ if (step == 0 || min > max || def < min || def > max)
return -ERANGE;
return 0;
case V4L2_CTRL_TYPE_BITMASK:
@@ -1389,58 +1609,33 @@ static int check_range(enum v4l2_ctrl_type type,
static int validate_new(const struct v4l2_ctrl *ctrl,
struct v4l2_ext_control *c)
{
- size_t len;
- u32 offset;
- s32 val;
-
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- /* Round towards the closest legal value */
- val = c->value + ctrl->step / 2;
- val = clamp(val, ctrl->minimum, ctrl->maximum);
- offset = val - ctrl->minimum;
- offset = ctrl->step * (offset / ctrl->step);
- c->value = ctrl->minimum + offset;
- return 0;
+ union v4l2_ctrl_ptr ptr;
+ unsigned idx;
+ int err = 0;
- case V4L2_CTRL_TYPE_BOOLEAN:
- c->value = !!c->value;
- return 0;
-
- case V4L2_CTRL_TYPE_MENU:
- case V4L2_CTRL_TYPE_INTEGER_MENU:
- if (c->value < ctrl->minimum || c->value > ctrl->maximum)
- return -ERANGE;
- if (ctrl->menu_skip_mask & (1 << c->value))
- return -EINVAL;
- if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
- ctrl->qmenu[c->value][0] == '\0')
- return -EINVAL;
- return 0;
-
- case V4L2_CTRL_TYPE_BITMASK:
- c->value &= ctrl->maximum;
- return 0;
-
- case V4L2_CTRL_TYPE_BUTTON:
- case V4L2_CTRL_TYPE_CTRL_CLASS:
- c->value = 0;
- return 0;
-
- case V4L2_CTRL_TYPE_INTEGER64:
- return 0;
-
- case V4L2_CTRL_TYPE_STRING:
- len = strlen(c->string);
- if (len < ctrl->minimum)
- return -ERANGE;
- if ((len - ctrl->minimum) % ctrl->step)
- return -ERANGE;
- return 0;
+ if (!ctrl->is_ptr) {
+ switch (ctrl->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_BUTTON:
+ case V4L2_CTRL_TYPE_CTRL_CLASS:
+ ptr.p_s32 = &c->value;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
- default:
- return -EINVAL;
+ case V4L2_CTRL_TYPE_INTEGER64:
+ ptr.p_s64 = &c->value64;
+ return ctrl->type_ops->validate(ctrl, 0, ptr);
+ default:
+ break;
+ }
}
+ ptr.p = c->ptr;
+ for (idx = 0; !err && idx < c->size / ctrl->elem_size; idx++)
+ err = ctrl->type_ops->validate(ctrl, idx, ptr);
+ return err;
}
static inline u32 node2id(struct list_head *node)
@@ -1522,7 +1717,7 @@ static struct v4l2_ctrl_ref *find_private_ref(
VIDIOC_G/S_CTRL. */
if (V4L2_CTRL_ID2CLASS(ref->ctrl->id) == V4L2_CTRL_CLASS_USER &&
V4L2_CTRL_DRIVER_PRIV(ref->ctrl->id)) {
- if (!type_is_int(ref->ctrl))
+ if (!ref->ctrl->is_int)
continue;
if (id == 0)
return ref;
@@ -1592,8 +1787,12 @@ static int handler_new_ref(struct v4l2_ctrl_handler *hdl,
u32 class_ctrl = V4L2_CTRL_ID2CLASS(id) | 1;
int bucket = id % hdl->nr_of_buckets; /* which bucket to use */
- /* Automatically add the control class if it is not yet present. */
- if (id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
+ /*
+ * Automatically add the control class if it is not yet present and
+ * the new control is not a compound control.
+ */
+ if (ctrl->type < V4L2_CTRL_COMPOUND_TYPES &&
+ id != class_ctrl && find_ref_lock(hdl, class_ctrl) == NULL)
if (!v4l2_ctrl_new_std(hdl, NULL, class_ctrl, 0, 0, 0, 0))
return hdl->error;
@@ -1652,20 +1851,58 @@ unlock:
/* Add a new control */
static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
+ const struct v4l2_ctrl_type_ops *type_ops,
u32 id, const char *name, enum v4l2_ctrl_type type,
- s32 min, s32 max, u32 step, s32 def,
+ s64 min, s64 max, u64 step, s64 def,
+ const u32 dims[V4L2_CTRL_MAX_DIMS], u32 elem_size,
u32 flags, const char * const *qmenu,
const s64 *qmenu_int, void *priv)
{
struct v4l2_ctrl *ctrl;
- unsigned sz_extra = 0;
+ unsigned sz_extra;
+ unsigned nr_of_dims = 0;
+ unsigned elems = 1;
+ bool is_array;
+ unsigned tot_ctrl_size;
+ unsigned idx;
+ void *data;
int err;
if (hdl->error)
return NULL;
+ while (dims && dims[nr_of_dims]) {
+ elems *= dims[nr_of_dims];
+ nr_of_dims++;
+ if (nr_of_dims == V4L2_CTRL_MAX_DIMS)
+ break;
+ }
+ is_array = nr_of_dims > 0;
+
+ /* Prefill elem_size for all types handled by std_type_ops */
+ switch (type) {
+ case V4L2_CTRL_TYPE_INTEGER64:
+ elem_size = sizeof(s64);
+ break;
+ case V4L2_CTRL_TYPE_STRING:
+ elem_size = max + 1;
+ break;
+ case V4L2_CTRL_TYPE_U8:
+ elem_size = sizeof(u8);
+ break;
+ case V4L2_CTRL_TYPE_U16:
+ elem_size = sizeof(u16);
+ break;
+ default:
+ if (type < V4L2_CTRL_COMPOUND_TYPES)
+ elem_size = sizeof(s32);
+ break;
+ }
+ tot_ctrl_size = elem_size * elems;
+
/* Sanity checks */
- if (id == 0 || name == NULL || id >= V4L2_CID_PRIVATE_BASE ||
+ if (id == 0 || name == NULL || !elem_size ||
+ id >= V4L2_CID_PRIVATE_BASE ||
(type == V4L2_CTRL_TYPE_MENU && qmenu == NULL) ||
(type == V4L2_CTRL_TYPE_INTEGER_MENU && qmenu_int == NULL)) {
handler_set_err(hdl, -ERANGE);
@@ -1680,13 +1917,23 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -ERANGE);
return NULL;
}
+ if (is_array &&
+ (type == V4L2_CTRL_TYPE_BUTTON ||
+ type == V4L2_CTRL_TYPE_CTRL_CLASS)) {
+ handler_set_err(hdl, -EINVAL);
+ return NULL;
+ }
+ sz_extra = 0;
if (type == V4L2_CTRL_TYPE_BUTTON)
flags |= V4L2_CTRL_FLAG_WRITE_ONLY;
else if (type == V4L2_CTRL_TYPE_CTRL_CLASS)
flags |= V4L2_CTRL_FLAG_READ_ONLY;
- else if (type == V4L2_CTRL_TYPE_STRING)
- sz_extra += 2 * (max + 1);
+ else if (type == V4L2_CTRL_TYPE_INTEGER64 ||
+ type == V4L2_CTRL_TYPE_STRING ||
+ type >= V4L2_CTRL_COMPOUND_TYPES ||
+ is_array)
+ sz_extra += 2 * tot_ctrl_size;
ctrl = kzalloc(sizeof(*ctrl) + sz_extra, GFP_KERNEL);
if (ctrl == NULL) {
@@ -1698,6 +1945,7 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
INIT_LIST_HEAD(&ctrl->ev_subs);
ctrl->handler = hdl;
ctrl->ops = ops;
+ ctrl->type_ops = type_ops ? type_ops : &std_type_ops;
ctrl->id = id;
ctrl->name = name;
ctrl->type = type;
@@ -1705,19 +1953,36 @@ static struct v4l2_ctrl *v4l2_ctrl_new(struct v4l2_ctrl_handler *hdl,
ctrl->minimum = min;
ctrl->maximum = max;
ctrl->step = step;
+ ctrl->default_value = def;
+ ctrl->is_string = !is_array && type == V4L2_CTRL_TYPE_STRING;
+ ctrl->is_ptr = is_array || type >= V4L2_CTRL_COMPOUND_TYPES || ctrl->is_string;
+ ctrl->is_int = !ctrl->is_ptr && type != V4L2_CTRL_TYPE_INTEGER64;
+ ctrl->is_array = is_array;
+ ctrl->elems = elems;
+ ctrl->nr_of_dims = nr_of_dims;
+ if (nr_of_dims)
+ memcpy(ctrl->dims, dims, nr_of_dims * sizeof(dims[0]));
+ ctrl->elem_size = elem_size;
if (type == V4L2_CTRL_TYPE_MENU)
ctrl->qmenu = qmenu;
else if (type == V4L2_CTRL_TYPE_INTEGER_MENU)
ctrl->qmenu_int = qmenu_int;
ctrl->priv = priv;
- ctrl->cur.val = ctrl->val = ctrl->default_value = def;
+ ctrl->cur.val = ctrl->val = def;
+ data = &ctrl[1];
- if (ctrl->type == V4L2_CTRL_TYPE_STRING) {
- ctrl->cur.string = (char *)&ctrl[1] + sz_extra - (max + 1);
- ctrl->string = (char *)&ctrl[1] + sz_extra - 2 * (max + 1);
- if (ctrl->minimum)
- memset(ctrl->cur.string, ' ', ctrl->minimum);
+ if (!ctrl->is_int) {
+ ctrl->p_new.p = data;
+ ctrl->p_cur.p = data + tot_ctrl_size;
+ } else {
+ ctrl->p_new.p = &ctrl->val;
+ ctrl->p_cur.p = &ctrl->cur.val;
+ }
+ for (idx = 0; idx < elems; idx++) {
+ ctrl->type_ops->init(ctrl, idx, ctrl->p_cur);
+ ctrl->type_ops->init(ctrl, idx, ctrl->p_new);
}
+
if (handler_new_ref(hdl, ctrl)) {
kfree(ctrl);
return NULL;
@@ -1738,10 +2003,10 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
const s64 *qmenu_int = cfg->qmenu_int;
enum v4l2_ctrl_type type = cfg->type;
u32 flags = cfg->flags;
- s32 min = cfg->min;
- s32 max = cfg->max;
- u32 step = cfg->step;
- s32 def = cfg->def;
+ s64 min = cfg->min;
+ s64 max = cfg->max;
+ u64 step = cfg->step;
+ s64 def = cfg->def;
if (name == NULL)
v4l2_ctrl_fill(cfg->id, &name, &type, &min, &max, &step,
@@ -1761,10 +2026,11 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
return NULL;
}
- ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->id, name,
+ ctrl = v4l2_ctrl_new(hdl, cfg->ops, cfg->type_ops, cfg->id, name,
type, min, max,
- is_menu ? cfg->menu_skip_mask : step,
- def, flags, qmenu, qmenu_int, priv);
+ is_menu ? cfg->menu_skip_mask : step, def,
+ cfg->dims, cfg->elem_size,
+ flags, qmenu, qmenu_int, priv);
if (ctrl)
ctrl->is_private = cfg->is_private;
return ctrl;
@@ -1774,35 +2040,39 @@ EXPORT_SYMBOL(v4l2_ctrl_new_custom);
/* Helper function for standard non-menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 min, s32 max, u32 step, s32 def)
+ u32 id, s64 min, s64 max, u64 step, s64 def)
{
const char *name;
enum v4l2_ctrl_type type;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
- if (type == V4L2_CTRL_TYPE_MENU
- || type == V4L2_CTRL_TYPE_INTEGER_MENU) {
+ if (type == V4L2_CTRL_TYPE_MENU ||
+ type == V4L2_CTRL_TYPE_INTEGER_MENU ||
+ type >= V4L2_CTRL_COMPOUND_TYPES) {
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- min, max, step, def, flags, NULL, NULL, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ min, max, step, def, NULL, 0,
+ flags, NULL, NULL, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std);
/* Helper function for standard menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 mask, s32 def)
+ u32 id, u8 _max, u64 mask, u8 _def)
{
const char * const *qmenu = NULL;
const s64 *qmenu_int = NULL;
unsigned int qmenu_int_len = 0;
const char *name;
enum v4l2_ctrl_type type;
- s32 min;
- s32 step;
+ s64 min;
+ s64 max = _max;
+ s64 def = _def;
+ u64 step;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1816,21 +2086,24 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- 0, max, mask, def, flags, qmenu, qmenu_int, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, mask, def, NULL, 0,
+ flags, qmenu, qmenu_int, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_std_menu);
/* Helper function for standard menu controls with driver defined menu */
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
- const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
- s32 mask, s32 def, const char * const *qmenu)
+ const struct v4l2_ctrl_ops *ops, u32 id, u8 _max,
+ u64 mask, u8 _def, const char * const *qmenu)
{
enum v4l2_ctrl_type type;
const char *name;
u32 flags;
- s32 step;
- s32 min;
+ u64 step;
+ s64 min;
+ s64 max = _max;
+ s64 def = _def;
/* v4l2_ctrl_new_std_menu_items() should only be called for
* standard controls without a standard menu.
@@ -1845,7 +2118,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, mask, def, NULL, 0,
flags, qmenu, NULL, NULL);
}
@@ -1854,12 +2128,14 @@ EXPORT_SYMBOL(v4l2_ctrl_new_std_menu_items);
/* Helper function for standard integer menu controls */
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 def, const s64 *qmenu_int)
+ u32 id, u8 _max, u8 _def, const s64 *qmenu_int)
{
const char *name;
enum v4l2_ctrl_type type;
- s32 min;
- s32 step;
+ s64 min;
+ u64 step;
+ s64 max = _max;
+ s64 def = _def;
u32 flags;
v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
@@ -1867,8 +2143,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
handler_set_err(hdl, -EINVAL);
return NULL;
}
- return v4l2_ctrl_new(hdl, ops, id, name, type,
- 0, max, 0, def, flags, NULL, qmenu_int, NULL);
+ return v4l2_ctrl_new(hdl, ops, NULL, id, name, type,
+ 0, max, 0, def, NULL, 0,
+ flags, NULL, qmenu_int, NULL);
}
EXPORT_SYMBOL(v4l2_ctrl_new_int_menu);
@@ -2048,45 +2325,21 @@ static void log_ctrl(const struct v4l2_ctrl *ctrl,
if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
return;
- printk(KERN_INFO "%s%s%s: ", prefix, colon, ctrl->name);
+ pr_info("%s%s%s: ", prefix, colon, ctrl->name);
+
+ ctrl->type_ops->log(ctrl);
- switch (ctrl->type) {
- case V4L2_CTRL_TYPE_INTEGER:
- printk(KERN_CONT "%d", ctrl->cur.val);
- break;
- case V4L2_CTRL_TYPE_BOOLEAN:
- printk(KERN_CONT "%s", ctrl->cur.val ? "true" : "false");
- break;
- case V4L2_CTRL_TYPE_MENU:
- printk(KERN_CONT "%s", ctrl->qmenu[ctrl->cur.val]);
- break;
- case V4L2_CTRL_TYPE_INTEGER_MENU:
- printk(KERN_CONT "%lld", ctrl->qmenu_int[ctrl->cur.val]);
- break;
- case V4L2_CTRL_TYPE_BITMASK:
- printk(KERN_CONT "0x%08x", ctrl->cur.val);
- break;
- case V4L2_CTRL_TYPE_INTEGER64:
- printk(KERN_CONT "%lld", ctrl->cur.val64);
- break;
- case V4L2_CTRL_TYPE_STRING:
- printk(KERN_CONT "%s", ctrl->cur.string);
- break;
- default:
- printk(KERN_CONT "unknown type %d", ctrl->type);
- break;
- }
if (ctrl->flags & (V4L2_CTRL_FLAG_INACTIVE |
V4L2_CTRL_FLAG_GRABBED |
V4L2_CTRL_FLAG_VOLATILE)) {
if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
- printk(KERN_CONT " inactive");
+ pr_cont(" inactive");
if (ctrl->flags & V4L2_CTRL_FLAG_GRABBED)
- printk(KERN_CONT " grabbed");
+ pr_cont(" grabbed");
if (ctrl->flags & V4L2_CTRL_FLAG_VOLATILE)
- printk(KERN_CONT " volatile");
+ pr_cont(" volatile");
}
- printk(KERN_CONT "\n");
+ pr_cont("\n");
}
/* Log all controls owned by the handler */
@@ -2157,9 +2410,10 @@ int v4l2_ctrl_handler_setup(struct v4l2_ctrl_handler *hdl)
}
EXPORT_SYMBOL(v4l2_ctrl_handler_setup);
-/* Implement VIDIOC_QUERYCTRL */
-int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+/* Implement VIDIOC_QUERY_EXT_CTRL */
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc)
{
+ const unsigned next_flags = V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND;
u32 id = qc->id & V4L2_CTRL_ID_MASK;
struct v4l2_ctrl_ref *ref;
struct v4l2_ctrl *ctrl;
@@ -2172,7 +2426,20 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
/* Try to find it */
ref = find_ref(hdl, id);
- if ((qc->id & V4L2_CTRL_FLAG_NEXT_CTRL) && !list_empty(&hdl->ctrl_refs)) {
+ if ((qc->id & next_flags) && !list_empty(&hdl->ctrl_refs)) {
+ bool is_compound;
+ /* Match any control that is not hidden */
+ unsigned mask = 1;
+ bool match = false;
+
+ if ((qc->id & next_flags) == V4L2_CTRL_FLAG_NEXT_COMPOUND) {
+ /* Match any hidden control */
+ match = true;
+ } else if ((qc->id & next_flags) == next_flags) {
+ /* Match any control, compound or not */
+ mask = 0;
+ }
+
/* Find the next control with ID > qc->id */
/* Did we reach the end of the control list? */
@@ -2180,19 +2447,34 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
ref = NULL; /* Yes, so there is no next control */
} else if (ref) {
/* We found a control with the given ID, so just get
- the next one in the list. */
- ref = list_entry(ref->node.next, typeof(*ref), node);
+ the next valid one in the list. */
+ list_for_each_entry_continue(ref, &hdl->ctrl_refs, node) {
+ is_compound =
+ ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+ if (id < ref->ctrl->id &&
+ (is_compound & mask) == match)
+ break;
+ }
+ if (&ref->node == &hdl->ctrl_refs)
+ ref = NULL;
} else {
/* No control with the given ID exists, so start
searching for the next largest ID. We know there
is one, otherwise the first 'if' above would have
been true. */
- list_for_each_entry(ref, &hdl->ctrl_refs, node)
- if (id < ref->ctrl->id)
+ list_for_each_entry(ref, &hdl->ctrl_refs, node) {
+ is_compound =
+ ref->ctrl->type >= V4L2_CTRL_COMPOUND_TYPES;
+ if (id < ref->ctrl->id &&
+ (is_compound & mask) == match)
break;
+ }
+ if (&ref->node == &hdl->ctrl_refs)
+ ref = NULL;
}
}
mutex_unlock(hdl->lock);
+
if (!ref)
return -EINVAL;
@@ -2203,6 +2485,14 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
else
qc->id = ctrl->id;
strlcpy(qc->name, ctrl->name, sizeof(qc->name));
+ qc->flags = ctrl->flags;
+ qc->type = ctrl->type;
+ if (ctrl->is_ptr)
+ qc->flags |= V4L2_CTRL_FLAG_HAS_PAYLOAD;
+ qc->elem_size = ctrl->elem_size;
+ qc->elems = ctrl->elems;
+ qc->nr_of_dims = ctrl->nr_of_dims;
+ memcpy(qc->dims, ctrl->dims, qc->nr_of_dims * sizeof(qc->dims[0]));
qc->minimum = ctrl->minimum;
qc->maximum = ctrl->maximum;
qc->default_value = ctrl->default_value;
@@ -2211,15 +2501,50 @@ int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
qc->step = 1;
else
qc->step = ctrl->step;
- qc->flags = ctrl->flags;
- qc->type = ctrl->type;
+ return 0;
+}
+EXPORT_SYMBOL(v4l2_query_ext_ctrl);
+
+/* Implement VIDIOC_QUERYCTRL */
+int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc)
+{
+ struct v4l2_query_ext_ctrl qec = { qc->id };
+ int rc;
+
+ rc = v4l2_query_ext_ctrl(hdl, &qec);
+ if (rc)
+ return rc;
+
+ qc->id = qec.id;
+ qc->type = qec.type;
+ qc->flags = qec.flags;
+ strlcpy(qc->name, qec.name, sizeof(qc->name));
+ switch (qc->type) {
+ case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_BOOLEAN:
+ case V4L2_CTRL_TYPE_MENU:
+ case V4L2_CTRL_TYPE_INTEGER_MENU:
+ case V4L2_CTRL_TYPE_STRING:
+ case V4L2_CTRL_TYPE_BITMASK:
+ qc->minimum = qec.minimum;
+ qc->maximum = qec.maximum;
+ qc->step = qec.step;
+ qc->default_value = qec.default_value;
+ break;
+ default:
+ qc->minimum = 0;
+ qc->maximum = 0;
+ qc->step = 0;
+ qc->default_value = 0;
+ break;
+ }
return 0;
}
EXPORT_SYMBOL(v4l2_queryctrl);
int v4l2_subdev_queryctrl(struct v4l2_subdev *sd, struct v4l2_queryctrl *qc)
{
- if (qc->id & V4L2_CTRL_FLAG_NEXT_CTRL)
+ if (qc->id & (V4L2_CTRL_FLAG_NEXT_CTRL | V4L2_CTRL_FLAG_NEXT_COMPOUND))
return -EINVAL;
return v4l2_queryctrl(sd->ctrl_handler, qc);
}
@@ -2319,7 +2644,8 @@ EXPORT_SYMBOL(v4l2_subdev_querymenu);
Find the controls in the control array and do some basic checks. */
static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_controls *cs,
- struct v4l2_ctrl_helper *helpers)
+ struct v4l2_ctrl_helper *helpers,
+ bool get)
{
struct v4l2_ctrl_helper *h;
bool have_clusters = false;
@@ -2351,6 +2677,18 @@ static int prepare_ext_ctrls(struct v4l2_ctrl_handler *hdl,
have_clusters = true;
if (ctrl->cluster[0] != ctrl)
ref = find_ref_lock(hdl, ctrl->cluster[0]->id);
+ if (ctrl->is_ptr && !ctrl->is_string) {
+ unsigned tot_size = ctrl->elems * ctrl->elem_size;
+
+ if (c->size < tot_size) {
+ if (get) {
+ c->size = tot_size;
+ return -ENOSPC;
+ }
+ return -EFAULT;
+ }
+ c->size = tot_size;
+ }
/* Store the ref to the master control of the cluster */
h->mref = ref;
h->ctrl = ctrl;
@@ -2431,7 +2769,7 @@ int v4l2_g_ext_ctrls(struct v4l2_ctrl_handler *hdl, struct v4l2_ext_controls *cs
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
+ ret = prepare_ext_ctrls(hdl, cs, helpers, true);
cs->error_idx = cs->count;
for (i = 0; !ret && i < cs->count; i++)
@@ -2493,11 +2831,11 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
int ret = 0;
int i;
- /* String controls are not supported. The new_to_user() and
+ /* Compound controls are not supported. The new_to_user() and
* cur_to_user() calls below would need to be modified not to access
* userspace memory when called from get_ctrl().
*/
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+ if (!ctrl->is_int)
return -EINVAL;
if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
@@ -2523,7 +2861,7 @@ int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
struct v4l2_ext_control c;
int ret;
- if (ctrl == NULL || !type_is_int(ctrl))
+ if (ctrl == NULL || !ctrl->is_int)
return -EINVAL;
ret = get_ctrl(ctrl, &c);
control->value = c.value;
@@ -2542,7 +2880,7 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
struct v4l2_ext_control c;
/* It's a driver bug if this happens. */
- WARN_ON(!type_is_int(ctrl));
+ WARN_ON(!ctrl->is_int);
c.value = 0;
get_ctrl(ctrl, &c);
return c.value;
@@ -2554,7 +2892,7 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl)
struct v4l2_ext_control c;
/* It's a driver bug if this happens. */
- WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
c.value = 0;
get_ctrl(ctrl, &c);
return c.value;
@@ -2678,7 +3016,7 @@ static int try_set_ext_ctrls(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
if (!helpers)
return -ENOMEM;
}
- ret = prepare_ext_ctrls(hdl, cs, helpers);
+ ret = prepare_ext_ctrls(hdl, cs, helpers, false);
if (!ret)
ret = validate_ctrls(cs, helpers, set);
if (ret && set)
@@ -2783,11 +3121,11 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
struct v4l2_ctrl *master = ctrl->cluster[0];
int i;
- /* String controls are not supported. The user_to_new() and
+ /* Compound controls are not supported. The user_to_new() and
* cur_to_user() calls below would need to be modified not to access
* userspace memory when called from set_ctrl().
*/
- if (ctrl->type == V4L2_CTRL_TYPE_STRING)
+ if (ctrl->is_ptr)
return -EINVAL;
/* Reset the 'is_new' flags of the cluster */
@@ -2829,7 +3167,7 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
struct v4l2_ext_control c;
int ret;
- if (ctrl == NULL || !type_is_int(ctrl))
+ if (ctrl == NULL || !ctrl->is_int)
return -EINVAL;
if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
@@ -2848,27 +3186,41 @@ int v4l2_subdev_s_ctrl(struct v4l2_subdev *sd, struct v4l2_control *control)
}
EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
-int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
+int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
{
struct v4l2_ext_control c;
+ int rval;
+
+ lockdep_assert_held(ctrl->handler->lock);
/* It's a driver bug if this happens. */
- WARN_ON(!type_is_int(ctrl));
+ WARN_ON(!ctrl->is_int);
c.value = val;
- return set_ctrl_lock(NULL, ctrl, &c);
+ rval = set_ctrl(NULL, ctrl, &c, 0);
+ if (!rval)
+ cur_to_user(&c, ctrl);
+
+ return rval;
}
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl);
-int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
+int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
{
struct v4l2_ext_control c;
+ int rval;
+
+ lockdep_assert_held(ctrl->handler->lock);
/* It's a driver bug if this happens. */
- WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+ WARN_ON(ctrl->is_ptr || ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
c.value64 = val;
- return set_ctrl_lock(NULL, ctrl, &c);
+ rval = set_ctrl(NULL, ctrl, &c, 0);
+ if (!rval)
+ cur_to_user(&c, ctrl);
+
+ return rval;
}
-EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
+EXPORT_SYMBOL(__v4l2_ctrl_s_ctrl_int64);
void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void *priv)
{
@@ -2886,40 +3238,46 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void
}
EXPORT_SYMBOL(v4l2_ctrl_notify);
-int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
- s32 min, s32 max, u32 step, s32 def)
+int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
+ s64 min, s64 max, u64 step, s64 def)
{
- int ret = check_range(ctrl->type, min, max, step, def);
+ int ret;
struct v4l2_ext_control c;
+ lockdep_assert_held(ctrl->handler->lock);
+
switch (ctrl->type) {
case V4L2_CTRL_TYPE_INTEGER:
+ case V4L2_CTRL_TYPE_INTEGER64:
case V4L2_CTRL_TYPE_BOOLEAN:
case V4L2_CTRL_TYPE_MENU:
case V4L2_CTRL_TYPE_INTEGER_MENU:
case V4L2_CTRL_TYPE_BITMASK:
+ case V4L2_CTRL_TYPE_U8:
+ case V4L2_CTRL_TYPE_U16:
+ if (ctrl->is_array)
+ return -EINVAL;
+ ret = check_range(ctrl->type, min, max, step, def);
if (ret)
return ret;
break;
default:
return -EINVAL;
}
- v4l2_ctrl_lock(ctrl);
ctrl->minimum = min;
ctrl->maximum = max;
ctrl->step = step;
ctrl->default_value = def;
- c.value = ctrl->cur.val;
+ c.value = *ctrl->p_cur.p_s32;
if (validate_new(ctrl, &c))
c.value = def;
- if (c.value != ctrl->cur.val)
+ if (c.value != *ctrl->p_cur.p_s32)
ret = set_ctrl(NULL, ctrl, &c, V4L2_EVENT_CTRL_CH_RANGE);
else
send_event(NULL, ctrl, V4L2_EVENT_CTRL_CH_RANGE);
- v4l2_ctrl_unlock(ctrl);
return ret;
}
-EXPORT_SYMBOL(v4l2_ctrl_modify_range);
+EXPORT_SYMBOL(__v4l2_ctrl_modify_range);
static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
{
diff --git a/drivers/media/v4l2-core/v4l2-dev.c b/drivers/media/v4l2-core/v4l2-dev.c
index 634d863c05b4..33617c365acc 100644
--- a/drivers/media/v4l2-core/v4l2-dev.c
+++ b/drivers/media/v4l2-core/v4l2-dev.c
@@ -335,7 +335,7 @@ static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
return DEFAULT_POLLMASK;
if (video_is_registered(vdev))
res = vdev->fops->poll(filp, poll);
- if (vdev->debug)
+ if (vdev->debug > 2)
printk(KERN_DEBUG "%s: poll: %08x\n",
video_device_node_name(vdev), res);
return res;
@@ -563,20 +563,18 @@ static void determine_valid_ioctls(struct video_device *vdev)
/* vfl_type and vfl_dir independent ioctls */
SET_VALID_IOCTL(ops, VIDIOC_QUERYCAP, vidioc_querycap);
- if (ops->vidioc_g_priority ||
- test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ if (ops->vidioc_g_priority)
set_bit(_IOC_NR(VIDIOC_G_PRIORITY), valid_ioctls);
- if (ops->vidioc_s_priority ||
- test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
+ if (ops->vidioc_s_priority)
set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
- SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
- SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
/* Note: the control handler can also be passed through the filehandle,
and that can't be tested here. If the bit for these control ioctls
is set, then the ioctl is valid. But if it is 0, then it can still
be valid if the filehandle passed the control handler. */
if (vdev->ctrl_handler || ops->vidioc_queryctrl)
set_bit(_IOC_NR(VIDIOC_QUERYCTRL), valid_ioctls);
+ if (vdev->ctrl_handler || ops->vidioc_query_ext_ctrl)
+ set_bit(_IOC_NR(VIDIOC_QUERY_EXT_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_g_ctrl || ops->vidioc_g_ext_ctrls)
set_bit(_IOC_NR(VIDIOC_G_CTRL), valid_ioctls);
if (vdev->ctrl_handler || ops->vidioc_s_ctrl || ops->vidioc_s_ext_ctrls)
@@ -684,6 +682,8 @@ static void determine_valid_ioctls(struct video_device *vdev)
SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
SET_VALID_IOCTL(ops, VIDIOC_CREATE_BUFS, vidioc_create_bufs);
SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
+ SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
}
if (is_vid || is_vbi) {
diff --git a/drivers/media/v4l2-core/v4l2-fh.c b/drivers/media/v4l2-core/v4l2-fh.c
index e57c002b4150..c97067a25bd2 100644
--- a/drivers/media/v4l2-core/v4l2-fh.c
+++ b/drivers/media/v4l2-core/v4l2-fh.c
@@ -37,6 +37,13 @@ void v4l2_fh_init(struct v4l2_fh *fh, struct video_device *vdev)
fh->ctrl_handler = vdev->ctrl_handler;
INIT_LIST_HEAD(&fh->list);
set_bit(V4L2_FL_USES_V4L2_FH, &fh->vdev->flags);
+ /*
+ * determine_valid_ioctls() does not know if struct v4l2_fh
+ * is used by this driver, but here we do. So enable the
+ * prio ioctls here.
+ */
+ set_bit(_IOC_NR(VIDIOC_G_PRIORITY), vdev->valid_ioctls);
+ set_bit(_IOC_NR(VIDIOC_S_PRIORITY), vdev->valid_ioctls);
fh->prio = V4L2_PRIORITY_UNSET;
init_waitqueue_head(&fh->wait);
INIT_LIST_HEAD(&fh->available);
@@ -49,8 +56,7 @@ void v4l2_fh_add(struct v4l2_fh *fh)
{
unsigned long flags;
- if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
- v4l2_prio_open(fh->vdev->prio, &fh->prio);
+ v4l2_prio_open(fh->vdev->prio, &fh->prio);
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_add(&fh->list, &fh->vdev->fh_list);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
@@ -78,8 +84,7 @@ void v4l2_fh_del(struct v4l2_fh *fh)
spin_lock_irqsave(&fh->vdev->fh_lock, flags);
list_del_init(&fh->list);
spin_unlock_irqrestore(&fh->vdev->fh_lock, flags);
- if (test_bit(V4L2_FL_USE_FH_PRIO, &fh->vdev->flags))
- v4l2_prio_close(fh->vdev->prio, fh->prio);
+ v4l2_prio_close(fh->vdev->prio, fh->prio);
}
EXPORT_SYMBOL_GPL(v4l2_fh_del);
diff --git a/drivers/media/v4l2-core/v4l2-ioctl.c b/drivers/media/v4l2-core/v4l2-ioctl.c
index 16bffd851bf9..d15e16737eef 100644
--- a/drivers/media/v4l2-core/v4l2-ioctl.c
+++ b/drivers/media/v4l2-core/v4l2-ioctl.c
@@ -256,7 +256,8 @@ static void v4l_print_format(const void *arg, bool write_only)
pix = &p->fmt.pix;
pr_cont(", width=%u, height=%u, "
"pixelformat=%c%c%c%c, field=%s, "
- "bytesperline=%u, sizeimage=%u, colorspace=%d\n",
+ "bytesperline=%u, sizeimage=%u, colorspace=%d, "
+ "flags %u\n",
pix->width, pix->height,
(pix->pixelformat & 0xff),
(pix->pixelformat >> 8) & 0xff,
@@ -264,7 +265,7 @@ static void v4l_print_format(const void *arg, bool write_only)
(pix->pixelformat >> 24) & 0xff,
prt_names(pix->field, v4l2_field_names),
pix->bytesperline, pix->sizeimage,
- pix->colorspace);
+ pix->colorspace, pix->flags);
break;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
@@ -525,6 +526,20 @@ static void v4l_print_queryctrl(const void *arg, bool write_only)
p->step, p->default_value, p->flags);
}
+static void v4l_print_query_ext_ctrl(const void *arg, bool write_only)
+{
+ const struct v4l2_query_ext_ctrl *p = arg;
+
+ pr_cont("id=0x%x, type=%d, name=%.*s, min/max=%lld/%lld, "
+ "step=%lld, default=%lld, flags=0x%08x, elem_size=%u, elems=%u, "
+ "nr_of_dims=%u, dims=%u,%u,%u,%u\n",
+ p->id, p->type, (int)sizeof(p->name), p->name,
+ p->minimum, p->maximum,
+ p->step, p->default_value, p->flags,
+ p->elem_size, p->elems, p->nr_of_dims,
+ p->dims[0], p->dims[1], p->dims[2], p->dims[3]);
+}
+
static void v4l_print_querymenu(const void *arg, bool write_only)
{
const struct v4l2_querymenu *p = arg;
@@ -959,13 +974,49 @@ static int check_fmt(struct file *file, enum v4l2_buf_type type)
return -EINVAL;
}
+static void v4l_sanitize_format(struct v4l2_format *fmt)
+{
+ unsigned int offset;
+
+ /*
+ * The v4l2_pix_format structure has been extended with fields that were
+ * not previously required to be set to zero by applications. The priv
+ * field, when set to a magic value, indicates the the extended fields
+ * are valid. Otherwise they will contain undefined values. To simplify
+ * the API towards drivers zero the extended fields and set the priv
+ * field to the magic value when the extended pixel format structure
+ * isn't used by applications.
+ */
+
+ if (fmt->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
+ fmt->type != V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ return;
+
+ if (fmt->fmt.pix.priv == V4L2_PIX_FMT_PRIV_MAGIC)
+ return;
+
+ fmt->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+ offset = offsetof(struct v4l2_pix_format, priv)
+ + sizeof(fmt->fmt.pix.priv);
+ memset(((void *)&fmt->fmt.pix) + offset, 0,
+ sizeof(fmt->fmt.pix) - offset);
+}
+
static int v4l_querycap(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_capability *cap = (struct v4l2_capability *)arg;
+ int ret;
cap->version = LINUX_VERSION_CODE;
- return ops->vidioc_querycap(file, fh, cap);
+
+ ret = ops->vidioc_querycap(file, fh, cap);
+
+ cap->capabilities |= V4L2_CAP_EXT_PIX_FORMAT;
+ cap->device_caps |= V4L2_CAP_EXT_PIX_FORMAT;
+
+ return ret;
}
static int v4l_s_input(const struct v4l2_ioctl_ops *ops,
@@ -1048,32 +1099,34 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
{
struct v4l2_fmtdesc *p = arg;
struct video_device *vfd = video_devdata(file);
+ bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+ bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap))
break;
return ops->vidioc_enum_fmt_vid_cap(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_cap_mplane))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_cap_mplane))
break;
return ops->vidioc_enum_fmt_vid_cap_mplane(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OVERLAY:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_vid_overlay))
+ if (unlikely(!is_rx || !is_vid || !ops->vidioc_enum_fmt_vid_overlay))
break;
return ops->vidioc_enum_fmt_vid_overlay(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
- if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out))
+ if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out))
break;
return ops->vidioc_enum_fmt_vid_out(file, fh, arg);
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
- if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
+ if (unlikely(!is_tx || !is_vid || !ops->vidioc_enum_fmt_vid_out_mplane))
break;
return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
case V4L2_BUF_TYPE_SDR_CAPTURE:
- if (unlikely(!is_rx || !ops->vidioc_enum_fmt_sdr_cap))
+ if (unlikely(!is_rx || !is_sdr || !ops->vidioc_enum_fmt_sdr_cap))
break;
return ops->vidioc_enum_fmt_sdr_cap(file, fh, arg);
}
@@ -1089,12 +1142,41 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ /*
+ * fmt can't be cleared for these overlay types due to the 'clips'
+ * 'clipcount' and 'bitmap' pointers in struct v4l2_window.
+ * Those are provided by the user. So handle these two overlay types
+ * first, and then just do a simple memset for the other types.
+ */
+ switch (p->type) {
+ case V4L2_BUF_TYPE_VIDEO_OVERLAY:
+ case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY: {
+ struct v4l2_clip *clips = p->fmt.win.clips;
+ u32 clipcount = p->fmt.win.clipcount;
+ void *bitmap = p->fmt.win.bitmap;
+
+ memset(&p->fmt, 0, sizeof(p->fmt));
+ p->fmt.win.clips = clips;
+ p->fmt.win.clipcount = clipcount;
+ p->fmt.win.bitmap = bitmap;
+ break;
+ }
+ default:
+ memset(&p->fmt, 0, sizeof(p->fmt));
+ break;
+ }
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
break;
- return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ ret = ops->vidioc_g_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
break;
@@ -1114,7 +1196,11 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
case V4L2_BUF_TYPE_VIDEO_OUTPUT:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
break;
- return ops->vidioc_g_fmt_vid_out(file, fh, arg);
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ ret = ops->vidioc_g_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
break;
@@ -1148,13 +1234,19 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ v4l_sanitize_format(p);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+ ret = ops->vidioc_s_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
break;
@@ -1179,7 +1271,10 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_s_fmt_vid_out(file, fh, arg);
+ ret = ops->vidioc_s_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
break;
@@ -1218,13 +1313,19 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
bool is_sdr = vfd->vfl_type == VFL_TYPE_SDR;
bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+ int ret;
+
+ v4l_sanitize_format(p);
switch (p->type) {
case V4L2_BUF_TYPE_VIDEO_CAPTURE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+ ret = ops->vidioc_try_fmt_vid_cap(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
break;
@@ -1249,7 +1350,10 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out))
break;
CLEAR_AFTER_FIELD(p, fmt.pix);
- return ops->vidioc_try_fmt_vid_out(file, fh, arg);
+ ret = ops->vidioc_try_fmt_vid_out(file, fh, arg);
+ /* just in case the driver zeroed it again */
+ p->fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+ return ret;
case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
break;
@@ -1502,7 +1606,18 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
struct v4l2_create_buffers *create = arg;
int ret = check_fmt(file, create->format.type);
- return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
+ if (ret)
+ return ret;
+
+ v4l_sanitize_format(&create->format);
+
+ ret = ops->vidioc_create_bufs(file, fh, create);
+
+ if (create->format.type == V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+ create->format.type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+ create->format.fmt.pix.priv = V4L2_PIX_FMT_PRIV_MAGIC;
+
+ return ret;
}
static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
@@ -1561,6 +1676,23 @@ static int v4l_queryctrl(const struct v4l2_ioctl_ops *ops,
return -ENOTTY;
}
+static int v4l_query_ext_ctrl(const struct v4l2_ioctl_ops *ops,
+ struct file *file, void *fh, void *arg)
+{
+ struct video_device *vfd = video_devdata(file);
+ struct v4l2_query_ext_ctrl *p = arg;
+ struct v4l2_fh *vfh =
+ test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags) ? fh : NULL;
+
+ if (vfh && vfh->ctrl_handler)
+ return v4l2_query_ext_ctrl(vfh->ctrl_handler, p);
+ if (vfd->ctrl_handler)
+ return v4l2_query_ext_ctrl(vfd->ctrl_handler, p);
+ if (ops->vidioc_query_ext_ctrl)
+ return ops->vidioc_query_ext_ctrl(file, fh, p);
+ return -ENOTTY;
+}
+
static int v4l_querymenu(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
@@ -1751,37 +1883,41 @@ static int v4l_cropcap(const struct v4l2_ioctl_ops *ops,
struct file *file, void *fh, void *arg)
{
struct v4l2_cropcap *p = arg;
- struct v4l2_selection s = { .type = p->type };
- int ret;
- if (ops->vidioc_cropcap)
- return ops->vidioc_cropcap(file, fh, p);
+ if (ops->vidioc_g_selection) {
+ struct v4l2_selection s = { .type = p->type };
+ int ret;
- /* obtaining bounds */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
- else
- s.target = V4L2_SEL_TGT_CROP_BOUNDS;
+ /* obtaining bounds */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_BOUNDS;
+ else
+ s.target = V4L2_SEL_TGT_CROP_BOUNDS;
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- return ret;
- p->bounds = s.r;
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ return ret;
+ p->bounds = s.r;
- /* obtaining defrect */
- if (V4L2_TYPE_IS_OUTPUT(p->type))
- s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
- else
- s.target = V4L2_SEL_TGT_CROP_DEFAULT;
+ /* obtaining defrect */
+ if (V4L2_TYPE_IS_OUTPUT(p->type))
+ s.target = V4L2_SEL_TGT_COMPOSE_DEFAULT;
+ else
+ s.target = V4L2_SEL_TGT_CROP_DEFAULT;
- ret = ops->vidioc_g_selection(file, fh, &s);
- if (ret)
- return ret;
- p->defrect = s.r;
+ ret = ops->vidioc_g_selection(file, fh, &s);
+ if (ret)
+ return ret;
+ p->defrect = s.r;
+ }
/* setting trivial pixelaspect */
p->pixelaspect.numerator = 1;
p->pixelaspect.denominator = 1;
+
+ if (ops->vidioc_cropcap)
+ return ops->vidioc_cropcap(file, fh, p);
+
return 0;
}
@@ -1951,8 +2087,11 @@ static int v4l_enum_freq_bands(const struct v4l2_ioctl_ops *ops,
if (type != p->type)
return -EINVAL;
}
- if (ops->vidioc_enum_freq_bands)
- return ops->vidioc_enum_freq_bands(file, fh, p);
+ if (ops->vidioc_enum_freq_bands) {
+ err = ops->vidioc_enum_freq_bands(file, fh, p);
+ if (err != -ENOTTY)
+ return err;
+ }
if (is_valid_ioctl(vfd, VIDIOC_G_TUNER)) {
struct v4l2_tuner t = {
.index = p->tuner,
@@ -2042,7 +2181,7 @@ struct v4l2_ioctl_info {
static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_QUERYCAP, v4l_querycap, v4l_print_querycap, 0),
IOCTL_INFO_FNC(VIDIOC_ENUM_FMT, v4l_enum_fmt, v4l_print_fmtdesc, INFO_FL_CLEAR(v4l2_fmtdesc, type)),
- IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, INFO_FL_CLEAR(v4l2_format, type)),
+ IOCTL_INFO_FNC(VIDIOC_G_FMT, v4l_g_fmt, v4l_print_format, 0),
IOCTL_INFO_FNC(VIDIOC_S_FMT, v4l_s_fmt, v4l_print_format, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_REQBUFS, v4l_reqbufs, v4l_print_requestbuffers, INFO_FL_PRIO | INFO_FL_QUEUE),
IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
@@ -2070,8 +2209,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_QUERYMENU, v4l_querymenu, v4l_print_querymenu, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_querymenu, index)),
IOCTL_INFO_STD(VIDIOC_G_INPUT, vidioc_g_input, v4l_print_u32, 0),
IOCTL_INFO_FNC(VIDIOC_S_INPUT, v4l_s_input, v4l_print_u32, INFO_FL_PRIO),
- IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, INFO_FL_CLEAR(v4l2_edid, edid)),
- IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_edid, edid)),
+ IOCTL_INFO_STD(VIDIOC_G_EDID, vidioc_g_edid, v4l_print_edid, 0),
+ IOCTL_INFO_STD(VIDIOC_S_EDID, vidioc_s_edid, v4l_print_edid, INFO_FL_PRIO),
IOCTL_INFO_STD(VIDIOC_G_OUTPUT, vidioc_g_output, v4l_print_u32, 0),
IOCTL_INFO_FNC(VIDIOC_S_OUTPUT, v4l_s_output, v4l_print_u32, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_ENUMOUTPUT, v4l_enumoutput, v4l_print_enumoutput, INFO_FL_CLEAR(v4l2_output, index)),
@@ -2084,8 +2223,8 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_FNC(VIDIOC_CROPCAP, v4l_cropcap, v4l_print_cropcap, INFO_FL_CLEAR(v4l2_cropcap, type)),
IOCTL_INFO_FNC(VIDIOC_G_CROP, v4l_g_crop, v4l_print_crop, INFO_FL_CLEAR(v4l2_crop, type)),
IOCTL_INFO_FNC(VIDIOC_S_CROP, v4l_s_crop, v4l_print_crop, INFO_FL_PRIO),
- IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, 0),
- IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO),
+ IOCTL_INFO_STD(VIDIOC_G_SELECTION, vidioc_g_selection, v4l_print_selection, INFO_FL_CLEAR(v4l2_selection, r)),
+ IOCTL_INFO_STD(VIDIOC_S_SELECTION, vidioc_s_selection, v4l_print_selection, INFO_FL_PRIO | INFO_FL_CLEAR(v4l2_selection, r)),
IOCTL_INFO_STD(VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp, v4l_print_jpegcompression, 0),
IOCTL_INFO_STD(VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp, v4l_print_jpegcompression, INFO_FL_PRIO),
IOCTL_INFO_FNC(VIDIOC_QUERYSTD, v4l_querystd, v4l_print_std, 0),
@@ -2121,6 +2260,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
IOCTL_INFO_STD(VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap, v4l_print_dv_timings_cap, INFO_FL_CLEAR(v4l2_dv_timings_cap, type)),
IOCTL_INFO_FNC(VIDIOC_ENUM_FREQ_BANDS, v4l_enum_freq_bands, v4l_print_freq_band, 0),
IOCTL_INFO_FNC(VIDIOC_DBG_G_CHIP_INFO, v4l_dbg_g_chip_info, v4l_print_dbg_chip_info, INFO_FL_CLEAR(v4l2_dbg_chip_info, match)),
+ IOCTL_INFO_FNC(VIDIOC_QUERY_EXT_CTRL, v4l_query_ext_ctrl, v4l_print_query_ext_ctrl, INFO_FL_CTRL | INFO_FL_CLEAR(v4l2_query_ext_ctrl, id)),
};
#define V4L2_IOCTLS ARRAY_SIZE(v4l2_ioctls)
@@ -2190,7 +2330,6 @@ static long __video_do_ioctl(struct file *file,
const struct v4l2_ioctl_info *info;
void *fh = file->private_data;
struct v4l2_fh *vfh = NULL;
- int use_fh_prio = 0;
int debug = vfd->debug;
long ret = -ENOTTY;
@@ -2200,10 +2339,8 @@ static long __video_do_ioctl(struct file *file,
return ret;
}
- if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags)) {
+ if (test_bit(V4L2_FL_USES_V4L2_FH, &vfd->flags))
vfh = file->private_data;
- use_fh_prio = test_bit(V4L2_FL_USE_FH_PRIO, &vfd->flags);
- }
if (v4l2_is_known_ioctl(cmd)) {
info = &v4l2_ioctls[_IOC_NR(cmd)];
@@ -2212,7 +2349,7 @@ static long __video_do_ioctl(struct file *file,
!((info->flags & INFO_FL_CTRL) && vfh && vfh->ctrl_handler))
goto done;
- if (use_fh_prio && (info->flags & INFO_FL_PRIO)) {
+ if (vfh && (info->flags & INFO_FL_PRIO)) {
ret = v4l2_prio_check(vfd->prio, vfh->prio);
if (ret)
goto done;
@@ -2237,7 +2374,7 @@ static long __video_do_ioctl(struct file *file,
ret = -ENOTTY;
} else {
ret = ops->vidioc_default(file, fh,
- use_fh_prio ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
+ vfh ? v4l2_prio_check(vfd->prio, vfh->prio) >= 0 : 0,
cmd, arg);
}
diff --git a/drivers/media/v4l2-core/v4l2-mem2mem.c b/drivers/media/v4l2-core/v4l2-mem2mem.c
index 178ce96556c6..97defed7c1ac 100644
--- a/drivers/media/v4l2-core/v4l2-mem2mem.c
+++ b/drivers/media/v4l2-core/v4l2-mem2mem.c
@@ -568,8 +568,12 @@ unsigned int v4l2_m2m_poll(struct file *file, struct v4l2_m2m_ctx *m2m_ctx,
if (m2m_ctx->m2m_dev->m2m_ops->lock)
m2m_ctx->m2m_dev->m2m_ops->lock(m2m_ctx->priv);
- else if (m2m_ctx->q_lock)
- mutex_lock(m2m_ctx->q_lock);
+ else if (m2m_ctx->q_lock) {
+ if (mutex_lock_interruptible(m2m_ctx->q_lock)) {
+ rc |= POLLERR;
+ goto end;
+ }
+ }
spin_lock_irqsave(&src_q->done_lock, flags);
if (!list_empty(&src_q->done_list))
diff --git a/drivers/media/v4l2-core/v4l2-subdev.c b/drivers/media/v4l2-core/v4l2-subdev.c
index 058c1a6e8392..b4d235c13fbf 100644
--- a/drivers/media/v4l2-core/v4l2-subdev.c
+++ b/drivers/media/v4l2-core/v4l2-subdev.c
@@ -126,6 +126,57 @@ static int subdev_close(struct file *file)
return 0;
}
+#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
+static int check_format(struct v4l2_subdev *sd,
+ struct v4l2_subdev_format *format)
+{
+ if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
+ format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (format->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_crop(struct v4l2_subdev *sd, struct v4l2_subdev_crop *crop)
+{
+ if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
+ crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (crop->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_selection(struct v4l2_subdev *sd,
+ struct v4l2_subdev_selection *sel)
+{
+ if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
+ sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
+ return -EINVAL;
+
+ if (sel->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int check_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+ if (edid->pad >= sd->entity.num_pads)
+ return -EINVAL;
+
+ if (edid->blocks && edid->edid == NULL)
+ return -EINVAL;
+
+ return 0;
+}
+#endif
+
static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
{
struct video_device *vdev = video_devdata(file);
@@ -133,12 +184,16 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
struct v4l2_fh *vfh = file->private_data;
#if defined(CONFIG_VIDEO_V4L2_SUBDEV_API)
struct v4l2_subdev_fh *subdev_fh = to_v4l2_subdev_fh(vfh);
+ int rval;
#endif
switch (cmd) {
case VIDIOC_QUERYCTRL:
return v4l2_queryctrl(vfh->ctrl_handler, arg);
+ case VIDIOC_QUERY_EXT_CTRL:
+ return v4l2_query_ext_ctrl(vfh->ctrl_handler, arg);
+
case VIDIOC_QUERYMENU:
return v4l2_querymenu(vfh->ctrl_handler, arg);
@@ -203,12 +258,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_FMT: {
struct v4l2_subdev_format *format = arg;
- if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
- format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (format->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_format(sd, format);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, get_fmt, subdev_fh, format);
}
@@ -216,12 +268,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_FMT: {
struct v4l2_subdev_format *format = arg;
- if (format->which != V4L2_SUBDEV_FORMAT_TRY &&
- format->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (format->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_format(sd, format);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, set_fmt, subdev_fh, format);
}
@@ -229,14 +278,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_CROP: {
struct v4l2_subdev_crop *crop = arg;
struct v4l2_subdev_selection sel;
- int rval;
-
- if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
- crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
- if (crop->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_crop(sd, crop);
+ if (rval)
+ return rval;
rval = v4l2_subdev_call(sd, pad, get_crop, subdev_fh, crop);
if (rval != -ENOIOCTLCMD)
@@ -258,14 +303,10 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_CROP: {
struct v4l2_subdev_crop *crop = arg;
struct v4l2_subdev_selection sel;
- int rval;
-
- if (crop->which != V4L2_SUBDEV_FORMAT_TRY &&
- crop->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
- if (crop->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_crop(sd, crop);
+ if (rval)
+ return rval;
rval = v4l2_subdev_call(sd, pad, set_crop, subdev_fh, crop);
if (rval != -ENOIOCTLCMD)
@@ -336,12 +377,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_G_SELECTION: {
struct v4l2_subdev_selection *sel = arg;
- if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
- sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (sel->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_selection(sd, sel);
+ if (rval)
+ return rval;
return v4l2_subdev_call(
sd, pad, get_selection, subdev_fh, sel);
@@ -350,12 +388,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_SUBDEV_S_SELECTION: {
struct v4l2_subdev_selection *sel = arg;
- if (sel->which != V4L2_SUBDEV_FORMAT_TRY &&
- sel->which != V4L2_SUBDEV_FORMAT_ACTIVE)
- return -EINVAL;
-
- if (sel->pad >= sd->entity.num_pads)
- return -EINVAL;
+ rval = check_selection(sd, sel);
+ if (rval)
+ return rval;
return v4l2_subdev_call(
sd, pad, set_selection, subdev_fh, sel);
@@ -364,10 +399,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_G_EDID: {
struct v4l2_subdev_edid *edid = arg;
- if (edid->pad >= sd->entity.num_pads)
- return -EINVAL;
- if (edid->blocks && edid->edid == NULL)
- return -EINVAL;
+ rval = check_edid(sd, edid);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, get_edid, edid);
}
@@ -375,10 +409,9 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
case VIDIOC_S_EDID: {
struct v4l2_subdev_edid *edid = arg;
- if (edid->pad >= sd->entity.num_pads)
- return -EINVAL;
- if (edid->blocks && edid->edid == NULL)
- return -EINVAL;
+ rval = check_edid(sd, edid);
+ if (rval)
+ return rval;
return v4l2_subdev_call(sd, pad, set_edid, edid);
}
diff --git a/drivers/media/v4l2-core/videobuf2-core.c b/drivers/media/v4l2-core/videobuf2-core.c
index 7c4489c42365..f33508f854a4 100644
--- a/drivers/media/v4l2-core/videobuf2-core.c
+++ b/drivers/media/v4l2-core/videobuf2-core.c
@@ -576,6 +576,7 @@ static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer
static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
{
unsigned int length;
+ unsigned int bytesused;
unsigned int plane;
if (!V4L2_TYPE_IS_OUTPUT(b->type))
@@ -583,21 +584,24 @@ static int __verify_length(struct vb2_buffer *vb, const struct v4l2_buffer *b)
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
for (plane = 0; plane < vb->num_planes; ++plane) {
- length = (b->memory == V4L2_MEMORY_USERPTR)
+ length = (b->memory == V4L2_MEMORY_USERPTR ||
+ b->memory == V4L2_MEMORY_DMABUF)
? b->m.planes[plane].length
: vb->v4l2_planes[plane].length;
+ bytesused = b->m.planes[plane].bytesused
+ ? b->m.planes[plane].bytesused : length;
if (b->m.planes[plane].bytesused > length)
return -EINVAL;
if (b->m.planes[plane].data_offset > 0 &&
- b->m.planes[plane].data_offset >=
- b->m.planes[plane].bytesused)
+ b->m.planes[plane].data_offset >= bytesused)
return -EINVAL;
}
} else {
length = (b->memory == V4L2_MEMORY_USERPTR)
? b->length : vb->v4l2_planes[0].length;
+ bytesused = b->bytesused ? b->bytesused : length;
if (b->bytesused > length)
return -EINVAL;
@@ -1234,35 +1238,6 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
unsigned int plane;
if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
- /* Fill in driver-provided information for OUTPUT types */
- if (V4L2_TYPE_IS_OUTPUT(b->type)) {
- bool bytesused_is_used;
-
- /* Check if bytesused == 0 for all planes */
- for (plane = 0; plane < vb->num_planes; ++plane)
- if (b->m.planes[plane].bytesused)
- break;
- bytesused_is_used = plane < vb->num_planes;
-
- /*
- * Will have to go up to b->length when API starts
- * accepting variable number of planes.
- *
- * If bytesused_is_used is false, then fall back to the
- * full buffer size. In that case userspace clearly
- * never bothered to set it and it's a safe assumption
- * that they really meant to use the full plane sizes.
- */
- for (plane = 0; plane < vb->num_planes; ++plane) {
- struct v4l2_plane *pdst = &v4l2_planes[plane];
- struct v4l2_plane *psrc = &b->m.planes[plane];
-
- pdst->bytesused = bytesused_is_used ?
- psrc->bytesused : psrc->length;
- pdst->data_offset = psrc->data_offset;
- }
- }
-
if (b->memory == V4L2_MEMORY_USERPTR) {
for (plane = 0; plane < vb->num_planes; ++plane) {
v4l2_planes[plane].m.userptr =
@@ -1279,6 +1254,28 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
b->m.planes[plane].length;
}
}
+
+ /* Fill in driver-provided information for OUTPUT types */
+ if (V4L2_TYPE_IS_OUTPUT(b->type)) {
+ /*
+ * Will have to go up to b->length when API starts
+ * accepting variable number of planes.
+ *
+ * If bytesused == 0 for the output buffer, then fall
+ * back to the full buffer size. In that case
+ * userspace clearly never bothered to set it and
+ * it's a safe assumption that they really meant to
+ * use the full plane sizes.
+ */
+ for (plane = 0; plane < vb->num_planes; ++plane) {
+ struct v4l2_plane *pdst = &v4l2_planes[plane];
+ struct v4l2_plane *psrc = &b->m.planes[plane];
+
+ pdst->bytesused = psrc->bytesused ?
+ psrc->bytesused : pdst->length;
+ pdst->data_offset = psrc->data_offset;
+ }
+ }
} else {
/*
* Single-planar buffers do not use planes array,
@@ -1286,15 +1283,9 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
* In videobuf we use our internal V4l2_planes struct for
* single-planar buffers as well, for simplicity.
*
- * If bytesused == 0, then fall back to the full buffer size
- * as that's a sensible default.
+ * If bytesused == 0 for the output buffer, then fall back
+ * to the full buffer size as that's a sensible default.
*/
- if (V4L2_TYPE_IS_OUTPUT(b->type))
- v4l2_planes[0].bytesused =
- b->bytesused ? b->bytesused : b->length;
- else
- v4l2_planes[0].bytesused = 0;
-
if (b->memory == V4L2_MEMORY_USERPTR) {
v4l2_planes[0].m.userptr = b->m.userptr;
v4l2_planes[0].length = b->length;
@@ -1304,6 +1295,13 @@ static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b
v4l2_planes[0].m.fd = b->m.fd;
v4l2_planes[0].length = b->length;
}
+
+ if (V4L2_TYPE_IS_OUTPUT(b->type))
+ v4l2_planes[0].bytesused = b->bytesused ?
+ b->bytesused : v4l2_planes[0].length;
+ else
+ v4l2_planes[0].bytesused = 0;
+
}
/* Zero flags that the vb2 core handles */
@@ -1606,6 +1604,11 @@ static int __buf_prepare(struct vb2_buffer *vb, const struct v4l2_buffer *b)
return -EINVAL;
}
+ if (q->error) {
+ dprintk(1, "fatal error occurred on queue\n");
+ return -EIO;
+ }
+
vb->state = VB2_BUF_STATE_PREPARING;
vb->v4l2_buf.timestamp.tv_sec = 0;
vb->v4l2_buf.timestamp.tv_usec = 0;
@@ -1750,12 +1753,14 @@ static int vb2_start_streaming(struct vb2_queue *q)
__enqueue_in_driver(vb);
/* Tell the driver to start streaming */
+ q->start_streaming_called = 1;
ret = call_qop(q, start_streaming, q,
atomic_read(&q->owned_by_drv_count));
- q->start_streaming_called = ret == 0;
if (!ret)
return 0;
+ q->start_streaming_called = 0;
+
dprintk(1, "driver refused to start streaming\n");
if (WARN_ON(atomic_read(&q->owned_by_drv_count))) {
unsigned i;
@@ -1901,6 +1906,11 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
return -EINVAL;
}
+ if (q->error) {
+ dprintk(1, "Queue in error state, will not wait for buffers\n");
+ return -EIO;
+ }
+
if (!list_empty(&q->done_list)) {
/*
* Found a buffer that we were waiting for.
@@ -1926,7 +1936,8 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
*/
dprintk(3, "will sleep waiting for buffers\n");
ret = wait_event_interruptible(q->done_wq,
- !list_empty(&q->done_list) || !q->streaming);
+ !list_empty(&q->done_list) || !q->streaming ||
+ q->error);
/*
* We need to reevaluate both conditions again after reacquiring
@@ -2123,6 +2134,7 @@ static void __vb2_queue_cancel(struct vb2_queue *q)
q->streaming = 0;
q->start_streaming_called = 0;
q->queued_count = 0;
+ q->error = 0;
/*
* Remove all buffers from videobuf's list...
@@ -2200,6 +2212,27 @@ static int vb2_internal_streamon(struct vb2_queue *q, enum v4l2_buf_type type)
}
/**
+ * vb2_queue_error() - signal a fatal error on the queue
+ * @q: videobuf2 queue
+ *
+ * Flag that a fatal unrecoverable error has occurred and wake up all processes
+ * waiting on the queue. Polling will now set POLLERR and queuing and dequeuing
+ * buffers will return -EIO.
+ *
+ * The error flag will be cleared when cancelling the queue, either from
+ * vb2_streamoff or vb2_queue_release. Drivers should thus not call this
+ * function before starting the stream, otherwise the error flag will remain set
+ * until the queue is released when closing the device node.
+ */
+void vb2_queue_error(struct vb2_queue *q)
+{
+ q->error = 1;
+
+ wake_up_all(&q->done_wq);
+}
+EXPORT_SYMBOL_GPL(vb2_queue_error);
+
+/**
* vb2_streamon - start streaming
* @q: videobuf2 queue
* @type: type argument passed from userspace to vidioc_streamon handler
@@ -2557,9 +2590,10 @@ unsigned int vb2_poll(struct vb2_queue *q, struct file *file, poll_table *wait)
}
/*
- * There is nothing to wait for if no buffers have already been queued.
+ * There is nothing to wait for if no buffer has been queued and the
+ * queue isn't streaming, or if the error flag is set.
*/
- if (list_empty(&q->queued_list))
+ if ((list_empty(&q->queued_list) && !vb2_is_streaming(q)) || q->error)
return res | POLLERR;
if (list_empty(&q->done_list))
diff --git a/drivers/media/v4l2-core/videobuf2-dma-contig.c b/drivers/media/v4l2-core/videobuf2-dma-contig.c
index 880be0782dd9..6b254b8e47c4 100644
--- a/drivers/media/v4l2-core/videobuf2-dma-contig.c
+++ b/drivers/media/v4l2-core/videobuf2-dma-contig.c
@@ -98,6 +98,9 @@ static void *vb2_dc_vaddr(void *buf_priv)
{
struct vb2_dc_buf *buf = buf_priv;
+ if (!buf->vaddr && buf->db_attach)
+ buf->vaddr = dma_buf_vmap(buf->db_attach->dmabuf);
+
return buf->vaddr;
}
@@ -735,6 +738,7 @@ static int vb2_dc_map_dmabuf(void *mem_priv)
buf->dma_addr = sg_dma_address(sgt->sgl);
buf->dma_sgt = sgt;
+ buf->vaddr = NULL;
return 0;
}
@@ -754,6 +758,10 @@ static void vb2_dc_unmap_dmabuf(void *mem_priv)
return;
}
+ if (buf->vaddr) {
+ dma_buf_vunmap(buf->db_attach->dmabuf, buf->vaddr);
+ buf->vaddr = NULL;
+ }
dma_buf_unmap_attachment(buf->db_attach, sgt, buf->dma_dir);
buf->dma_addr = 0;
diff --git a/drivers/staging/media/Kconfig b/drivers/staging/media/Kconfig
index a9f2e63a7c9c..e91c538d3d0d 100644
--- a/drivers/staging/media/Kconfig
+++ b/drivers/staging/media/Kconfig
@@ -31,18 +31,12 @@ source "drivers/staging/media/dt3155v4l/Kconfig"
source "drivers/staging/media/go7007/Kconfig"
-source "drivers/staging/media/msi3101/Kconfig"
-
source "drivers/staging/media/omap24xx/Kconfig"
-source "drivers/staging/media/sn9c102/Kconfig"
-
source "drivers/staging/media/solo6x10/Kconfig"
source "drivers/staging/media/omap4iss/Kconfig"
-source "drivers/staging/media/rtl2832u_sdr/Kconfig"
-
# Keep LIRC at the end, as it has sub-menus
source "drivers/staging/media/lirc/Kconfig"
diff --git a/drivers/staging/media/Makefile b/drivers/staging/media/Makefile
index 8e2c5d272162..4f6c0ee0ad13 100644
--- a/drivers/staging/media/Makefile
+++ b/drivers/staging/media/Makefile
@@ -5,11 +5,8 @@ obj-$(CONFIG_LIRC_STAGING) += lirc/
obj-$(CONFIG_SOLO6X10) += solo6x10/
obj-$(CONFIG_VIDEO_DT3155) += dt3155v4l/
obj-$(CONFIG_VIDEO_GO7007) += go7007/
-obj-$(CONFIG_USB_MSI3101) += msi3101/
obj-$(CONFIG_VIDEO_DM365_VPFE) += davinci_vpfe/
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
-obj-$(CONFIG_USB_SN9C102) += sn9c102/
obj-$(CONFIG_VIDEO_OMAP2) += omap24xx/
obj-$(CONFIG_VIDEO_TCM825X) += omap24xx/
-obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832u_sdr/
diff --git a/drivers/staging/media/bcm2048/radio-bcm2048.c b/drivers/staging/media/bcm2048/radio-bcm2048.c
index bbf236e842a9..2bba370a47ca 100644
--- a/drivers/staging/media/bcm2048/radio-bcm2048.c
+++ b/drivers/staging/media/bcm2048/radio-bcm2048.c
@@ -369,13 +369,12 @@ static int bcm2048_send_command(struct bcm2048_device *bdev, unsigned int reg,
data[0] = reg & 0xff;
data[1] = value & 0xff;
- if (i2c_master_send(client, data, 2) == 2) {
+ if (i2c_master_send(client, data, 2) == 2)
return 0;
- } else {
- dev_err(&bdev->client->dev, "BCM I2C error!\n");
- dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n");
- return -EIO;
- }
+
+ dev_err(&bdev->client->dev, "BCM I2C error!\n");
+ dev_err(&bdev->client->dev, "Is Bluetooth up and running?\n");
+ return -EIO;
}
static int bcm2048_recv_command(struct bcm2048_device *bdev, unsigned int reg,
@@ -725,8 +724,8 @@ static int bcm2048_get_fm_deemphasis(struct bcm2048_device *bdev)
if (!err) {
if (value & BCM2048_DE_EMPHASIS_SELECT)
return BCM2048_DE_EMPHASIS_75us;
- else
- return BCM2048_DE_EMPHASIS_50us;
+
+ return BCM2048_DE_EMPHASIS_50us;
}
return err;
@@ -1971,7 +1970,8 @@ static ssize_t bcm2048_##prop##_write(struct device *dev, \
if (!bdev) \
return -ENODEV; \
\
- sscanf(buf, mask, &value); \
+ if (sscanf(buf, mask, &value) != 1) \
+ return -EINVAL; \
\
if (check) \
return -EDOM; \
@@ -2242,6 +2242,7 @@ static ssize_t bcm2048_fops_read(struct file *file, char __user *buf,
i = 0;
while (i < count) {
unsigned char tmpbuf[3];
+
tmpbuf[i] = bdev->rds_info.radio_text[bdev->rd_index+i+2];
tmpbuf[i+1] = bdev->rds_info.radio_text[bdev->rd_index+i+1];
tmpbuf[i+2] = ((bdev->rds_info.radio_text[bdev->rd_index+i]
@@ -2598,7 +2599,6 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
bdev = kzalloc(sizeof(*bdev), GFP_KERNEL);
if (!bdev) {
- dev_dbg(&client->dev, "Failed to alloc video device.\n");
err = -ENOMEM;
goto exit;
}
@@ -2618,7 +2618,7 @@ static int bcm2048_i2c_driver_probe(struct i2c_client *client,
if (client->irq) {
err = request_irq(client->irq,
- bcm2048_handler, IRQF_TRIGGER_FALLING | IRQF_DISABLED,
+ bcm2048_handler, IRQF_TRIGGER_FALLING,
client->name, bdev);
if (err < 0) {
dev_err(&client->dev, "Could not request IRQ\n");
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
index b7044a380fe3..bdc7f005b3ba 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe.c
@@ -1268,6 +1268,7 @@ static int ipipe_s_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
for (i = 0; i < ARRAY_SIZE(ipipe_modules); i++) {
unsigned int bit = 1 << i;
+
if (cfg->flag & bit) {
const struct ipipe_module_if *module_if =
&ipipe_modules[i];
@@ -1310,6 +1311,7 @@ static int ipipe_g_config(struct v4l2_subdev *sd, struct vpfe_ipipe_config *cfg)
for (i = 1; i < ARRAY_SIZE(ipipe_modules); i++) {
unsigned int bit = 1 << i;
+
if (cfg->flag & bit) {
const struct ipipe_module_if *module_if =
&ipipe_modules[i];
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h
index 010fdb247faf..81176fb9d164 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipe_hw.h
@@ -479,7 +479,6 @@
#define RSZ_TYP_Y_SHIFT 0
#define RSZ_TYP_C_SHIFT 1
#define RSZ_LPF_INT_MASK 0x3f
-#define RSZ_LPF_INT_MASK 0x3f
#define RSZ_LPF_INT_C_SHIFT 6
#define RSZ_H_PHS_MASK 0x3fff
#define RSZ_H_DIF_MASK 0x3fff
diff --git a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
index 59540cd4bb98..6d4893b44c1f 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_ipipeif.c
@@ -196,6 +196,7 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd)
int data_shift;
int pack_mode;
int source1;
+ int tmp;
ipipeif_base_addr = ipipeif->ipipeif_base_addr;
@@ -206,8 +207,8 @@ static int ipipeif_hw_setup(struct v4l2_subdev *sd)
outformat = &ipipeif->formats[IPIPEIF_PAD_SOURCE];
/* Combine all the fields to make CFG1 register of IPIPEIF */
- val = get_oneshot_mode(ipipeif->input);
- if (val < 0) {
+ tmp = val = get_oneshot_mode(ipipeif->input);
+ if (tmp < 0) {
pr_err("ipipeif: links setup required");
return -EINVAL;
}
diff --git a/drivers/staging/media/davinci_vpfe/dm365_resizer.c b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
index 8e13bd494c98..8828d6c2aab1 100644
--- a/drivers/staging/media/davinci_vpfe/dm365_resizer.c
+++ b/drivers/staging/media/davinci_vpfe/dm365_resizer.c
@@ -219,7 +219,7 @@ configure_resizer_out_params(struct vpfe_resizer_device *resizer, int index,
* @resizer: Pointer to VPFE resizer subdevice.
* @index: index RSZ_A-resizer-A RSZ_B-resizer-B.
*/
-void
+static void
resizer_calculate_resize_ratios(struct vpfe_resizer_device *resizer, int index)
{
struct resizer_params *param = &resizer->config;
@@ -310,7 +310,7 @@ resizer_calculate_sdram_offsets(struct vpfe_resizer_device *resizer, int index)
return 0;
}
-int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
+static int resizer_configure_output_win(struct vpfe_resizer_device *resizer)
{
struct resizer_params *param = &resizer->config;
struct vpfe_rsz_output_spec output_specs;
diff --git a/drivers/staging/media/davinci_vpfe/vpfe_video.c b/drivers/staging/media/davinci_vpfe/vpfe_video.c
index d95c427043d4..6f9171c39bdc 100644
--- a/drivers/staging/media/davinci_vpfe/vpfe_video.c
+++ b/drivers/staging/media/davinci_vpfe/vpfe_video.c
@@ -1606,7 +1606,6 @@ int vpfe_video_init(struct vpfe_video_device *video, const char *name)
if (ret < 0)
return ret;
- set_bit(V4L2_FL_USE_FH_PRIO, &video->video_dev.flags);
video_set_drvdata(&video->video_dev, video);
return 0;
diff --git a/drivers/staging/media/go7007/README b/drivers/staging/media/go7007/README
index 3af0d9062811..34516ea3b9c5 100644
--- a/drivers/staging/media/go7007/README
+++ b/drivers/staging/media/go7007/README
@@ -1,5 +1,4 @@
Todo:
- - create an API for motion detection
- let s2250-board use i2c subdevs as well instead of hardcoding
support for the i2c devices.
- when the driver is moved out of staging, support for saa7134-go7007
diff --git a/drivers/staging/media/go7007/go7007-driver.c b/drivers/staging/media/go7007/go7007-driver.c
index 6f1beca86b2b..95cffb771a62 100644
--- a/drivers/staging/media/go7007/go7007-driver.c
+++ b/drivers/staging/media/go7007/go7007-driver.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -32,6 +28,7 @@
#include <linux/videodev2.h>
#include <media/tuner.h>
#include <media/v4l2-common.h>
+#include <media/v4l2-event.h>
#include "go7007-priv.h"
@@ -224,7 +221,7 @@ static int init_i2c_module(struct i2c_adapter *adapter, const struct go_i2c *con
return 0;
}
- printk(KERN_INFO "go7007: probing for module i2c:%s failed\n", i2c->type);
+ pr_info("go7007: probing for module i2c:%s failed\n", i2c->type);
return -EINVAL;
}
@@ -332,20 +329,33 @@ EXPORT_SYMBOL(go7007_register_encoder);
int go7007_start_encoder(struct go7007 *go)
{
u8 *fw;
- int fw_len, rv = 0, i;
+ int fw_len, rv = 0, i, x, y;
u16 intr_val, intr_data;
go->modet_enable = 0;
- if (!go->dvd_mode)
- for (i = 0; i < 4; ++i) {
- if (go->modet[i].enable) {
- go->modet_enable = 1;
- continue;
+ for (i = 0; i < 4; i++)
+ go->modet[i].enable = 0;
+
+ switch (v4l2_ctrl_g_ctrl(go->modet_mode)) {
+ case V4L2_DETECT_MD_MODE_GLOBAL:
+ memset(go->modet_map, 0, sizeof(go->modet_map));
+ go->modet[0].enable = 1;
+ go->modet_enable = 1;
+ break;
+ case V4L2_DETECT_MD_MODE_REGION_GRID:
+ for (y = 0; y < go->height / 16; y++) {
+ for (x = 0; x < go->width / 16; x++) {
+ int idx = y * go->width / 16 + x;
+
+ go->modet[go->modet_map[idx]].enable = 1;
}
- go->modet[i].pixel_threshold = 32767;
- go->modet[i].motion_threshold = 32767;
- go->modet[i].mb_threshold = 32767;
}
+ go->modet_enable = 1;
+ break;
+ }
+
+ if (go->dvd_mode)
+ go->modet_enable = 0;
if (go7007_construct_fw_image(go, &fw, &fw_len) < 0)
return -1;
@@ -383,44 +393,89 @@ static inline void store_byte(struct go7007_buffer *vb, u8 byte)
}
}
+static void go7007_set_motion_regions(struct go7007 *go, struct go7007_buffer *vb,
+ u32 motion_regions)
+{
+ if (motion_regions != go->modet_event_status) {
+ struct v4l2_event ev = {
+ .type = V4L2_EVENT_MOTION_DET,
+ .u.motion_det = {
+ .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vb->vb.v4l2_buf.sequence,
+ .region_mask = motion_regions,
+ },
+ };
+
+ v4l2_event_queue(&go->vdev, &ev);
+ go->modet_event_status = motion_regions;
+ }
+}
+
/*
- * Deliver the last video buffer and get a new one to start writing to.
+ * Determine regions with motion and send a motion detection event
+ * in case of changes.
*/
-static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
+static void go7007_motion_regions(struct go7007 *go, struct go7007_buffer *vb)
{
- struct go7007_buffer *vb_tmp = NULL;
u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ unsigned motion[4] = { 0, 0, 0, 0 };
+ u32 motion_regions = 0;
+ unsigned stride = (go->width + 7) >> 3;
+ unsigned x, y;
int i;
- if (vb) {
- if (vb->modet_active) {
- if (*bytesused + 216 < GO7007_BUF_SIZE) {
- for (i = 0; i < 216; ++i)
- store_byte(vb, go->active_map[i]);
- *bytesused -= 216;
- } else
- vb->modet_active = 0;
+ for (i = 0; i < 216; ++i)
+ store_byte(vb, go->active_map[i]);
+ for (y = 0; y < go->height / 16; y++) {
+ for (x = 0; x < go->width / 16; x++) {
+ if (!(go->active_map[y * stride + (x >> 3)] & (1 << (x & 7))))
+ continue;
+ motion[go->modet_map[y * (go->width / 16) + x]]++;
}
- vb->vb.v4l2_buf.sequence = go->next_seq++;
- v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
- vb_tmp = vb;
+ }
+ motion_regions = ((motion[0] > 0) << 0) |
+ ((motion[1] > 0) << 1) |
+ ((motion[2] > 0) << 2) |
+ ((motion[3] > 0) << 3);
+ *bytesused -= 216;
+ go7007_set_motion_regions(go, vb, motion_regions);
+}
+
+/*
+ * Deliver the last video buffer and get a new one to start writing to.
+ */
+static struct go7007_buffer *frame_boundary(struct go7007 *go, struct go7007_buffer *vb)
+{
+ u32 *bytesused = &vb->vb.v4l2_planes[0].bytesused;
+ struct go7007_buffer *vb_tmp = NULL;
+
+ if (vb == NULL) {
spin_lock(&go->spinlock);
- list_del(&vb->list);
- if (list_empty(&go->vidq_active))
- vb = NULL;
- else
- vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
- go->active_buf = vb;
+ if (!list_empty(&go->vidq_active))
+ vb = go->active_buf =
+ list_first_entry(&go->vidq_active, struct go7007_buffer, list);
spin_unlock(&go->spinlock);
- vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
+ go->next_seq++;
return vb;
}
+
+ vb->vb.v4l2_buf.sequence = go->next_seq++;
+ if (vb->modet_active && *bytesused + 216 < GO7007_BUF_SIZE)
+ go7007_motion_regions(go, vb);
+ else
+ go7007_set_motion_regions(go, vb, 0);
+
+ v4l2_get_timestamp(&vb->vb.v4l2_buf.timestamp);
+ vb_tmp = vb;
spin_lock(&go->spinlock);
- if (!list_empty(&go->vidq_active))
- vb = go->active_buf =
- list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+ list_del(&vb->list);
+ if (list_empty(&go->vidq_active))
+ vb = NULL;
+ else
+ vb = list_first_entry(&go->vidq_active, struct go7007_buffer, list);
+ go->active_buf = vb;
spin_unlock(&go->spinlock);
- go->next_seq++;
+ vb2_buffer_done(&vb_tmp->vb, VB2_BUF_STATE_DONE);
return vb;
}
diff --git a/drivers/staging/media/go7007/go7007-fw.c b/drivers/staging/media/go7007/go7007-fw.c
index 814ce08bc44d..5f4c9b9e899a 100644
--- a/drivers/staging/media/go7007/go7007-fw.c
+++ b/drivers/staging/media/go7007/go7007-fw.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
/*
@@ -1432,22 +1428,26 @@ static int audio_to_package(struct go7007 *go, __le16 *code, int space)
static int modet_to_package(struct go7007 *go, __le16 *code, int space)
{
+ bool has_modet0 = go->modet[0].enable;
+ bool has_modet1 = go->modet[1].enable;
+ bool has_modet2 = go->modet[2].enable;
+ bool has_modet3 = go->modet[3].enable;
int ret, mb, i, addr, cnt = 0;
u16 pack[32];
u16 thresholds[] = {
0x200e, 0,
- 0xbf82, go->modet[0].pixel_threshold,
- 0xbf83, go->modet[1].pixel_threshold,
- 0xbf84, go->modet[2].pixel_threshold,
- 0xbf85, go->modet[3].pixel_threshold,
- 0xbf86, go->modet[0].motion_threshold,
- 0xbf87, go->modet[1].motion_threshold,
- 0xbf88, go->modet[2].motion_threshold,
- 0xbf89, go->modet[3].motion_threshold,
- 0xbf8a, go->modet[0].mb_threshold,
- 0xbf8b, go->modet[1].mb_threshold,
- 0xbf8c, go->modet[2].mb_threshold,
- 0xbf8d, go->modet[3].mb_threshold,
+ 0xbf82, has_modet0 ? go->modet[0].pixel_threshold : 32767,
+ 0xbf83, has_modet1 ? go->modet[1].pixel_threshold : 32767,
+ 0xbf84, has_modet2 ? go->modet[2].pixel_threshold : 32767,
+ 0xbf85, has_modet3 ? go->modet[3].pixel_threshold : 32767,
+ 0xbf86, has_modet0 ? go->modet[0].motion_threshold : 32767,
+ 0xbf87, has_modet1 ? go->modet[1].motion_threshold : 32767,
+ 0xbf88, has_modet2 ? go->modet[2].motion_threshold : 32767,
+ 0xbf89, has_modet3 ? go->modet[3].motion_threshold : 32767,
+ 0xbf8a, has_modet0 ? go->modet[0].mb_threshold : 32767,
+ 0xbf8b, has_modet1 ? go->modet[1].mb_threshold : 32767,
+ 0xbf8c, has_modet2 ? go->modet[2].mb_threshold : 32767,
+ 0xbf8d, has_modet3 ? go->modet[3].mb_threshold : 32767,
0xbf8e, 0,
0xbf8f, 0,
0, 0,
diff --git a/drivers/staging/media/go7007/go7007-i2c.c b/drivers/staging/media/go7007/go7007-i2c.c
index 4cf4c0d65085..55addfa855d4 100644
--- a/drivers/staging/media/go7007/go7007-i2c.c
+++ b/drivers/staging/media/go7007/go7007-i2c.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
diff --git a/drivers/staging/media/go7007/go7007-loader.c b/drivers/staging/media/go7007/go7007-loader.c
index 491d0e697f5a..042f78a31283 100644
--- a/drivers/staging/media/go7007/go7007-loader.c
+++ b/drivers/staging/media/go7007/go7007-loader.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
diff --git a/drivers/staging/media/go7007/go7007-priv.h b/drivers/staging/media/go7007/go7007-priv.h
index 6e16af720504..2251c3f99d1d 100644
--- a/drivers/staging/media/go7007/go7007-priv.h
+++ b/drivers/staging/media/go7007/go7007-priv.h
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
/*
@@ -75,6 +71,20 @@ struct go7007;
#define GO7007_AUDIO_I2S_MASTER (1<<16)
#define GO7007_AUDIO_OKI_MODE (1<<17)
+#define GO7007_CID_CUSTOM_BASE (V4L2_CID_DETECT_CLASS_BASE + 0x1000)
+#define V4L2_CID_PIXEL_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+1)
+#define V4L2_CID_MOTION_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+2)
+#define V4L2_CID_MB_THRESHOLD0 (GO7007_CID_CUSTOM_BASE+3)
+#define V4L2_CID_PIXEL_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+4)
+#define V4L2_CID_MOTION_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+5)
+#define V4L2_CID_MB_THRESHOLD1 (GO7007_CID_CUSTOM_BASE+6)
+#define V4L2_CID_PIXEL_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+7)
+#define V4L2_CID_MOTION_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+8)
+#define V4L2_CID_MB_THRESHOLD2 (GO7007_CID_CUSTOM_BASE+9)
+#define V4L2_CID_PIXEL_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+10)
+#define V4L2_CID_MOTION_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+11)
+#define V4L2_CID_MB_THRESHOLD3 (GO7007_CID_CUSTOM_BASE+12)
+
struct go7007_board_info {
unsigned int flags;
int hpi_buffer_cap;
@@ -168,6 +178,7 @@ struct go7007 {
struct v4l2_ctrl *mpeg_video_aspect_ratio;
struct v4l2_ctrl *mpeg_video_b_frames;
struct v4l2_ctrl *mpeg_video_rep_seqheader;
+ struct v4l2_ctrl *modet_mode;
enum { STATUS_INIT, STATUS_ONLINE, STATUS_SHUTDOWN } status;
spinlock_t spinlock;
struct mutex hw_lock;
@@ -216,6 +227,7 @@ struct go7007 {
} modet[4];
unsigned char modet_map[1624];
unsigned char active_map[216];
+ u32 modet_event_status;
/* Video streaming */
struct mutex queue_lock;
diff --git a/drivers/staging/media/go7007/go7007-usb.c b/drivers/staging/media/go7007/go7007-usb.c
index 2f62be905cd1..ece27ece8115 100644
--- a/drivers/staging/media/go7007/go7007-usb.c
+++ b/drivers/staging/media/go7007/go7007-usb.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
diff --git a/drivers/staging/media/go7007/go7007-v4l2.c b/drivers/staging/media/go7007/go7007-v4l2.c
index da7b5493e13e..ec799b4d88be 100644
--- a/drivers/staging/media/go7007/go7007-v4l2.c
+++ b/drivers/staging/media/go7007/go7007-v4l2.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -36,7 +32,6 @@
#include <media/videobuf2-vmalloc.h>
#include <media/saa7115.h>
-#include "go7007.h"
#include "go7007-priv.h"
#define call_all(dev, o, f, args...) \
@@ -189,7 +184,7 @@ static void set_formatting(struct go7007 *go)
static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
{
int sensor_height = 0, sensor_width = 0;
- int width, height, i;
+ int width, height;
if (fmt != NULL && !valid_pixelformat(fmt->fmt.pix.pixelformat))
return -EINVAL;
@@ -253,10 +248,6 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
go->height = height;
go->encoder_h_offset = go->board_info->sensor_h_offset;
go->encoder_v_offset = go->board_info->sensor_v_offset;
- for (i = 0; i < 4; ++i)
- go->modet[i].enable = 0;
- for (i = 0; i < 1624; ++i)
- go->modet_map[i] = 0;
if (go->board_info->sensor_flags & GO7007_SENSOR_SCALING) {
struct v4l2_mbus_framefmt mbus_fmt;
@@ -286,64 +277,6 @@ static int set_capture_size(struct go7007 *go, struct v4l2_format *fmt, int try)
return 0;
}
-#if 0
-static int clip_to_modet_map(struct go7007 *go, int region,
- struct v4l2_clip *clip_list)
-{
- struct v4l2_clip clip, *clip_ptr;
- int x, y, mbnum;
-
- /* Check if coordinates are OK and if any macroblocks are already
- * used by other regions (besides 0) */
- clip_ptr = clip_list;
- while (clip_ptr) {
- if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
- return -EFAULT;
- if (clip.c.left < 0 || (clip.c.left & 0xF) ||
- clip.c.width <= 0 || (clip.c.width & 0xF))
- return -EINVAL;
- if (clip.c.left + clip.c.width > go->width)
- return -EINVAL;
- if (clip.c.top < 0 || (clip.c.top & 0xF) ||
- clip.c.height <= 0 || (clip.c.height & 0xF))
- return -EINVAL;
- if (clip.c.top + clip.c.height > go->height)
- return -EINVAL;
- for (y = 0; y < clip.c.height; y += 16)
- for (x = 0; x < clip.c.width; x += 16) {
- mbnum = (go->width >> 4) *
- ((clip.c.top + y) >> 4) +
- ((clip.c.left + x) >> 4);
- if (go->modet_map[mbnum] != 0 &&
- go->modet_map[mbnum] != region)
- return -EBUSY;
- }
- clip_ptr = clip.next;
- }
-
- /* Clear old region macroblocks */
- for (mbnum = 0; mbnum < 1624; ++mbnum)
- if (go->modet_map[mbnum] == region)
- go->modet_map[mbnum] = 0;
-
- /* Claim macroblocks in this list */
- clip_ptr = clip_list;
- while (clip_ptr) {
- if (copy_from_user(&clip, clip_ptr, sizeof(clip)))
- return -EFAULT;
- for (y = 0; y < clip.c.height; y += 16)
- for (x = 0; x < clip.c.width; x += 16) {
- mbnum = (go->width >> 4) *
- ((clip.c.top + y) >> 4) +
- ((clip.c.left + x) >> 4);
- go->modet_map[mbnum] = region;
- }
- clip_ptr = clip.next;
- }
- return 0;
-}
-#endif
-
static int vidioc_querycap(struct file *file, void *priv,
struct v4l2_capability *cap)
{
@@ -495,6 +428,7 @@ static int go7007_start_streaming(struct vb2_queue *q, unsigned int count)
mutex_lock(&go->hw_lock);
go->next_seq = 0;
go->active_buf = NULL;
+ go->modet_event_status = 0;
q->streaming = 1;
if (go7007_start_encoder(go) < 0)
ret = -EIO;
@@ -850,41 +784,76 @@ static int vidioc_log_status(struct file *file, void *priv)
return call_all(&go->v4l2_dev, core, log_status);
}
-/* FIXME:
- Those ioctls are private, and not needed, since several standard
- extended controls already provide streaming control.
- So, those ioctls should be converted into vidioc_g_ext_ctrls()
- and vidioc_s_ext_ctrls()
- */
-
-#if 0
- case GO7007IOC_S_MD_PARAMS:
- {
- struct go7007_md_params *mdp = arg;
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
- if (mdp->region > 3)
- return -EINVAL;
- if (mdp->trigger > 0) {
- go->modet[mdp->region].pixel_threshold =
- mdp->pixel_threshold >> 1;
- go->modet[mdp->region].motion_threshold =
- mdp->motion_threshold >> 1;
- go->modet[mdp->region].mb_threshold =
- mdp->trigger >> 1;
- go->modet[mdp->region].enable = 1;
- } else
- go->modet[mdp->region].enable = 0;
- /* fall-through */
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(fh, sub);
+ case V4L2_EVENT_MOTION_DET:
+ /* Allow for up to 30 events (1 second for NTSC) to be
+ * stored. */
+ return v4l2_event_subscribe(fh, sub, 30, NULL);
}
- case GO7007IOC_S_MD_REGION:
- {
- struct go7007_md_region *region = arg;
+ return -EINVAL;
+}
- if (region->region < 1 || region->region > 3)
- return -EINVAL;
- return clip_to_modet_map(go, region->region, region->clips);
+
+static int go7007_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+ struct go7007 *go =
+ container_of(ctrl->handler, struct go7007, hdl);
+ unsigned y;
+ u8 *mt;
+
+ switch (ctrl->id) {
+ case V4L2_CID_PIXEL_THRESHOLD0:
+ go->modet[0].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD0:
+ go->modet[0].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD0:
+ go->modet[0].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD1:
+ go->modet[1].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD1:
+ go->modet[1].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD1:
+ go->modet[1].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD2:
+ go->modet[2].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD2:
+ go->modet[2].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD2:
+ go->modet[2].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_PIXEL_THRESHOLD3:
+ go->modet[3].pixel_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MOTION_THRESHOLD3:
+ go->modet[3].motion_threshold = ctrl->val;
+ break;
+ case V4L2_CID_MB_THRESHOLD3:
+ go->modet[3].mb_threshold = ctrl->val;
+ break;
+ case V4L2_CID_DETECT_MD_REGION_GRID:
+ mt = go->modet_map;
+ for (y = 0; y < go->height / 16; y++, mt += go->width / 16)
+ memcpy(mt, ctrl->p_new.p_u8 + y * (720 / 16), go->width / 16);
+ break;
+ default:
+ return -EINVAL;
}
-#endif
+ return 0;
+}
static struct v4l2_file_operations go7007_fops = {
.owner = THIS_MODULE,
@@ -926,7 +895,7 @@ static const struct v4l2_ioctl_ops video_ioctl_ops = {
.vidioc_enum_framesizes = vidioc_enum_framesizes,
.vidioc_enum_frameintervals = vidioc_enum_frameintervals,
.vidioc_log_status = vidioc_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_subscribe_event = vidioc_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
};
@@ -938,12 +907,144 @@ static struct video_device go7007_template = {
.tvnorms = V4L2_STD_ALL,
};
+static const struct v4l2_ctrl_ops go7007_ctrl_ops = {
+ .s_ctrl = go7007_s_ctrl,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD0,
+ .name = "Pixel Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD0,
+ .name = "Motion Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold0_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD0,
+ .name = "MB Threshold Region 0",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD1,
+ .name = "Pixel Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD1,
+ .name = "Motion Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold1_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD1,
+ .name = "MB Threshold Region 1",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD2,
+ .name = "Pixel Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD2,
+ .name = "Motion Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold2_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD2,
+ .name = "MB Threshold Region 2",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_pixel_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_PIXEL_THRESHOLD3,
+ .name = "Pixel Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 20,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_motion_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MOTION_THRESHOLD3,
+ .name = "Motion Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 80,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_threshold3_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_MB_THRESHOLD3,
+ .name = "MB Threshold Region 3",
+ .type = V4L2_CTRL_TYPE_INTEGER,
+ .def = 200,
+ .max = 32767,
+ .step = 1,
+};
+
+static const struct v4l2_ctrl_config go7007_mb_regions_ctrl = {
+ .ops = &go7007_ctrl_ops,
+ .id = V4L2_CID_DETECT_MD_REGION_GRID,
+ .dims = { 576 / 16, 720 / 16 },
+ .max = 3,
+ .step = 1,
+};
+
int go7007_v4l2_ctrl_init(struct go7007 *go)
{
struct v4l2_ctrl_handler *hdl = &go->hdl;
struct v4l2_ctrl *ctrl;
- v4l2_ctrl_handler_init(hdl, 13);
+ v4l2_ctrl_handler_init(hdl, 22);
go->mpeg_video_gop_size = v4l2_ctrl_new_std(hdl, NULL,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 0, 34, 1, 15);
go->mpeg_video_gop_closure = v4l2_ctrl_new_std(hdl, NULL,
@@ -968,6 +1069,24 @@ int go7007_v4l2_ctrl_init(struct go7007 *go)
V4L2_JPEG_ACTIVE_MARKER_DHT);
if (ctrl)
ctrl->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold0_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold1_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold2_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_pixel_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_motion_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_threshold3_ctrl, NULL);
+ v4l2_ctrl_new_custom(hdl, &go7007_mb_regions_ctrl, NULL);
+ go->modet_mode = v4l2_ctrl_new_std_menu(hdl, NULL,
+ V4L2_CID_DETECT_MD_MODE,
+ V4L2_DETECT_MD_MODE_REGION_GRID,
+ 1 << V4L2_DETECT_MD_MODE_THRESHOLD_GRID,
+ V4L2_DETECT_MD_MODE_DISABLED);
if (hdl->error) {
int rv = hdl->error;
@@ -1001,7 +1120,6 @@ int go7007_v4l2_init(struct go7007 *go)
*vdev = go7007_template;
vdev->lock = &go->serialize_lock;
vdev->queue = &go->vidq;
- set_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags);
video_set_drvdata(vdev, go);
vdev->v4l2_dev = &go->v4l2_dev;
if (!v4l2_device_has_op(&go->v4l2_dev, video, querystd))
diff --git a/drivers/staging/media/go7007/go7007.h b/drivers/staging/media/go7007/go7007.h
deleted file mode 100644
index 54b989738982..000000000000
--- a/drivers/staging/media/go7007/go7007.h
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Copyright (C) 2005-2006 Micronas USA Inc.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and the associated README documentation file (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sublicense, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
- * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
- * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- */
-
-struct go7007_md_params {
- __u16 region;
- __u16 trigger;
- __u16 pixel_threshold;
- __u16 motion_threshold;
- __u32 reserved[8];
-};
-
-struct go7007_md_region {
- __u16 region;
- __u16 flags;
- struct v4l2_clip *clips;
- __u32 reserved[8];
-};
-
-#define GO7007IOC_S_MD_PARAMS _IOWR('V', BASE_VIDIOC_PRIVATE + 6, \
- struct go7007_md_params)
-#define GO7007IOC_G_MD_PARAMS _IOR('V', BASE_VIDIOC_PRIVATE + 7, \
- struct go7007_md_params)
-#define GO7007IOC_S_MD_REGION _IOW('V', BASE_VIDIOC_PRIVATE + 8, \
- struct go7007_md_region)
diff --git a/drivers/staging/media/go7007/s2250-board.c b/drivers/staging/media/go7007/s2250-board.c
index eaa2b0990a1b..bb846680bcd4 100644
--- a/drivers/staging/media/go7007/s2250-board.c
+++ b/drivers/staging/media/go7007/s2250-board.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -573,11 +569,12 @@ static int s2250_probe(struct i2c_client *client,
if (mutex_lock_interruptible(&usb->i2c_lock) == 0) {
data = kzalloc(16, GFP_KERNEL);
if (data != NULL) {
- int rc;
- rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
+ int rc = go7007_usb_vendor_request(go, 0x41, 0, 0,
data, 16, 1);
+
if (rc > 0) {
u8 mask;
+
data[0] = 0;
mask = 1<<5;
data[0] &= ~mask;
diff --git a/drivers/staging/media/go7007/saa7134-go7007.c b/drivers/staging/media/go7007/saa7134-go7007.c
index e40f7fbfc0a5..b137432fa0e4 100644
--- a/drivers/staging/media/go7007/saa7134-go7007.c
+++ b/drivers/staging/media/go7007/saa7134-go7007.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/module.h>
@@ -33,7 +29,6 @@
#include "saa7134.h"
#include "saa7134-reg.h"
-#include "go7007.h"
#include "go7007-priv.h"
/*#define GO7007_HPI_DEBUG*/
@@ -168,7 +163,7 @@ static int saa7134_go7007_interface_reset(struct go7007 *go)
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
status = saa_readb(SAA7134_GPIO_GPSTATUS2);
- /*printk(KERN_DEBUG "status is %s\n", status & 0x40 ? "OK" : "not OK"); */
+ /*pr_debug("status is %s\n", status & 0x40 ? "OK" : "not OK"); */
/* enter command mode...(?) */
saa_writeb(SAA7134_GPIO_GPSTATUS2, GPIO_COMMAND_REQ1);
@@ -178,14 +173,13 @@ static int saa7134_go7007_interface_reset(struct go7007 *go)
saa_clearb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
saa_setb(SAA7134_GPIO_GPMODE3, SAA7134_GPIO_GPRESCAN);
status = saa_readb(SAA7134_GPIO_GPSTATUS2);
- /*printk(KERN_INFO "gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
+ /*pr_info("gpio is %08x\n", saa_readl(SAA7134_GPIO_GPSTATUS0 >> 2)); */
} while (--count > 0);
/* Wait for an interrupt to indicate successful hardware reset */
if (go7007_read_interrupt(go, &intr_val, &intr_data) < 0 ||
(intr_val & ~0x1) != 0x55aa) {
- printk(KERN_ERR
- "saa7134-go7007: unable to reset the GO7007\n");
+ pr_err("saa7134-go7007: unable to reset the GO7007\n");
return -1;
}
return 0;
@@ -199,8 +193,7 @@ static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
u16 status_reg;
#ifdef GO7007_HPI_DEBUG
- printk(KERN_DEBUG
- "saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
+ pr_debug("saa7134-go7007: WriteInterrupt: %04x %04x\n", addr, data);
#endif
for (i = 0; i < 100; ++i) {
@@ -210,8 +203,7 @@ static int saa7134_go7007_write_interrupt(struct go7007 *go, int addr, int data)
msleep(10);
}
if (i == 100) {
- printk(KERN_ERR
- "saa7134-go7007: device is hung, status reg = 0x%04x\n",
+ pr_err("saa7134-go7007: device is hung, status reg = 0x%04x\n",
status_reg);
return -1;
}
@@ -231,7 +223,7 @@ static int saa7134_go7007_read_interrupt(struct go7007 *go)
gpio_read(dev, HPI_ADDR_INTR_RET_VALUE, &go->interrupt_value);
gpio_read(dev, HPI_ADDR_INTR_RET_DATA, &go->interrupt_data);
#ifdef GO7007_HPI_DEBUG
- printk(KERN_DEBUG "saa7134-go7007: ReadInterrupt: %04x %04x\n",
+ pr_debug("saa7134-go7007: ReadInterrupt: %04x %04x\n",
go->interrupt_value, go->interrupt_data);
#endif
return 0;
@@ -246,7 +238,7 @@ static void saa7134_go7007_irq_ts_done(struct saa7134_dev *dev,
if (!vb2_is_streaming(&go->vidq))
return;
if (0 != (status & 0x000f0000))
- printk(KERN_DEBUG "saa7134-go7007: irq: lost %ld\n",
+ pr_debug("saa7134-go7007: irq: lost %ld\n",
(status >> 16) & 0x0f);
if (status & 0x100000) {
dma_sync_single_for_cpu(&dev->pci->dev,
@@ -356,8 +348,7 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
int i;
#ifdef GO7007_HPI_DEBUG
- printk(KERN_DEBUG "saa7134-go7007: DownloadBuffer "
- "sending %d bytes\n", len);
+ pr_debug("saa7134-go7007: DownloadBuffer sending %d bytes\n", len);
#endif
while (len > 0) {
@@ -379,8 +370,8 @@ static int saa7134_go7007_send_firmware(struct go7007 *go, u8 *data, int len)
break;
}
if (i == 100) {
- printk(KERN_ERR "saa7134-go7007: device is hung, "
- "status reg = 0x%04x\n", status_reg);
+ pr_err("saa7134-go7007: device is hung, status reg = 0x%04x\n",
+ status_reg);
return -1;
}
}
@@ -417,6 +408,7 @@ static int saa7134_go7007_s_ctrl(struct v4l2_subdev *sd,
{
struct saa7134_go7007 *saa = to_state(sd);
struct saa7134_dev *dev = saa->dev;
+
return saa7134_s_ctrl_internal(dev, NULL, ctrl);
}
@@ -425,6 +417,7 @@ static int saa7134_go7007_g_ctrl(struct v4l2_subdev *sd,
{
struct saa7134_go7007 *saa = to_state(sd);
struct saa7134_dev *dev = saa->dev;
+
return saa7134_g_ctrl_internal(dev, NULL, ctrl);
}
@@ -456,7 +449,7 @@ static int saa7134_go7007_init(struct saa7134_dev *dev)
struct saa7134_go7007 *saa;
struct v4l2_subdev *sd;
- printk(KERN_DEBUG "saa7134-go7007: probing new SAA713X board\n");
+ pr_debug("saa7134-go7007: probing new SAA713X board\n");
go = go7007_alloc(&board_voyager, &dev->pci->dev);
if (go == NULL)
@@ -501,7 +494,7 @@ static int saa7134_go7007_init(struct saa7134_dev *dev)
/* Register the subdevice interface with the go7007 device */
if (v4l2_device_register_subdev(&go->v4l2_dev, sd) < 0)
- printk(KERN_INFO "saa7134-go7007: register subdev failed\n");
+ pr_info("saa7134-go7007: register subdev failed\n");
dev->empress_dev = &go->vdev;
diff --git a/drivers/staging/media/go7007/snd-go7007.c b/drivers/staging/media/go7007/snd-go7007.c
index 9eb2a20ae40a..d22d7d574672 100644
--- a/drivers/staging/media/go7007/snd-go7007.c
+++ b/drivers/staging/media/go7007/snd-go7007.c
@@ -9,10 +9,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 59 Temple Place - Suite 330, Boston MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/msi3101/Kconfig b/drivers/staging/media/msi3101/Kconfig
deleted file mode 100644
index de0b3bba3873..000000000000
--- a/drivers/staging/media/msi3101/Kconfig
+++ /dev/null
@@ -1,10 +0,0 @@
-config USB_MSI3101
- tristate "Mirics MSi3101 SDR Dongle"
- depends on USB && VIDEO_DEV && VIDEO_V4L2 && SPI
- select VIDEOBUF2_CORE
- select VIDEOBUF2_VMALLOC
- select MEDIA_TUNER_MSI001
-
-config MEDIA_TUNER_MSI001
- tristate "Mirics MSi001"
- depends on VIDEO_V4L2 && SPI
diff --git a/drivers/staging/media/msi3101/Makefile b/drivers/staging/media/msi3101/Makefile
deleted file mode 100644
index daf4f58d9a56..000000000000
--- a/drivers/staging/media/msi3101/Makefile
+++ /dev/null
@@ -1,2 +0,0 @@
-obj-$(CONFIG_USB_MSI3101) += sdr-msi3101.o
-obj-$(CONFIG_MEDIA_TUNER_MSI001) += msi001.o
diff --git a/drivers/staging/media/omap4iss/iss.c b/drivers/staging/media/omap4iss/iss.c
index 2e422dde074e..d548371db65a 100644
--- a/drivers/staging/media/omap4iss/iss.c
+++ b/drivers/staging/media/omap4iss/iss.c
@@ -1003,33 +1003,18 @@ static void iss_disable_clocks(struct iss_device *iss)
clk_disable(iss->iss_fck);
}
-static void iss_put_clocks(struct iss_device *iss)
-{
- if (iss->iss_fck) {
- clk_put(iss->iss_fck);
- iss->iss_fck = NULL;
- }
-
- if (iss->iss_ctrlclk) {
- clk_put(iss->iss_ctrlclk);
- iss->iss_ctrlclk = NULL;
- }
-}
-
static int iss_get_clocks(struct iss_device *iss)
{
- iss->iss_fck = clk_get(iss->dev, "iss_fck");
+ iss->iss_fck = devm_clk_get(iss->dev, "iss_fck");
if (IS_ERR(iss->iss_fck)) {
dev_err(iss->dev, "Unable to get iss_fck clock info\n");
- iss_put_clocks(iss);
return PTR_ERR(iss->iss_fck);
}
- iss->iss_ctrlclk = clk_get(iss->dev, "iss_ctrlclk");
+ iss->iss_ctrlclk = devm_clk_get(iss->dev, "iss_ctrlclk");
if (IS_ERR(iss->iss_ctrlclk)) {
dev_err(iss->dev, "Unable to get iss_ctrlclk clock info\n");
- iss_put_clocks(iss);
- return PTR_ERR(iss->iss_fck);
+ return PTR_ERR(iss->iss_ctrlclk);
}
return 0;
@@ -1104,29 +1089,11 @@ static int iss_map_mem_resource(struct platform_device *pdev,
{
struct resource *mem;
- /* request the mem region for the camera registers */
-
mem = platform_get_resource(pdev, IORESOURCE_MEM, res);
- if (!mem) {
- dev_err(iss->dev, "no mem resource?\n");
- return -ENODEV;
- }
- if (!request_mem_region(mem->start, resource_size(mem), pdev->name)) {
- dev_err(iss->dev,
- "cannot reserve camera register I/O region\n");
- return -ENODEV;
- }
- iss->res[res] = mem;
+ iss->regs[res] = devm_ioremap_resource(iss->dev, mem);
- /* map the region */
- iss->regs[res] = ioremap_nocache(mem->start, resource_size(mem));
- if (!iss->regs[res]) {
- dev_err(iss->dev, "cannot map camera register I/O region\n");
- return -ENODEV;
- }
-
- return 0;
+ return PTR_ERR_OR_ZERO(iss->regs[res]);
}
static void iss_unregister_entities(struct iss_device *iss)
@@ -1389,7 +1356,7 @@ static int iss_probe(struct platform_device *pdev)
if (pdata == NULL)
return -EINVAL;
- iss = kzalloc(sizeof(*iss), GFP_KERNEL);
+ iss = devm_kzalloc(&pdev->dev, sizeof(*iss), GFP_KERNEL);
if (!iss) {
dev_err(&pdev->dev, "Could not allocate memory\n");
return -ENOMEM;
@@ -1456,7 +1423,8 @@ static int iss_probe(struct platform_device *pdev)
goto error_iss;
}
- if (request_irq(iss->irq_num, iss_isr, IRQF_SHARED, "OMAP4 ISS", iss)) {
+ if (devm_request_irq(iss->dev, iss->irq_num, iss_isr, IRQF_SHARED,
+ "OMAP4 ISS", iss)) {
dev_err(iss->dev, "Unable to request IRQ\n");
ret = -EINVAL;
goto error_iss;
@@ -1465,7 +1433,7 @@ static int iss_probe(struct platform_device *pdev)
/* Entities */
ret = iss_initialize_modules(iss);
if (ret < 0)
- goto error_irq;
+ goto error_iss;
ret = iss_register_entities(iss);
if (ret < 0)
@@ -1477,29 +1445,12 @@ static int iss_probe(struct platform_device *pdev)
error_modules:
iss_cleanup_modules(iss);
-error_irq:
- free_irq(iss->irq_num, iss);
error_iss:
omap4iss_put(iss);
error:
- iss_put_clocks(iss);
-
- for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
- if (iss->regs[i]) {
- iounmap(iss->regs[i]);
- iss->regs[i] = NULL;
- }
-
- if (iss->res[i]) {
- release_mem_region(iss->res[i]->start,
- resource_size(iss->res[i]));
- iss->res[i] = NULL;
- }
- }
platform_set_drvdata(pdev, NULL);
mutex_destroy(&iss->iss_mutex);
- kfree(iss);
return ret;
}
@@ -1507,29 +1458,10 @@ error:
static int iss_remove(struct platform_device *pdev)
{
struct iss_device *iss = platform_get_drvdata(pdev);
- unsigned int i;
iss_unregister_entities(iss);
iss_cleanup_modules(iss);
- free_irq(iss->irq_num, iss);
- iss_put_clocks(iss);
-
- for (i = 0; i < OMAP4_ISS_MEM_LAST; i++) {
- if (iss->regs[i]) {
- iounmap(iss->regs[i]);
- iss->regs[i] = NULL;
- }
-
- if (iss->res[i]) {
- release_mem_region(iss->res[i]->start,
- resource_size(iss->res[i]));
- iss->res[i] = NULL;
- }
- }
-
- kfree(iss);
-
return 0;
}
diff --git a/drivers/staging/media/omap4iss/iss_video.c b/drivers/staging/media/omap4iss/iss_video.c
index cbf455d66f73..943b5b09c632 100644
--- a/drivers/staging/media/omap4iss/iss_video.c
+++ b/drivers/staging/media/omap4iss/iss_video.c
@@ -25,6 +25,9 @@
#include "iss_video.h"
#include "iss.h"
+static unsigned debug;
+module_param(debug, uint, 0644);
+MODULE_PARM_DESC(debug, "activates debug info");
/* -----------------------------------------------------------------------------
* Helper functions
@@ -328,15 +331,6 @@ static int iss_video_buf_prepare(struct vb2_buffer *vb)
if (vb2_plane_size(vb, 0) < size)
return -ENOBUFS;
- /* Refuse to prepare the buffer is the video node has registered an
- * error. We don't need to take any lock here as the operation is
- * inherently racy. The authoritative check will be performed in the
- * queue handler, which can't return an error, this check is just a best
- * effort to notify userspace as early as possible.
- */
- if (unlikely(video->error))
- return -EIO;
-
addr = vb2_dma_contig_plane_dma_addr(vb, 0);
if (!IS_ALIGNED(addr, 32)) {
dev_dbg(video->iss->dev,
@@ -360,6 +354,11 @@ static void iss_video_buf_queue(struct vb2_buffer *vb)
spin_lock_irqsave(&video->qlock, flags);
+ /* Mark the buffer is faulty and give it back to the queue immediately
+ * if the video node has registered an error. vb2 will perform the same
+ * check when preparing the buffer, but that is inherently racy, so we
+ * need to handle the race condition with an authoritative check here.
+ */
if (unlikely(video->error)) {
vb2_buffer_done(vb, VB2_BUF_STATE_ERROR);
spin_unlock_irqrestore(&video->qlock, flags);
@@ -510,6 +509,7 @@ void omap4iss_video_cancel_stream(struct iss_video *video)
vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
}
+ vb2_queue_error(video->queue);
video->error = true;
spin_unlock_irqrestore(&video->qlock, flags);
@@ -895,7 +895,6 @@ iss_video_streamon(struct file *file, void *fh, enum v4l2_buf_type type)
video->queue = &vfh->queue;
INIT_LIST_HEAD(&video->dmaqueue);
- spin_lock_init(&video->qlock);
video->error = false;
atomic_set(&pipe->frame_number, -1);
@@ -1044,6 +1043,8 @@ static int iss_video_open(struct file *file)
if (handle == NULL)
return -ENOMEM;
+ video->video.debug = debug;
+
v4l2_fh_init(&handle->vfh, &video->video);
v4l2_fh_add(&handle->vfh);
@@ -1175,6 +1176,7 @@ int omap4iss_video_init(struct iss_video *video, const char *name)
if (ret < 0)
return ret;
+ spin_lock_init(&video->qlock);
mutex_init(&video->mutex);
atomic_set(&video->active, 0);
diff --git a/drivers/staging/media/rtl2832u_sdr/Kconfig b/drivers/staging/media/rtl2832u_sdr/Kconfig
deleted file mode 100644
index 3ede5fe8f0a5..000000000000
--- a/drivers/staging/media/rtl2832u_sdr/Kconfig
+++ /dev/null
@@ -1,7 +0,0 @@
-config DVB_RTL2832_SDR
- tristate "Realtek RTL2832 SDR"
- depends on USB && DVB_CORE && I2C && VIDEO_V4L2 && DVB_USB_RTL28XXU
- select DVB_RTL2832
- select VIDEOBUF2_VMALLOC
- default m if !MEDIA_SUBDRV_AUTOSELECT
-
diff --git a/drivers/staging/media/rtl2832u_sdr/Makefile b/drivers/staging/media/rtl2832u_sdr/Makefile
deleted file mode 100644
index 7e00a0df4631..000000000000
--- a/drivers/staging/media/rtl2832u_sdr/Makefile
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CONFIG_DVB_RTL2832_SDR) += rtl2832_sdr.o
-
-ccflags-y += -Idrivers/media/dvb-core
-ccflags-y += -Idrivers/media/dvb-frontends
-ccflags-y += -Idrivers/media/tuners
-ccflags-y += -Idrivers/media/usb/dvb-usb-v2
diff --git a/drivers/staging/media/sn9c102/Kconfig b/drivers/staging/media/sn9c102/Kconfig
deleted file mode 100644
index c9aba59258d9..000000000000
--- a/drivers/staging/media/sn9c102/Kconfig
+++ /dev/null
@@ -1,17 +0,0 @@
-config USB_SN9C102
- tristate "USB SN9C1xx PC Camera Controller support (DEPRECATED)"
- depends on VIDEO_V4L2 && MEDIA_USB_SUPPORT
- ---help---
- This driver is DEPRECATED, please use the gspca sonixb and
- sonixj modules instead.
-
- Say Y here if you want support for cameras based on SONiX SN9C101,
- SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers.
-
- See <file:drivers/staging/media/sn9c102/sn9c102.txt> for more info.
-
- If you have webcams that are only supported by this driver and not by
- the gspca driver, then contact the linux-media mailinglist.
-
- To compile this driver as a module, choose M here: the
- module will be called sn9c102.
diff --git a/drivers/staging/media/sn9c102/Makefile b/drivers/staging/media/sn9c102/Makefile
deleted file mode 100644
index 7ecd5a90c7c9..000000000000
--- a/drivers/staging/media/sn9c102/Makefile
+++ /dev/null
@@ -1,15 +0,0 @@
-sn9c102-objs := sn9c102_core.o \
- sn9c102_hv7131d.o \
- sn9c102_hv7131r.o \
- sn9c102_mi0343.o \
- sn9c102_mi0360.o \
- sn9c102_mt9v111.o \
- sn9c102_ov7630.o \
- sn9c102_ov7660.o \
- sn9c102_pas106b.o \
- sn9c102_pas202bcb.o \
- sn9c102_tas5110c1b.o \
- sn9c102_tas5110d.o \
- sn9c102_tas5130d1b.o
-
-obj-$(CONFIG_USB_SN9C102) += sn9c102.o
diff --git a/drivers/staging/media/sn9c102/sn9c102.h b/drivers/staging/media/sn9c102/sn9c102.h
deleted file mode 100644
index 37ca7225fcf7..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102.h
+++ /dev/null
@@ -1,214 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers *
- * *
- * Copyright (C) 2004-2006 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#ifndef _SN9C102_H_
-#define _SN9C102_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <media/v4l2-common.h>
-#include <media/v4l2-ioctl.h>
-#include <media/v4l2-device.h>
-#include <linux/device.h>
-#include <linux/list.h>
-#include <linux/spinlock.h>
-#include <linux/time.h>
-#include <linux/wait.h>
-#include <linux/types.h>
-#include <linux/param.h>
-#include <linux/rwsem.h>
-#include <linux/mutex.h>
-#include <linux/string.h>
-#include <linux/stddef.h>
-#include <linux/kref.h>
-
-#include "sn9c102_config.h"
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-enum sn9c102_frame_state {
- F_UNUSED,
- F_QUEUED,
- F_GRABBING,
- F_DONE,
- F_ERROR,
-};
-
-struct sn9c102_frame_t {
- void *bufmem;
- struct v4l2_buffer buf;
- enum sn9c102_frame_state state;
- struct list_head frame;
- unsigned long vma_use_count;
-};
-
-enum sn9c102_dev_state {
- DEV_INITIALIZED = 0x01,
- DEV_DISCONNECTED = 0x02,
- DEV_MISCONFIGURED = 0x04,
-};
-
-enum sn9c102_io_method {
- IO_NONE,
- IO_READ,
- IO_MMAP,
-};
-
-enum sn9c102_stream_state {
- STREAM_OFF,
- STREAM_INTERRUPT,
- STREAM_ON,
-};
-
-typedef char sn9c102_sof_header_t[62];
-
-struct sn9c102_sof_t {
- sn9c102_sof_header_t header;
- u16 bytesread;
-};
-
-struct sn9c102_sysfs_attr {
- u16 reg, i2c_reg;
- sn9c102_sof_header_t frame_header;
-};
-
-struct sn9c102_module_param {
- u8 force_munmap;
- u16 frame_timeout;
-};
-
-static DEFINE_MUTEX(sn9c102_sysfs_lock);
-static DECLARE_RWSEM(sn9c102_dev_lock);
-
-struct sn9c102_device {
- struct video_device *v4ldev;
-
- struct v4l2_device v4l2_dev;
-
- enum sn9c102_bridge bridge;
- struct sn9c102_sensor sensor;
-
- struct usb_device *usbdev;
- struct urb *urb[SN9C102_URBS];
- void *transfer_buffer[SN9C102_URBS];
- u8 *control_buffer;
-
- struct sn9c102_frame_t *frame_current, frame[SN9C102_MAX_FRAMES];
- struct list_head inqueue, outqueue;
- u32 frame_count, nbuffers, nreadbuffers;
-
- enum sn9c102_io_method io;
- enum sn9c102_stream_state stream;
-
- struct v4l2_jpegcompression compression;
-
- struct sn9c102_sysfs_attr sysfs;
- struct sn9c102_sof_t sof;
- u16 reg[384];
-
- struct sn9c102_module_param module_param;
-
- struct kref kref;
- enum sn9c102_dev_state state;
- u8 users;
-
- struct completion probe;
- struct mutex open_mutex, fileop_mutex;
- spinlock_t queue_lock;
- wait_queue_head_t wait_open, wait_frame, wait_stream;
-};
-
-/*****************************************************************************/
-
-struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id)
-{
- return usb_match_id(usb_ifnum_to_if(cam->usbdev, 0), id) ? cam : NULL;
-}
-
-
-void
-sn9c102_attach_sensor(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor)
-{
- memcpy(&cam->sensor, sensor, sizeof(struct sn9c102_sensor));
-}
-
-
-enum sn9c102_bridge
-sn9c102_get_bridge(struct sn9c102_device *cam)
-{
- return cam->bridge;
-}
-
-
-struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam)
-{
- return &cam->sensor;
-}
-
-/*****************************************************************************/
-
-#undef DBG
-#undef KDBG
-#ifdef SN9C102_DEBUG
-# define DBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1) \
- dev_err(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) == 2) \
- dev_info(&cam->usbdev->dev, fmt "\n", ## args); \
- else if ((level) >= 3) \
- dev_info(&cam->usbdev->dev, "[%s:%d] " fmt "\n", \
- __func__, __LINE__ , ## args); \
- } \
-} while (0)
-# define V4LDBG(level, name, cmd) \
-do { \
- if (debug >= (level)) \
- v4l_printk_ioctl(name, cmd); \
-} while (0)
-# define KDBG(level, fmt, args...) \
-do { \
- if (debug >= (level)) { \
- if ((level) == 1 || (level) == 2) \
- pr_info("sn9c102: " fmt "\n", ## args); \
- else if ((level) == 3) \
- pr_debug("sn9c102: [%s:%d] " fmt "\n", \
- __func__, __LINE__ , ## args); \
- } \
-} while (0)
-#else
-# define DBG(level, fmt, args...) do { ; } while (0)
-# define V4LDBG(level, name, cmd) do { ; } while (0)
-# define KDBG(level, fmt, args...) do { ; } while (0)
-#endif
-
-#undef PDBG
-#define PDBG(fmt, args...) \
-dev_info(&cam->usbdev->dev, "[%s:%s:%d] " fmt "\n", __FILE__, __func__, \
- __LINE__ , ## args)
-
-#undef PDBGG
-#define PDBGG(fmt, args...) do { ; } while (0) /* placeholder */
-
-#endif /* _SN9C102_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102.txt b/drivers/staging/media/sn9c102/sn9c102.txt
deleted file mode 100644
index b4f67040403a..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102.txt
+++ /dev/null
@@ -1,592 +0,0 @@
-
- SN9C1xx PC Camera Controllers
- Driver for Linux
- =============================
-
- - Documentation -
-
-
-Index
-=====
-1. Copyright
-2. Disclaimer
-3. License
-4. Overview and features
-5. Module dependencies
-6. Module loading
-7. Module parameters
-8. Optional device control through "sysfs"
-9. Supported devices
-10. Notes for V4L2 application developers
-11. Video frame formats
-12. Contact information
-13. Credits
-
-
-1. Copyright
-============
-Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it>
-
-
-2. Disclaimer
-=============
-SONiX is a trademark of SONiX Technology Company Limited, inc.
-This software is not sponsored or developed by SONiX.
-
-
-3. License
-==========
-This program is free software; you can redistribute it and/or modify
-it under the terms of the GNU General Public License as published by
-the Free Software Foundation; either version 2 of the License, or
-(at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-You should have received a copy of the GNU General Public License
-along with this program; if not, write to the Free Software
-Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-
-
-4. Overview and features
-========================
-This driver attempts to support the video interface of the devices assembling
-the SONiX SN9C101, SN9C102, SN9C103, SN9C105 and SN9C120 PC Camera Controllers
-("SN9C1xx" from now on).
-
-The driver relies on the Video4Linux2 and USB core modules. It has been
-designed to run properly on SMP systems as well.
-
-The latest version of the SN9C1xx driver can be found at the following URL:
-http://www.linux-projects.org/
-
-Some of the features of the driver are:
-
-- full compliance with the Video4Linux2 API (see also "Notes for V4L2
- application developers" paragraph);
-- available mmap or read/poll methods for video streaming through isochronous
- data transfers;
-- automatic detection of image sensor;
-- support for built-in microphone interface;
-- support for any window resolutions and optional panning within the maximum
- pixel area of image sensor;
-- image downscaling with arbitrary scaling factors from 1, 2 and 4 in both
- directions (see "Notes for V4L2 application developers" paragraph);
-- two different video formats for uncompressed or compressed data in low or
- high compression quality (see also "Notes for V4L2 application developers"
- and "Video frame formats" paragraphs);
-- full support for the capabilities of many of the possible image sensors that
- can be connected to the SN9C1xx bridges, including, for instance, red, green,
- blue and global gain adjustments and exposure (see "Supported devices"
- paragraph for details);
-- use of default color settings for sunlight conditions;
-- dynamic I/O interface for both SN9C1xx and image sensor control and
- monitoring (see "Optional device control through 'sysfs'" paragraph);
-- dynamic driver control thanks to various module parameters (see "Module
- parameters" paragraph);
-- up to 64 cameras can be handled at the same time; they can be connected and
- disconnected from the host many times without turning off the computer, if
- the system supports hotplugging;
-- no known bugs.
-
-
-5. Module dependencies
-======================
-For it to work properly, the driver needs kernel support for Video4Linux and
-USB.
-
-The following options of the kernel configuration file must be enabled and
-corresponding modules must be compiled:
-
- # Multimedia devices
- #
- CONFIG_VIDEO_DEV=m
-
-To enable advanced debugging functionality on the device through /sysfs:
-
- # Multimedia devices
- #
- CONFIG_VIDEO_ADV_DEBUG=y
-
- # USB support
- #
- CONFIG_USB=m
-
-In addition, depending on the hardware being used, the modules below are
-necessary:
-
- # USB Host Controller Drivers
- #
- CONFIG_USB_EHCI_HCD=m
- CONFIG_USB_UHCI_HCD=m
- CONFIG_USB_OHCI_HCD=m
-
-The SN9C103, SN9c105 and SN9C120 controllers also provide a built-in microphone
-interface. It is supported by the USB Audio driver thanks to the ALSA API:
-
- # Sound
- #
- CONFIG_SOUND=y
-
- # Advanced Linux Sound Architecture
- #
- CONFIG_SND=m
-
- # USB devices
- #
- CONFIG_SND_USB_AUDIO=m
-
-And finally:
-
- # USB Multimedia devices
- #
- CONFIG_USB_SN9C102=m
-
-
-6. Module loading
-=================
-To use the driver, it is necessary to load the "sn9c102" module into memory
-after every other module required: "videodev", "v4l2_common", "compat_ioctl32",
-"usbcore" and, depending on the USB host controller you have, "ehci-hcd",
-"uhci-hcd" or "ohci-hcd".
-
-Loading can be done as shown below:
-
- [root@localhost home]# modprobe sn9c102
-
-Note that the module is called "sn9c102" for historic reasons, although it
-does not just support the SN9C102.
-
-At this point all the devices supported by the driver and connected to the USB
-ports should be recognized. You can invoke "dmesg" to analyze kernel messages
-and verify that the loading process has gone well:
-
- [user@localhost home]$ dmesg
-
-or, to isolate all the kernel messages generated by the driver:
-
- [user@localhost home]$ dmesg | grep sn9c102
-
-
-7. Module parameters
-====================
-Module parameters are listed below:
--------------------------------------------------------------------------------
-Name: video_nr
-Type: short array (min = 0, max = 64)
-Syntax: <-1|n[,...]>
-Description: Specify V4L2 minor mode number:
- -1 = use next available
- n = use minor number n
- You can specify up to 64 cameras this way.
- For example:
- video_nr=-1,2,-1 would assign minor number 2 to the second
- recognized camera and use auto for the first one and for every
- other camera.
-Default: -1
--------------------------------------------------------------------------------
-Name: force_munmap
-Type: bool array (min = 0, max = 64)
-Syntax: <0|1[,...]>
-Description: Force the application to unmap previously mapped buffer memory
- before calling any VIDIOC_S_CROP or VIDIOC_S_FMT ioctl's. Not
- all the applications support this feature. This parameter is
- specific for each detected camera.
- 0 = do not force memory unmapping
- 1 = force memory unmapping (save memory)
-Default: 0
--------------------------------------------------------------------------------
-Name: frame_timeout
-Type: uint array (min = 0, max = 64)
-Syntax: <0|n[,...]>
-Description: Timeout for a video frame in seconds before returning an I/O
- error; 0 for infinity. This parameter is specific for each
- detected camera and can be changed at runtime thanks to the
- /sys filesystem interface.
-Default: 2
--------------------------------------------------------------------------------
-Name: debug
-Type: ushort
-Syntax: <n>
-Description: Debugging information level, from 0 to 3:
- 0 = none (use carefully)
- 1 = critical errors
- 2 = significant information
- 3 = more verbose messages
- Level 3 is useful for testing only. It also shows some more
- information about the hardware being detected.
- This parameter can be changed at runtime thanks to the /sys
- filesystem interface.
-Default: 2
--------------------------------------------------------------------------------
-
-
-8. Optional device control through "sysfs" [1]
-==========================================
-If the kernel has been compiled with the CONFIG_VIDEO_ADV_DEBUG option enabled,
-it is possible to read and write both the SN9C1xx and the image sensor
-registers by using the "sysfs" filesystem interface.
-
-Every time a supported device is recognized, a write-only file named "green" is
-created in the /sys/class/video4linux/videoX directory. You can set the green
-channel's gain by writing the desired value to it. The value may range from 0
-to 15 for the SN9C101 or SN9C102 bridges, from 0 to 127 for the SN9C103,
-SN9C105 and SN9C120 bridges.
-Similarly, only for the SN9C103, SN9C105 and SN9C120 controllers, blue and red
-gain control files are available in the same directory, for which accepted
-values may range from 0 to 127.
-
-There are other four entries in the directory above for each registered camera:
-"reg", "val", "i2c_reg" and "i2c_val". The first two files control the
-SN9C1xx bridge, while the other two control the sensor chip. "reg" and
-"i2c_reg" hold the values of the current register index where the following
-reading/writing operations are addressed at through "val" and "i2c_val". Their
-use is not intended for end-users. Note that "i2c_reg" and "i2c_val" will not
-be created if the sensor does not actually support the standard I2C protocol or
-its registers are not 8-bit long. Also, remember that you must be logged in as
-root before writing to them.
-
-As an example, suppose we were to want to read the value contained in the
-register number 1 of the sensor register table - which is usually the product
-identifier - of the camera registered as "/dev/video0":
-
- [root@localhost #] cd /sys/class/video4linux/video0
- [root@localhost #] echo 1 > i2c_reg
- [root@localhost #] cat i2c_val
-
-Note that "cat" will fail if sensor registers cannot be read.
-
-Now let's set the green gain's register of the SN9C101 or SN9C102 chips to 2:
-
- [root@localhost #] echo 0x11 > reg
- [root@localhost #] echo 2 > val
-
-Note that the SN9C1xx always returns 0 when some of its registers are read.
-To avoid race conditions, all the I/O accesses to the above files are
-serialized.
-The sysfs interface also provides the "frame_header" entry, which exports the
-frame header of the most recent requested and captured video frame. The header
-is always 18-bytes long and is appended to every video frame by the SN9C1xx
-controllers. As an example, this additional information can be used by the user
-application for implementing auto-exposure features via software.
-
-The following table describes the frame header exported by the SN9C101 and
-SN9C102:
-
-Byte # Value or bits Description
------- ------------- -----------
-0x00 0xFF Frame synchronisation pattern
-0x01 0xFF Frame synchronisation pattern
-0x02 0x00 Frame synchronisation pattern
-0x03 0xC4 Frame synchronisation pattern
-0x04 0xC4 Frame synchronisation pattern
-0x05 0x96 Frame synchronisation pattern
-0x06 [3:0] Read channel gain control = (1+R_GAIN/8)
- [7:4] Blue channel gain control = (1+B_GAIN/8)
-0x07 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled
- [2:1] Maximum scale factor for compression
- [ 3 ] 1 = USB fifo(2K bytes) is full
- [ 4 ] 1 = Digital gain is finish
- [ 5 ] 1 = Exposure is finish
- [7:6] Frame index
-0x08 [7:0] Y sum inside Auto-Exposure area (low-byte)
-0x09 [7:0] Y sum inside Auto-Exposure area (high-byte)
- where Y sum = (R/4 + 5G/16 + B/8) / 32
-0x0A [7:0] Y sum outside Auto-Exposure area (low-byte)
-0x0B [7:0] Y sum outside Auto-Exposure area (high-byte)
- where Y sum = (R/4 + 5G/16 + B/8) / 128
-0x0C 0xXX Not used
-0x0D 0xXX Not used
-0x0E 0xXX Not used
-0x0F 0xXX Not used
-0x10 0xXX Not used
-0x11 0xXX Not used
-
-The following table describes the frame header exported by the SN9C103:
-
-Byte # Value or bits Description
------- ------------- -----------
-0x00 0xFF Frame synchronisation pattern
-0x01 0xFF Frame synchronisation pattern
-0x02 0x00 Frame synchronisation pattern
-0x03 0xC4 Frame synchronisation pattern
-0x04 0xC4 Frame synchronisation pattern
-0x05 0x96 Frame synchronisation pattern
-0x06 [6:0] Read channel gain control = (1/2+R_GAIN/64)
-0x07 [6:0] Blue channel gain control = (1/2+B_GAIN/64)
- [7:4]
-0x08 [ 0 ] Compression mode. 0=No compression, 1=Compression enabled
- [2:1] Maximum scale factor for compression
- [ 3 ] 1 = USB fifo(2K bytes) is full
- [ 4 ] 1 = Digital gain is finish
- [ 5 ] 1 = Exposure is finish
- [7:6] Frame index
-0x09 [7:0] Y sum inside Auto-Exposure area (low-byte)
-0x0A [7:0] Y sum inside Auto-Exposure area (high-byte)
- where Y sum = (R/4 + 5G/16 + B/8) / 32
-0x0B [7:0] Y sum outside Auto-Exposure area (low-byte)
-0x0C [7:0] Y sum outside Auto-Exposure area (high-byte)
- where Y sum = (R/4 + 5G/16 + B/8) / 128
-0x0D [1:0] Audio frame number
- [ 2 ] 1 = Audio is recording
-0x0E [7:0] Audio summation (low-byte)
-0x0F [7:0] Audio summation (high-byte)
-0x10 [7:0] Audio sample count
-0x11 [7:0] Audio peak data in audio frame
-
-The AE area (sx, sy, ex, ey) in the active window can be set by programming the
-registers 0x1c, 0x1d, 0x1e and 0x1f of the SN9C1xx controllers, where one unit
-corresponds to 32 pixels.
-
-[1] The frame headers exported by the SN9C105 and SN9C120 are not described.
-
-
-9. Supported devices
-====================
-None of the names of the companies as well as their products will be mentioned
-here. They have never collaborated with the author, so no advertising.
-
-From the point of view of a driver, what unambiguously identify a device are
-its vendor and product USB identifiers. Below is a list of known identifiers of
-devices assembling the SN9C1xx PC camera controllers:
-
-Vendor ID Product ID
---------- ----------
-0x0458 0x7025
-0x045e 0x00f5
-0x045e 0x00f7
-0x0471 0x0327
-0x0471 0x0328
-0x0c45 0x6001
-0x0c45 0x6005
-0x0c45 0x6007
-0x0c45 0x6009
-0x0c45 0x600d
-0x0c45 0x6011
-0x0c45 0x6019
-0x0c45 0x6024
-0x0c45 0x6025
-0x0c45 0x6028
-0x0c45 0x6029
-0x0c45 0x602a
-0x0c45 0x602b
-0x0c45 0x602c
-0x0c45 0x602d
-0x0c45 0x602e
-0x0c45 0x6030
-0x0c45 0x603f
-0x0c45 0x6080
-0x0c45 0x6082
-0x0c45 0x6083
-0x0c45 0x6088
-0x0c45 0x608a
-0x0c45 0x608b
-0x0c45 0x608c
-0x0c45 0x608e
-0x0c45 0x608f
-0x0c45 0x60a0
-0x0c45 0x60a2
-0x0c45 0x60a3
-0x0c45 0x60a8
-0x0c45 0x60aa
-0x0c45 0x60ab
-0x0c45 0x60ac
-0x0c45 0x60ae
-0x0c45 0x60af
-0x0c45 0x60b0
-0x0c45 0x60b2
-0x0c45 0x60b3
-0x0c45 0x60b8
-0x0c45 0x60ba
-0x0c45 0x60bb
-0x0c45 0x60bc
-0x0c45 0x60be
-0x0c45 0x60c0
-0x0c45 0x60c2
-0x0c45 0x60c8
-0x0c45 0x60cc
-0x0c45 0x60ea
-0x0c45 0x60ec
-0x0c45 0x60ef
-0x0c45 0x60fa
-0x0c45 0x60fb
-0x0c45 0x60fc
-0x0c45 0x60fe
-0x0c45 0x6102
-0x0c45 0x6108
-0x0c45 0x610f
-0x0c45 0x6130
-0x0c45 0x6138
-0x0c45 0x613a
-0x0c45 0x613b
-0x0c45 0x613c
-0x0c45 0x613e
-
-The list above does not imply that all those devices work with this driver: up
-until now only the ones that assemble the following pairs of SN9C1xx bridges
-and image sensors are supported; kernel messages will always tell you whether
-this is the case (see "Module loading" paragraph):
-
-Image sensor / SN9C1xx bridge | SN9C10[12] SN9C103 SN9C105 SN9C120
--------------------------------------------------------------------------------
-HV7131D Hynix Semiconductor | Yes No No No
-HV7131R Hynix Semiconductor | No Yes Yes Yes
-MI-0343 Micron Technology | Yes No No No
-MI-0360 Micron Technology | No Yes Yes Yes
-OV7630 OmniVision Technologies | Yes Yes Yes Yes
-OV7660 OmniVision Technologies | No No Yes Yes
-PAS106B PixArt Imaging | Yes No No No
-PAS202B PixArt Imaging | Yes Yes No No
-TAS5110C1B Taiwan Advanced Sensor | Yes No No No
-TAS5110D Taiwan Advanced Sensor | Yes No No No
-TAS5130D1B Taiwan Advanced Sensor | Yes No No No
-
-"Yes" means that the pair is supported by the driver, while "No" means that the
-pair does not exist or is not supported by the driver.
-
-Only some of the available control settings of each image sensor are supported
-through the V4L2 interface.
-
-Donations of new models for further testing and support would be much
-appreciated. Non-available hardware will not be supported by the author of this
-driver.
-
-
-10. Notes for V4L2 application developers
-=========================================
-This driver follows the V4L2 API specifications. In particular, it enforces two
-rules:
-
-- exactly one I/O method, either "mmap" or "read", is associated with each
-file descriptor. Once it is selected, the application must close and reopen the
-device to switch to the other I/O method;
-
-- although it is not mandatory, previously mapped buffer memory should always
-be unmapped before calling any "VIDIOC_S_CROP" or "VIDIOC_S_FMT" ioctl's.
-The same number of buffers as before will be allocated again to match the size
-of the new video frames, so you have to map the buffers again before any I/O
-attempts on them.
-
-Consistently with the hardware limits, this driver also supports image
-downscaling with arbitrary scaling factors from 1, 2 and 4 in both directions.
-However, the V4L2 API specifications don't correctly define how the scaling
-factor can be chosen arbitrarily by the "negotiation" of the "source" and
-"target" rectangles. To work around this flaw, we have added the convention
-that, during the negotiation, whenever the "VIDIOC_S_CROP" ioctl is issued, the
-scaling factor is restored to 1.
-
-This driver supports two different video formats: the first one is the "8-bit
-Sequential Bayer" format and can be used to obtain uncompressed video data
-from the device through the current I/O method, while the second one provides
-either "raw" compressed video data (without frame headers not related to the
-compressed data) or standard JPEG (with frame headers). The compression quality
-may vary from 0 to 1 and can be selected or queried thanks to the
-VIDIOC_S_JPEGCOMP and VIDIOC_G_JPEGCOMP V4L2 ioctl's. For maximum flexibility,
-both the default active video format and the default compression quality
-depend on how the image sensor being used is initialized.
-
-
-11. Video frame formats [1]
-=======================
-The SN9C1xx PC Camera Controllers can send images in two possible video
-formats over the USB: either native "Sequential RGB Bayer" or compressed.
-The compression is used to achieve high frame rates. With regard to the
-SN9C101, SN9C102 and SN9C103, the compression is based on the Huffman encoding
-algorithm described below, while with regard to the SN9C105 and SN9C120 the
-compression is based on the JPEG standard.
-The current video format may be selected or queried from the user application
-by calling the VIDIOC_S_FMT or VIDIOC_G_FMT ioctl's, as described in the V4L2
-API specifications.
-
-The name "Sequential Bayer" indicates the organization of the red, green and
-blue pixels in one video frame. Each pixel is associated with a 8-bit long
-value and is disposed in memory according to the pattern shown below:
-
-B[0] G[1] B[2] G[3] ... B[m-2] G[m-1]
-G[m] R[m+1] G[m+2] R[m+2] ... G[2m-2] R[2m-1]
-...
-... B[(n-1)(m-2)] G[(n-1)(m-1)]
-... G[n(m-2)] R[n(m-1)]
-
-The above matrix also represents the sequential or progressive read-out mode of
-the (n, m) Bayer color filter array used in many CCD or CMOS image sensors.
-
-The Huffman compressed video frame consists of a bitstream that encodes for
-every R, G, or B pixel the difference between the value of the pixel itself and
-some reference pixel value. Pixels are organised in the Bayer pattern and the
-Bayer sub-pixels are tracked individually and alternatingly. For example, in
-the first line values for the B and G1 pixels are alternatingly encoded, while
-in the second line values for the G2 and R pixels are alternatingly encoded.
-
-The pixel reference value is calculated as follows:
-- the 4 top left pixels are encoded in raw uncompressed 8-bit format;
-- the value in the top two rows is the value of the pixel left of the current
- pixel;
-- the value in the left column is the value of the pixel above the current
- pixel;
-- for all other pixels, the reference value is the average of the value of the
- pixel on the left and the value of the pixel above the current pixel;
-- there is one code in the bitstream that specifies the value of a pixel
- directly (in 4-bit resolution);
-- pixel values need to be clamped inside the range [0..255] for proper
- decoding.
-
-The algorithm purely describes the conversion from compressed Bayer code used
-in the SN9C101, SN9C102 and SN9C103 chips to uncompressed Bayer. Additional
-steps are required to convert this to a color image (i.e. a color interpolation
-algorithm).
-
-The following Huffman codes have been found:
-0: +0 (relative to reference pixel value)
-100: +4
-101: -4?
-1110xxxx: set absolute value to xxxx.0000
-1101: +11
-1111: -11
-11001: +20
-110000: -20
-110001: ??? - these codes are apparently not used
-
-[1] The Huffman compression algorithm has been reverse-engineered and
- documented by Bertrik Sikken.
-
-
-12. Contact information
-=======================
-The author may be contacted by e-mail at <luca.risolia@studio.unibo.it>.
-
-GPG/PGP encrypted e-mail's are accepted. The GPG key ID of the author is
-'FCE635A4'; the public 1024-bit key should be available at any keyserver;
-the fingerprint is: '88E8 F32F 7244 68BA 3958 5D40 99DA 5D2A FCE6 35A4'.
-
-
-13. Credits
-===========
-Many thanks to following persons for their contribute (listed in alphabetical
-order):
-
-- David Anderson for the donation of a webcam;
-- Luca Capello for the donation of a webcam;
-- Philippe Coval for having helped testing the PAS202BCA image sensor;
-- Joao Rodrigo Fuzaro, Joao Limirio, Claudio Filho and Caio Begotti for the
- donation of a webcam;
-- Dennis Heitmann for the donation of a webcam;
-- Jon Hollstrom for the donation of a webcam;
-- Nick McGill for the donation of a webcam;
-- Carlos Eduardo Medaglia Dyonisio, who added the support for the PAS202BCB
- image sensor;
-- Stefano Mozzi, who donated 45 EU;
-- Andrew Pearce for the donation of a webcam;
-- John Pullan for the donation of a webcam;
-- Bertrik Sikken, who reverse-engineered and documented the Huffman compression
- algorithm used in the SN9C101, SN9C102 and SN9C103 controllers and
- implemented the first decoder;
-- Ronny Standke for the donation of a webcam;
-- Mizuno Takafumi for the donation of a webcam;
-- an "anonymous" donator (who didn't want his name to be revealed) for the
- donation of a webcam.
-- an anonymous donator for the donation of four webcams and two boards with ten
- image sensors.
diff --git a/drivers/staging/media/sn9c102/sn9c102_config.h b/drivers/staging/media/sn9c102/sn9c102_config.h
deleted file mode 100644
index 0f4e0378b071..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_config.h
+++ /dev/null
@@ -1,86 +0,0 @@
-/***************************************************************************
- * Global parameters for the V4L2 driver for SN9C1xx PC Camera Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#ifndef _SN9C102_CONFIG_H_
-#define _SN9C102_CONFIG_H_
-
-#include <linux/types.h>
-#include <linux/jiffies.h>
-
-#define SN9C102_DEBUG
-#define SN9C102_DEBUG_LEVEL 2
-#define SN9C102_MAX_DEVICES 64
-#define SN9C102_PRESERVE_IMGSCALE 0
-#define SN9C102_FORCE_MUNMAP 0
-#define SN9C102_MAX_FRAMES 32
-#define SN9C102_URBS 2
-#define SN9C102_ISO_PACKETS 7
-#define SN9C102_ALTERNATE_SETTING 8
-#define SN9C102_URB_TIMEOUT msecs_to_jiffies(2 * SN9C102_ISO_PACKETS)
-#define SN9C102_CTRL_TIMEOUT 300
-#define SN9C102_FRAME_TIMEOUT 0
-
-/*****************************************************************************/
-
-static const u8 SN9C102_Y_QTABLE0[64] = {
- 8, 5, 5, 8, 12, 20, 25, 30,
- 6, 6, 7, 9, 13, 29, 30, 27,
- 7, 6, 8, 12, 20, 28, 34, 28,
- 7, 8, 11, 14, 25, 43, 40, 31,
- 9, 11, 18, 28, 34, 54, 51, 38,
- 12, 17, 27, 32, 40, 52, 56, 46,
- 24, 32, 39, 43, 51, 60, 60, 50,
- 36, 46, 47, 49, 56, 50, 51, 49
-};
-
-static const u8 SN9C102_UV_QTABLE0[64] = {
- 8, 9, 12, 23, 49, 49, 49, 49,
- 9, 10, 13, 33, 49, 49, 49, 49,
- 12, 13, 28, 49, 49, 49, 49, 49,
- 23, 33, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49,
- 49, 49, 49, 49, 49, 49, 49, 49
-};
-
-static const u8 SN9C102_Y_QTABLE1[64] = {
- 16, 11, 10, 16, 24, 40, 51, 61,
- 12, 12, 14, 19, 26, 58, 60, 55,
- 14, 13, 16, 24, 40, 57, 69, 56,
- 14, 17, 22, 29, 51, 87, 80, 62,
- 18, 22, 37, 56, 68, 109, 103, 77,
- 24, 35, 55, 64, 81, 104, 113, 92,
- 49, 64, 78, 87, 103, 121, 120, 101,
- 72, 92, 95, 98, 112, 100, 103, 99
-};
-
-static const u8 SN9C102_UV_QTABLE1[64] = {
- 17, 18, 24, 47, 99, 99, 99, 99,
- 18, 21, 26, 66, 99, 99, 99, 99,
- 24, 26, 56, 99, 99, 99, 99, 99,
- 47, 66, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99,
- 99, 99, 99, 99, 99, 99, 99, 99
-};
-
-#endif /* _SN9C102_CONFIG_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_core.c b/drivers/staging/media/sn9c102/sn9c102_core.c
deleted file mode 100644
index 98b30579b0ac..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_core.c
+++ /dev/null
@@ -1,3465 +0,0 @@
-/***************************************************************************
- * V4L2 driver for SN9C1xx PC Camera Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/kernel.h>
-#include <linux/param.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/device.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/compiler.h>
-#include <linux/ioctl.h>
-#include <linux/poll.h>
-#include <linux/stat.h>
-#include <linux/mm.h>
-#include <linux/vmalloc.h>
-#include <linux/version.h>
-#include <linux/page-flags.h>
-#include <asm/byteorder.h>
-#include <asm/page.h>
-#include <asm/uaccess.h>
-
-#include "sn9c102.h"
-
-/*****************************************************************************/
-
-#define SN9C102_MODULE_NAME "V4L2 driver for SN9C1xx PC Camera Controllers"
-#define SN9C102_MODULE_ALIAS "sn9c1xx"
-#define SN9C102_MODULE_AUTHOR "(C) 2004-2007 Luca Risolia"
-#define SN9C102_AUTHOR_EMAIL "<luca.risolia@studio.unibo.it>"
-#define SN9C102_MODULE_LICENSE "GPL"
-#define SN9C102_MODULE_VERSION "1:1.48"
-
-/*****************************************************************************/
-
-MODULE_DEVICE_TABLE(usb, sn9c102_id_table);
-
-MODULE_AUTHOR(SN9C102_MODULE_AUTHOR " " SN9C102_AUTHOR_EMAIL);
-MODULE_DESCRIPTION(SN9C102_MODULE_NAME);
-MODULE_ALIAS(SN9C102_MODULE_ALIAS);
-MODULE_VERSION(SN9C102_MODULE_VERSION);
-MODULE_LICENSE(SN9C102_MODULE_LICENSE);
-
-static short video_nr[] = {[0 ... SN9C102_MAX_DEVICES-1] = -1};
-module_param_array(video_nr, short, NULL, 0444);
-MODULE_PARM_DESC(video_nr,
- " <-1|n[,...]>"
- "\nSpecify V4L2 minor mode number."
- "\n-1 = use next available (default)"
- "\n n = use minor number n (integer >= 0)"
- "\nYou can specify up to "__MODULE_STRING(SN9C102_MAX_DEVICES)
- " cameras this way."
- "\nFor example:"
- "\nvideo_nr=-1,2,-1 would assign minor number 2 to"
- "\nthe second camera and use auto for the first"
- "\none and for every other camera."
- "\n");
-
-static bool force_munmap[] = {[0 ... SN9C102_MAX_DEVICES-1] =
- SN9C102_FORCE_MUNMAP};
-module_param_array(force_munmap, bool, NULL, 0444);
-MODULE_PARM_DESC(force_munmap,
- " <0|1[,...]>"
- "\nForce the application to unmap previously"
- "\nmapped buffer memory before calling any VIDIOC_S_CROP or"
- "\nVIDIOC_S_FMT ioctl's. Not all the applications support"
- "\nthis feature. This parameter is specific for each"
- "\ndetected camera."
- "\n0 = do not force memory unmapping"
- "\n1 = force memory unmapping (save memory)"
- "\nDefault value is "__MODULE_STRING(SN9C102_FORCE_MUNMAP)"."
- "\n");
-
-static unsigned int frame_timeout[] = {[0 ... SN9C102_MAX_DEVICES-1] =
- SN9C102_FRAME_TIMEOUT};
-module_param_array(frame_timeout, uint, NULL, 0644);
-MODULE_PARM_DESC(frame_timeout,
- " <0|n[,...]>"
- "\nTimeout for a video frame in seconds before"
- "\nreturning an I/O error; 0 for infinity."
- "\nThis parameter is specific for each detected camera."
- "\nDefault value is "__MODULE_STRING(SN9C102_FRAME_TIMEOUT)"."
- "\n");
-
-#ifdef SN9C102_DEBUG
-static unsigned short debug = SN9C102_DEBUG_LEVEL;
-module_param(debug, ushort, 0644);
-MODULE_PARM_DESC(debug,
- " <n>"
- "\nDebugging information level, from 0 to 3:"
- "\n0 = none (use carefully)"
- "\n1 = critical errors"
- "\n2 = significant informations"
- "\n3 = more verbose messages"
- "\nLevel 3 is useful for testing only."
- "\nDefault value is "__MODULE_STRING(SN9C102_DEBUG_LEVEL)"."
- "\n");
-#endif
-
-/*
- Add the probe entries to this table. Be sure to add the entry in the right
- place, since, on failure, the next probing routine is called according to
- the order of the list below, from top to bottom.
-*/
-static int (*sn9c102_sensor_table[])(struct sn9c102_device *) = {
- &sn9c102_probe_hv7131d, /* strong detection based on SENSOR ids */
- &sn9c102_probe_hv7131r, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mi0343, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mi0360, /* strong detection based on SENSOR ids */
- &sn9c102_probe_mt9v111, /* strong detection based on SENSOR ids */
- &sn9c102_probe_pas106b, /* strong detection based on SENSOR ids */
- &sn9c102_probe_pas202bcb, /* strong detection based on SENSOR ids */
- &sn9c102_probe_ov7630, /* strong detection based on SENSOR ids */
- &sn9c102_probe_ov7660, /* strong detection based on SENSOR ids */
- &sn9c102_probe_tas5110c1b, /* detection based on USB pid/vid */
- &sn9c102_probe_tas5110d, /* detection based on USB pid/vid */
- &sn9c102_probe_tas5130d1b, /* detection based on USB pid/vid */
-};
-
-/*****************************************************************************/
-
-static u32
-sn9c102_request_buffers(struct sn9c102_device *cam, u32 count,
- enum sn9c102_io_method io)
-{
- struct v4l2_pix_format *p = &(cam->sensor.pix_format);
- struct v4l2_rect *r = &(cam->sensor.cropcap.bounds);
- size_t imagesize = cam->module_param.force_munmap || io == IO_READ ?
- (p->width * p->height * p->priv) / 8 :
- (r->width * r->height * p->priv) / 8;
- void *buff = NULL;
- u32 i;
-
- if (count > SN9C102_MAX_FRAMES)
- count = SN9C102_MAX_FRAMES;
-
- if (cam->bridge == BRIDGE_SN9C105 || cam->bridge == BRIDGE_SN9C120)
- imagesize += 589 + 2; /* length of JPEG header + EOI marker */
-
- cam->nbuffers = count;
- while (cam->nbuffers > 0) {
- buff = vmalloc_32_user(cam->nbuffers * PAGE_ALIGN(imagesize));
- if (buff)
- break;
- cam->nbuffers--;
- }
-
- for (i = 0; i < cam->nbuffers; i++) {
- cam->frame[i].bufmem = buff + i*PAGE_ALIGN(imagesize);
- cam->frame[i].buf.index = i;
- cam->frame[i].buf.m.offset = i*PAGE_ALIGN(imagesize);
- cam->frame[i].buf.length = imagesize;
- cam->frame[i].buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cam->frame[i].buf.sequence = 0;
- cam->frame[i].buf.field = V4L2_FIELD_NONE;
- cam->frame[i].buf.memory = V4L2_MEMORY_MMAP;
- cam->frame[i].buf.flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
- }
-
- return cam->nbuffers;
-}
-
-
-static void sn9c102_release_buffers(struct sn9c102_device *cam)
-{
- if (cam->nbuffers) {
- vfree(cam->frame[0].bufmem);
- cam->nbuffers = 0;
- }
- cam->frame_current = NULL;
-}
-
-
-static void sn9c102_empty_framequeues(struct sn9c102_device *cam)
-{
- u32 i;
-
- INIT_LIST_HEAD(&cam->inqueue);
- INIT_LIST_HEAD(&cam->outqueue);
-
- for (i = 0; i < SN9C102_MAX_FRAMES; i++) {
- cam->frame[i].state = F_UNUSED;
- cam->frame[i].buf.bytesused = 0;
- }
-}
-
-
-static void sn9c102_requeue_outqueue(struct sn9c102_device *cam)
-{
- struct sn9c102_frame_t *i;
-
- list_for_each_entry(i, &cam->outqueue, frame) {
- i->state = F_QUEUED;
- list_add(&i->frame, &cam->inqueue);
- }
-
- INIT_LIST_HEAD(&cam->outqueue);
-}
-
-
-static void sn9c102_queue_unusedframes(struct sn9c102_device *cam)
-{
- unsigned long lock_flags;
- u32 i;
-
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].state == F_UNUSED) {
- cam->frame[i].state = F_QUEUED;
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- list_add_tail(&cam->frame[i].frame, &cam->inqueue);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
- }
-}
-
-/*****************************************************************************/
-
-/*
- Write a sequence of count value/register pairs. Returns -1 after the first
- failed write, or 0 for no errors.
-*/
-int sn9c102_write_regs(struct sn9c102_device *cam, const u8 valreg[][2],
- int count)
-{
- struct usb_device *udev = cam->usbdev;
- u8 *buff = cam->control_buffer;
- int i, res;
-
- for (i = 0; i < count; i++) {
- u8 index = valreg[i][1];
-
- /*
- index is a u8, so it must be <256 and can't be out of range.
- If we put in a check anyway, gcc annoys us with a warning
- hat our check is useless. People get all uppity when they
- see warnings in the kernel compile.
- */
-
- *buff = valreg[i][0];
-
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08,
- 0x41, index, 0, buff, 1,
- SN9C102_CTRL_TIMEOUT);
-
- if (res < 0) {
- DBG(3, "Failed to write a register (value 0x%02X, "
- "index 0x%02X, error %d)", *buff, index, res);
- return -1;
- }
-
- cam->reg[index] = *buff;
- }
-
- return 0;
-}
-
-
-int sn9c102_write_reg(struct sn9c102_device *cam, u8 value, u16 index)
-{
- struct usb_device *udev = cam->usbdev;
- u8 *buff = cam->control_buffer;
- int res;
-
- if (index >= ARRAY_SIZE(cam->reg))
- return -1;
-
- *buff = value;
-
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
- if (res < 0) {
- DBG(3, "Failed to write a register (value 0x%02X, index "
- "0x%02X, error %d)", value, index, res);
- return -1;
- }
-
- cam->reg[index] = value;
-
- return 0;
-}
-
-
-/* NOTE: with the SN9C10[123] reading some registers always returns 0 */
-int sn9c102_read_reg(struct sn9c102_device *cam, u16 index)
-{
- struct usb_device *udev = cam->usbdev;
- u8 *buff = cam->control_buffer;
- int res;
-
- res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- index, 0, buff, 1, SN9C102_CTRL_TIMEOUT);
- if (res < 0)
- DBG(3, "Failed to read a register (index 0x%02X, error %d)",
- index, res);
-
- return (res >= 0) ? (int)(*buff) : -1;
-}
-
-
-int sn9c102_pread_reg(struct sn9c102_device *cam, u16 index)
-{
- if (index >= ARRAY_SIZE(cam->reg))
- return -1;
-
- return cam->reg[index];
-}
-
-
-static int
-sn9c102_i2c_wait(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor)
-{
- int i, r;
-
- for (i = 1; i <= 5; i++) {
- r = sn9c102_read_reg(cam, 0x08);
- if (r < 0)
- return -EIO;
- if (r & 0x04)
- return 0;
- if (sensor->frequency & SN9C102_I2C_400KHZ)
- udelay(5*16);
- else
- udelay(16*16);
- }
- return -EBUSY;
-}
-
-
-static int
-sn9c102_i2c_detect_read_error(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor)
-{
- int r , err = 0;
-
- r = sn9c102_read_reg(cam, 0x08);
- if (r < 0)
- err += r;
-
- if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
- if (!(r & 0x08))
- err += -1;
- } else {
- if (r & 0x08)
- err += -1;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_i2c_detect_write_error(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor)
-{
- int r;
-
- r = sn9c102_read_reg(cam, 0x08);
- return (r < 0 || (r >= 0 && (r & 0x08))) ? -EIO : 0;
-}
-
-
-int
-sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor, u8 data0,
- u8 data1, u8 n, u8 buffer[])
-{
- struct usb_device *udev = cam->usbdev;
- u8 *data = cam->control_buffer;
- int i = 0, err = 0, res;
-
- /* Write cycle */
- data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) | 0x10;
- data[1] = data0; /* I2C slave id */
- data[2] = data1; /* address */
- data[7] = 0x10;
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
- if (res < 0)
- err += res;
-
- err += sn9c102_i2c_wait(cam, sensor);
-
- /* Read cycle - n bytes */
- data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0) |
- (n << 4) | 0x02;
- data[1] = data0;
- data[7] = 0x10;
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
- if (res < 0)
- err += res;
-
- err += sn9c102_i2c_wait(cam, sensor);
-
- /* The first read byte will be placed in data[4] */
- res = usb_control_msg(udev, usb_rcvctrlpipe(udev, 0), 0x00, 0xc1,
- 0x0a, 0, data, 5, SN9C102_CTRL_TIMEOUT);
- if (res < 0)
- err += res;
-
- err += sn9c102_i2c_detect_read_error(cam, sensor);
-
- PDBGG("I2C read: address 0x%02X, first read byte: 0x%02X", data1,
- data[4]);
-
- if (err) {
- DBG(3, "I2C read failed for %s image sensor", sensor->name);
- return -1;
- }
-
- if (buffer)
- for (i = 0; i < n && i < 5; i++)
- buffer[n-i-1] = data[4-i];
-
- return (int)data[4];
-}
-
-
-int
-sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor, u8 n, u8 data0,
- u8 data1, u8 data2, u8 data3, u8 data4, u8 data5)
-{
- struct usb_device *udev = cam->usbdev;
- u8 *data = cam->control_buffer;
- int err = 0, res;
-
- /* Write cycle. It usually is address + value */
- data[0] = ((sensor->interface == SN9C102_I2C_2WIRES) ? 0x80 : 0) |
- ((sensor->frequency & SN9C102_I2C_400KHZ) ? 0x01 : 0)
- | ((n - 1) << 4);
- data[1] = data0;
- data[2] = data1;
- data[3] = data2;
- data[4] = data3;
- data[5] = data4;
- data[6] = data5;
- data[7] = 0x17;
- res = usb_control_msg(udev, usb_sndctrlpipe(udev, 0), 0x08, 0x41,
- 0x08, 0, data, 8, SN9C102_CTRL_TIMEOUT);
- if (res < 0)
- err += res;
-
- err += sn9c102_i2c_wait(cam, sensor);
- err += sn9c102_i2c_detect_write_error(cam, sensor);
-
- if (err)
- DBG(3, "I2C write failed for %s image sensor", sensor->name);
-
- PDBGG("I2C raw write: %u bytes, data0 = 0x%02X, data1 = 0x%02X, "
- "data2 = 0x%02X, data3 = 0x%02X, data4 = 0x%02X, data5 = 0x%02X",
- n, data0, data1, data2, data3, data4, data5);
-
- return err ? -1 : 0;
-}
-
-
-int
-sn9c102_i2c_try_read(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor, u8 address)
-{
- return sn9c102_i2c_try_raw_read(cam, sensor, sensor->i2c_slave_id,
- address, 1, NULL);
-}
-
-
-static int sn9c102_i2c_try_write(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor,
- u8 address, u8 value)
-{
- return sn9c102_i2c_try_raw_write(cam, sensor, 3,
- sensor->i2c_slave_id, address,
- value, 0, 0, 0);
-}
-
-
-int sn9c102_i2c_read(struct sn9c102_device *cam, u8 address)
-{
- return sn9c102_i2c_try_read(cam, &cam->sensor, address);
-}
-
-
-int sn9c102_i2c_write(struct sn9c102_device *cam, u8 address, u8 value)
-{
- return sn9c102_i2c_try_write(cam, &cam->sensor, address, value);
-}
-
-/*****************************************************************************/
-
-static size_t sn9c102_sof_length(struct sn9c102_device *cam)
-{
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- return 12;
- case BRIDGE_SN9C103:
- return 18;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- return 62;
- }
-
- return 0;
-}
-
-
-static void*
-sn9c102_find_sof_header(struct sn9c102_device *cam, void *mem, size_t len)
-{
- static const char marker[6] = {0xff, 0xff, 0x00, 0xc4, 0xc4, 0x96};
- const char *m = mem;
- size_t soflen = 0, i, j;
-
- soflen = sn9c102_sof_length(cam);
-
- for (i = 0; i < len; i++) {
- size_t b;
-
- /* Read the variable part of the header */
- if (unlikely(cam->sof.bytesread >= sizeof(marker))) {
- cam->sof.header[cam->sof.bytesread] = *(m+i);
- if (++cam->sof.bytesread == soflen) {
- cam->sof.bytesread = 0;
- return mem + i;
- }
- continue;
- }
-
- /* Search for the SOF marker (fixed part) in the header */
- for (j = 0, b = cam->sof.bytesread; j+b < sizeof(marker); j++) {
- if (unlikely(i+j == len))
- return NULL;
- if (*(m+i+j) == marker[cam->sof.bytesread]) {
- cam->sof.header[cam->sof.bytesread] = *(m+i+j);
- if (++cam->sof.bytesread == sizeof(marker)) {
- PDBGG("Bytes to analyze: %zd. SOF "
- "starts at byte #%zd", len, i);
- i += j+1;
- break;
- }
- } else {
- cam->sof.bytesread = 0;
- break;
- }
- }
- }
-
- return NULL;
-}
-
-
-static void*
-sn9c102_find_eof_header(struct sn9c102_device *cam, void *mem, size_t len)
-{
- static const u8 eof_header[4][4] = {
- {0x00, 0x00, 0x00, 0x00},
- {0x40, 0x00, 0x00, 0x00},
- {0x80, 0x00, 0x00, 0x00},
- {0xc0, 0x00, 0x00, 0x00},
- };
- size_t i, j;
-
- /* The EOF header does not exist in compressed data */
- if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
- cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- return NULL;
-
- /*
- The EOF header might cross the packet boundary, but this is not a
- problem, since the end of a frame is determined by checking its size
- in the first place.
- */
- for (i = 0; (len >= 4) && (i <= len - 4); i++)
- for (j = 0; j < ARRAY_SIZE(eof_header); j++)
- if (!memcmp(mem + i, eof_header[j], 4))
- return mem + i;
-
- return NULL;
-}
-
-
-static void
-sn9c102_write_jpegheader(struct sn9c102_device *cam, struct sn9c102_frame_t *f)
-{
- static const u8 jpeg_header[589] = {
- 0xff, 0xd8, 0xff, 0xdb, 0x00, 0x84, 0x00, 0x06, 0x04, 0x05,
- 0x06, 0x05, 0x04, 0x06, 0x06, 0x05, 0x06, 0x07, 0x07, 0x06,
- 0x08, 0x0a, 0x10, 0x0a, 0x0a, 0x09, 0x09, 0x0a, 0x14, 0x0e,
- 0x0f, 0x0c, 0x10, 0x17, 0x14, 0x18, 0x18, 0x17, 0x14, 0x16,
- 0x16, 0x1a, 0x1d, 0x25, 0x1f, 0x1a, 0x1b, 0x23, 0x1c, 0x16,
- 0x16, 0x20, 0x2c, 0x20, 0x23, 0x26, 0x27, 0x29, 0x2a, 0x29,
- 0x19, 0x1f, 0x2d, 0x30, 0x2d, 0x28, 0x30, 0x25, 0x28, 0x29,
- 0x28, 0x01, 0x07, 0x07, 0x07, 0x0a, 0x08, 0x0a, 0x13, 0x0a,
- 0x0a, 0x13, 0x28, 0x1a, 0x16, 0x1a, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0x28,
- 0x28, 0x28, 0x28, 0x28, 0x28, 0x28, 0xff, 0xc4, 0x01, 0xa2,
- 0x00, 0x00, 0x01, 0x05, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
- 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x01,
- 0x00, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
- 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x03,
- 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x10, 0x00,
- 0x02, 0x01, 0x03, 0x03, 0x02, 0x04, 0x03, 0x05, 0x05, 0x04,
- 0x04, 0x00, 0x00, 0x01, 0x7d, 0x01, 0x02, 0x03, 0x00, 0x04,
- 0x11, 0x05, 0x12, 0x21, 0x31, 0x41, 0x06, 0x13, 0x51, 0x61,
- 0x07, 0x22, 0x71, 0x14, 0x32, 0x81, 0x91, 0xa1, 0x08, 0x23,
- 0x42, 0xb1, 0xc1, 0x15, 0x52, 0xd1, 0xf0, 0x24, 0x33, 0x62,
- 0x72, 0x82, 0x09, 0x0a, 0x16, 0x17, 0x18, 0x19, 0x1a, 0x25,
- 0x26, 0x27, 0x28, 0x29, 0x2a, 0x34, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
- 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
- 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
- 0x77, 0x78, 0x79, 0x7a, 0x83, 0x84, 0x85, 0x86, 0x87, 0x88,
- 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99,
- 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9, 0xaa,
- 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba, 0xc2,
- 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2, 0xd3,
- 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe1, 0xe2, 0xe3,
- 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf1, 0xf2, 0xf3,
- 0xf4, 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0x11, 0x00, 0x02,
- 0x01, 0x02, 0x04, 0x04, 0x03, 0x04, 0x07, 0x05, 0x04, 0x04,
- 0x00, 0x01, 0x02, 0x77, 0x00, 0x01, 0x02, 0x03, 0x11, 0x04,
- 0x05, 0x21, 0x31, 0x06, 0x12, 0x41, 0x51, 0x07, 0x61, 0x71,
- 0x13, 0x22, 0x32, 0x81, 0x08, 0x14, 0x42, 0x91, 0xa1, 0xb1,
- 0xc1, 0x09, 0x23, 0x33, 0x52, 0xf0, 0x15, 0x62, 0x72, 0xd1,
- 0x0a, 0x16, 0x24, 0x34, 0xe1, 0x25, 0xf1, 0x17, 0x18, 0x19,
- 0x1a, 0x26, 0x27, 0x28, 0x29, 0x2a, 0x35, 0x36, 0x37, 0x38,
- 0x39, 0x3a, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a,
- 0x53, 0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5a, 0x63, 0x64,
- 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x73, 0x74, 0x75, 0x76,
- 0x77, 0x78, 0x79, 0x7a, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
- 0x88, 0x89, 0x8a, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98,
- 0x99, 0x9a, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa8, 0xa9,
- 0xaa, 0xb2, 0xb3, 0xb4, 0xb5, 0xb6, 0xb7, 0xb8, 0xb9, 0xba,
- 0xc2, 0xc3, 0xc4, 0xc5, 0xc6, 0xc7, 0xc8, 0xc9, 0xca, 0xd2,
- 0xd3, 0xd4, 0xd5, 0xd6, 0xd7, 0xd8, 0xd9, 0xda, 0xe2, 0xe3,
- 0xe4, 0xe5, 0xe6, 0xe7, 0xe8, 0xe9, 0xea, 0xf2, 0xf3, 0xf4,
- 0xf5, 0xf6, 0xf7, 0xf8, 0xf9, 0xfa, 0xff, 0xc0, 0x00, 0x11,
- 0x08, 0x01, 0xe0, 0x02, 0x80, 0x03, 0x01, 0x21, 0x00, 0x02,
- 0x11, 0x01, 0x03, 0x11, 0x01, 0xff, 0xda, 0x00, 0x0c, 0x03,
- 0x01, 0x00, 0x02, 0x11, 0x03, 0x11, 0x00, 0x3f, 0x00
- };
- u8 *pos = f->bufmem;
-
- memcpy(pos, jpeg_header, sizeof(jpeg_header));
- *(pos + 6) = 0x00;
- *(pos + 7 + 64) = 0x01;
- if (cam->compression.quality == 0) {
- memcpy(pos + 7, SN9C102_Y_QTABLE0, 64);
- memcpy(pos + 8 + 64, SN9C102_UV_QTABLE0, 64);
- } else if (cam->compression.quality == 1) {
- memcpy(pos + 7, SN9C102_Y_QTABLE1, 64);
- memcpy(pos + 8 + 64, SN9C102_UV_QTABLE1, 64);
- }
- *(pos + 564) = cam->sensor.pix_format.width & 0xFF;
- *(pos + 563) = (cam->sensor.pix_format.width >> 8) & 0xFF;
- *(pos + 562) = cam->sensor.pix_format.height & 0xFF;
- *(pos + 561) = (cam->sensor.pix_format.height >> 8) & 0xFF;
- *(pos + 567) = 0x21;
-
- f->buf.bytesused += sizeof(jpeg_header);
-}
-
-
-static void sn9c102_urb_complete(struct urb *urb)
-{
- struct sn9c102_device *cam = urb->context;
- struct sn9c102_frame_t **f;
- size_t imagesize, soflen;
- u8 i;
- int err = 0;
-
- if (urb->status == -ENOENT)
- return;
-
- f = &cam->frame_current;
-
- if (cam->stream == STREAM_INTERRUPT) {
- cam->stream = STREAM_OFF;
- if ((*f))
- (*f)->state = F_QUEUED;
- cam->sof.bytesread = 0;
- DBG(3, "Stream interrupted by application");
- wake_up(&cam->wait_stream);
- }
-
- if (cam->state & DEV_DISCONNECTED)
- return;
-
- if (cam->state & DEV_MISCONFIGURED) {
- wake_up_interruptible(&cam->wait_frame);
- return;
- }
-
- if (cam->stream == STREAM_OFF || list_empty(&cam->inqueue))
- goto resubmit_urb;
-
- if (!(*f))
- (*f) = list_entry(cam->inqueue.next, struct sn9c102_frame_t,
- frame);
-
- imagesize = (cam->sensor.pix_format.width *
- cam->sensor.pix_format.height *
- cam->sensor.pix_format.priv) / 8;
- if (cam->sensor.pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- imagesize += 589; /* length of jpeg header */
- soflen = sn9c102_sof_length(cam);
-
- for (i = 0; i < urb->number_of_packets; i++) {
- unsigned int img, len, status;
- void *pos, *sof, *eof;
-
- len = urb->iso_frame_desc[i].actual_length;
- status = urb->iso_frame_desc[i].status;
- pos = urb->iso_frame_desc[i].offset + urb->transfer_buffer;
-
- if (status) {
- DBG(3, "Error in isochronous frame");
- (*f)->state = F_ERROR;
- cam->sof.bytesread = 0;
- continue;
- }
-
- PDBGG("Isochrnous frame: length %u, #%u i", len, i);
-
-redo:
- sof = sn9c102_find_sof_header(cam, pos, len);
- if (likely(!sof)) {
- eof = sn9c102_find_eof_header(cam, pos, len);
- if ((*f)->state == F_GRABBING) {
-end_of_frame:
- img = len;
-
- if (eof)
- img = (eof > pos) ? eof - pos - 1 : 0;
-
- if ((*f)->buf.bytesused + img > imagesize) {
- u32 b;
- b = (*f)->buf.bytesused + img -
- imagesize;
- img = imagesize - (*f)->buf.bytesused;
- PDBGG("Expected EOF not found: video "
- "frame cut");
- if (eof)
- DBG(3, "Exceeded limit: +%u "
- "bytes", (unsigned)(b));
- }
-
- memcpy((*f)->bufmem + (*f)->buf.bytesused, pos,
- img);
-
- if ((*f)->buf.bytesused == 0)
- v4l2_get_timestamp(
- &(*f)->buf.timestamp);
-
- (*f)->buf.bytesused += img;
-
- if ((*f)->buf.bytesused == imagesize ||
- ((cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_SN9C10X ||
- cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_JPEG) && eof)) {
- u32 b;
-
- b = (*f)->buf.bytesused;
- (*f)->state = F_DONE;
- (*f)->buf.sequence = ++cam->frame_count;
-
- spin_lock(&cam->queue_lock);
- list_move_tail(&(*f)->frame,
- &cam->outqueue);
- if (!list_empty(&cam->inqueue))
- (*f) = list_entry(
- cam->inqueue.next,
- struct sn9c102_frame_t,
- frame);
- else
- (*f) = NULL;
- spin_unlock(&cam->queue_lock);
-
- memcpy(cam->sysfs.frame_header,
- cam->sof.header, soflen);
-
- DBG(3, "Video frame captured: %lu "
- "bytes", (unsigned long)(b));
-
- if (!(*f))
- goto resubmit_urb;
-
- } else if (eof) {
- (*f)->state = F_ERROR;
- DBG(3, "Not expected EOF after %lu "
- "bytes of image data",
- (unsigned long)
- ((*f)->buf.bytesused));
- }
-
- if (sof) /* (1) */
- goto start_of_frame;
-
- } else if (eof) {
- DBG(3, "EOF without SOF");
- continue;
-
- } else {
- PDBGG("Ignoring pointless isochronous frame");
- continue;
- }
-
- } else if ((*f)->state == F_QUEUED || (*f)->state == F_ERROR) {
-start_of_frame:
- (*f)->state = F_GRABBING;
- (*f)->buf.bytesused = 0;
- len -= (sof - pos);
- pos = sof;
- if (cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_JPEG)
- sn9c102_write_jpegheader(cam, (*f));
- DBG(3, "SOF detected: new video frame");
- if (len)
- goto redo;
-
- } else if ((*f)->state == F_GRABBING) {
- eof = sn9c102_find_eof_header(cam, pos, len);
- if (eof && eof < sof)
- goto end_of_frame; /* (1) */
- else {
- if (cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_SN9C10X ||
- cam->sensor.pix_format.pixelformat ==
- V4L2_PIX_FMT_JPEG) {
- if (sof - pos >= soflen) {
- eof = sof - soflen;
- } else { /* remove header */
- eof = pos;
- (*f)->buf.bytesused -=
- (soflen - (sof - pos));
- }
- goto end_of_frame;
- } else {
- DBG(3, "SOF before expected EOF after "
- "%lu bytes of image data",
- (unsigned long)
- ((*f)->buf.bytesused));
- goto start_of_frame;
- }
- }
- }
- }
-
-resubmit_urb:
- urb->dev = cam->usbdev;
- err = usb_submit_urb(urb, GFP_ATOMIC);
- if (err < 0 && err != -EPERM) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "usb_submit_urb() failed");
- }
-
- wake_up_interruptible(&cam->wait_frame);
-}
-
-
-static int sn9c102_start_transfer(struct sn9c102_device *cam)
-{
- struct usb_device *udev = cam->usbdev;
- struct urb *urb;
- struct usb_host_interface *altsetting = usb_altnum_to_altsetting(
- usb_ifnum_to_if(udev, 0),
- SN9C102_ALTERNATE_SETTING);
- const unsigned int psz = le16_to_cpu(altsetting->
- endpoint[0].desc.wMaxPacketSize);
- s8 i, j;
- int err = 0;
-
- for (i = 0; i < SN9C102_URBS; i++) {
- cam->transfer_buffer[i] = kzalloc(SN9C102_ISO_PACKETS * psz,
- GFP_KERNEL);
- if (!cam->transfer_buffer[i]) {
- err = -ENOMEM;
- DBG(1, "Not enough memory");
- goto free_buffers;
- }
- }
-
- for (i = 0; i < SN9C102_URBS; i++) {
- urb = usb_alloc_urb(SN9C102_ISO_PACKETS, GFP_KERNEL);
- cam->urb[i] = urb;
- if (!urb) {
- err = -ENOMEM;
- DBG(1, "usb_alloc_urb() failed");
- goto free_urbs;
- }
- urb->dev = udev;
- urb->context = cam;
- urb->pipe = usb_rcvisocpipe(udev, 1);
- urb->transfer_flags = URB_ISO_ASAP;
- urb->number_of_packets = SN9C102_ISO_PACKETS;
- urb->complete = sn9c102_urb_complete;
- urb->transfer_buffer = cam->transfer_buffer[i];
- urb->transfer_buffer_length = psz * SN9C102_ISO_PACKETS;
- urb->interval = 1;
- for (j = 0; j < SN9C102_ISO_PACKETS; j++) {
- urb->iso_frame_desc[j].offset = psz * j;
- urb->iso_frame_desc[j].length = psz;
- }
- }
-
- /* Enable video */
- if (!(cam->reg[0x01] & 0x04)) {
- err = sn9c102_write_reg(cam, cam->reg[0x01] | 0x04, 0x01);
- if (err) {
- err = -EIO;
- DBG(1, "I/O hardware error");
- goto free_urbs;
- }
- }
-
- err = usb_set_interface(udev, 0, SN9C102_ALTERNATE_SETTING);
- if (err) {
- DBG(1, "usb_set_interface() failed");
- goto free_urbs;
- }
-
- cam->frame_current = NULL;
- cam->sof.bytesread = 0;
-
- for (i = 0; i < SN9C102_URBS; i++) {
- err = usb_submit_urb(cam->urb[i], GFP_KERNEL);
- if (err) {
- for (j = i-1; j >= 0; j--)
- usb_kill_urb(cam->urb[j]);
- DBG(1, "usb_submit_urb() failed, error %d", err);
- goto free_urbs;
- }
- }
-
- return 0;
-
-free_urbs:
- for (i = 0; (i < SN9C102_URBS) && cam->urb[i]; i++)
- usb_free_urb(cam->urb[i]);
-
-free_buffers:
- for (i = 0; (i < SN9C102_URBS) && cam->transfer_buffer[i]; i++)
- kfree(cam->transfer_buffer[i]);
-
- return err;
-}
-
-
-static int sn9c102_stop_transfer(struct sn9c102_device *cam)
-{
- struct usb_device *udev = cam->usbdev;
- s8 i;
- int err = 0;
-
- if (cam->state & DEV_DISCONNECTED)
- return 0;
-
- for (i = SN9C102_URBS-1; i >= 0; i--) {
- usb_kill_urb(cam->urb[i]);
- usb_free_urb(cam->urb[i]);
- kfree(cam->transfer_buffer[i]);
- }
-
- err = usb_set_interface(udev, 0, 0); /* 0 Mb/s */
- if (err)
- DBG(3, "usb_set_interface() failed");
-
- return err;
-}
-
-
-static int sn9c102_stream_interrupt(struct sn9c102_device *cam)
-{
- cam->stream = STREAM_INTERRUPT;
- wait_event_timeout(cam->wait_stream,
- (cam->stream == STREAM_OFF) ||
- (cam->state & DEV_DISCONNECTED),
- SN9C102_URB_TIMEOUT);
- if (cam->state & DEV_DISCONNECTED)
- return -ENODEV;
- else if (cam->stream != STREAM_OFF) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "URB timeout reached. The camera is misconfigured. "
- "To use it, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -EIO;
- }
-
- return 0;
-}
-
-/*****************************************************************************/
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
-static u16 sn9c102_strtou16(const char *buff, size_t len, ssize_t *count)
-{
- char str[7];
- char *endp;
- unsigned long val;
-
- if (len < 6) {
- strncpy(str, buff, len);
- str[len] = '\0';
- } else {
- strncpy(str, buff, 6);
- str[6] = '\0';
- }
-
- val = simple_strtoul(str, &endp, 0);
-
- *count = 0;
- if (val <= 0xffff)
- *count = (ssize_t)(endp - str);
- if ((*count) && (len == *count+1) && (buff[*count] == '\n'))
- *count += 1;
-
- return (u16)val;
-}
-
-/*
- NOTE 1: being inside one of the following methods implies that the v4l
- device exists for sure (see kobjects and reference counters)
- NOTE 2: buffers are PAGE_SIZE long
-*/
-
-static ssize_t sn9c102_show_reg(struct device *cd,
- struct device_attribute *attr, char *buf)
-{
- struct sn9c102_device *cam;
- ssize_t count;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- count = sprintf(buf, "%u\n", cam->sysfs.reg);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t
-sn9c102_store_reg(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct sn9c102_device *cam;
- u16 index;
- ssize_t count;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- index = sn9c102_strtou16(buf, len, &count);
- if (index >= ARRAY_SIZE(cam->reg) || !count) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EINVAL;
- }
-
- cam->sysfs.reg = index;
-
- DBG(2, "Moved SN9C1XX register index to 0x%02X", cam->sysfs.reg);
- DBG(3, "Written bytes: %zd", count);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t sn9c102_show_val(struct device *cd,
- struct device_attribute *attr, char *buf)
-{
- struct sn9c102_device *cam;
- ssize_t count;
- int val;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- val = sn9c102_read_reg(cam, cam->sysfs.reg);
- if (val < 0) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EIO;
- }
-
- count = sprintf(buf, "%d\n", val);
-
- DBG(3, "Read bytes: %zd, value: %d", count, val);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t
-sn9c102_store_val(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct sn9c102_device *cam;
- u16 value;
- ssize_t count;
- int err;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- value = sn9c102_strtou16(buf, len, &count);
- if (!count) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EINVAL;
- }
-
- err = sn9c102_write_reg(cam, value, cam->sysfs.reg);
- if (err) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EIO;
- }
-
- DBG(2, "Written SN9C1XX reg. 0x%02X, val. 0x%02X",
- cam->sysfs.reg, value);
- DBG(3, "Written bytes: %zd", count);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_reg(struct device *cd,
- struct device_attribute *attr, char *buf)
-{
- struct sn9c102_device *cam;
- ssize_t count;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- count = sprintf(buf, "%u\n", cam->sysfs.i2c_reg);
-
- DBG(3, "Read bytes: %zd", count);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_reg(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct sn9c102_device *cam;
- u16 index;
- ssize_t count;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- index = sn9c102_strtou16(buf, len, &count);
- if (!count) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EINVAL;
- }
-
- cam->sysfs.i2c_reg = index;
-
- DBG(2, "Moved sensor register index to 0x%02X", cam->sysfs.i2c_reg);
- DBG(3, "Written bytes: %zd", count);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t sn9c102_show_i2c_val(struct device *cd,
- struct device_attribute *attr, char *buf)
-{
- struct sn9c102_device *cam;
- ssize_t count;
- int val;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- if (!(cam->sensor.sysfs_ops & SN9C102_I2C_READ)) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENOSYS;
- }
-
- val = sn9c102_i2c_read(cam, cam->sysfs.i2c_reg);
- if (val < 0) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EIO;
- }
-
- count = sprintf(buf, "%d\n", val);
-
- DBG(3, "Read bytes: %zd, value: %d", count, val);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t
-sn9c102_store_i2c_val(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct sn9c102_device *cam;
- u16 value;
- ssize_t count;
- int err;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- if (!(cam->sensor.sysfs_ops & SN9C102_I2C_WRITE)) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENOSYS;
- }
-
- value = sn9c102_strtou16(buf, len, &count);
- if (!count) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EINVAL;
- }
-
- err = sn9c102_i2c_write(cam, cam->sysfs.i2c_reg, value);
- if (err) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -EIO;
- }
-
- DBG(2, "Written sensor reg. 0x%02X, val. 0x%02X",
- cam->sysfs.i2c_reg, value);
- DBG(3, "Written bytes: %zd", count);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- return count;
-}
-
-
-static ssize_t
-sn9c102_store_green(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- struct sn9c102_device *cam;
- enum sn9c102_bridge bridge;
- ssize_t res = 0;
- u16 value;
- ssize_t count;
-
- if (mutex_lock_interruptible(&sn9c102_sysfs_lock))
- return -ERESTARTSYS;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam) {
- mutex_unlock(&sn9c102_sysfs_lock);
- return -ENODEV;
- }
-
- bridge = cam->bridge;
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
- value = sn9c102_strtou16(buf, len, &count);
- if (!count)
- return -EINVAL;
-
- switch (bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- if (value > 0x0f)
- return -EINVAL;
- res = sn9c102_store_reg(cd, attr, "0x11", 4);
- if (res >= 0)
- res = sn9c102_store_val(cd, attr, buf, len);
- break;
- case BRIDGE_SN9C103:
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (value > 0x7f)
- return -EINVAL;
- res = sn9c102_store_reg(cd, attr, "0x07", 4);
- if (res >= 0)
- res = sn9c102_store_val(cd, attr, buf, len);
- break;
- }
-
- return res;
-}
-
-
-static ssize_t
-sn9c102_store_blue(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- ssize_t res = 0;
- u16 value;
- ssize_t count;
-
- value = sn9c102_strtou16(buf, len, &count);
- if (!count || value > 0x7f)
- return -EINVAL;
-
- res = sn9c102_store_reg(cd, attr, "0x06", 4);
- if (res >= 0)
- res = sn9c102_store_val(cd, attr, buf, len);
-
- return res;
-}
-
-
-static ssize_t
-sn9c102_store_red(struct device *cd, struct device_attribute *attr,
- const char *buf, size_t len)
-{
- ssize_t res = 0;
- u16 value;
- ssize_t count;
-
- value = sn9c102_strtou16(buf, len, &count);
- if (!count || value > 0x7f)
- return -EINVAL;
- res = sn9c102_store_reg(cd, attr, "0x05", 4);
- if (res >= 0)
- res = sn9c102_store_val(cd, attr, buf, len);
-
- return res;
-}
-
-
-static ssize_t sn9c102_show_frame_header(struct device *cd,
- struct device_attribute *attr,
- char *buf)
-{
- struct sn9c102_device *cam;
- ssize_t count;
-
- cam = video_get_drvdata(container_of(cd, struct video_device, dev));
- if (!cam)
- return -ENODEV;
-
- count = sizeof(cam->sysfs.frame_header);
- memcpy(buf, cam->sysfs.frame_header, count);
-
- DBG(3, "Frame header, read bytes: %zd", count);
-
- return count;
-}
-
-
-static DEVICE_ATTR(reg, S_IRUGO | S_IWUSR, sn9c102_show_reg, sn9c102_store_reg);
-static DEVICE_ATTR(val, S_IRUGO | S_IWUSR, sn9c102_show_val, sn9c102_store_val);
-static DEVICE_ATTR(i2c_reg, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_reg, sn9c102_store_i2c_reg);
-static DEVICE_ATTR(i2c_val, S_IRUGO | S_IWUSR,
- sn9c102_show_i2c_val, sn9c102_store_i2c_val);
-static DEVICE_ATTR(green, S_IWUSR, NULL, sn9c102_store_green);
-static DEVICE_ATTR(blue, S_IWUSR, NULL, sn9c102_store_blue);
-static DEVICE_ATTR(red, S_IWUSR, NULL, sn9c102_store_red);
-static DEVICE_ATTR(frame_header, S_IRUGO, sn9c102_show_frame_header, NULL);
-
-
-static int sn9c102_create_sysfs(struct sn9c102_device *cam)
-{
- struct device *dev = &(cam->v4ldev->dev);
- int err = 0;
-
- err = device_create_file(dev, &dev_attr_reg);
- if (err)
- goto err_out;
- err = device_create_file(dev, &dev_attr_val);
- if (err)
- goto err_reg;
- err = device_create_file(dev, &dev_attr_frame_header);
- if (err)
- goto err_val;
-
- if (cam->sensor.sysfs_ops) {
- err = device_create_file(dev, &dev_attr_i2c_reg);
- if (err)
- goto err_frame_header;
- err = device_create_file(dev, &dev_attr_i2c_val);
- if (err)
- goto err_i2c_reg;
- }
-
- if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102) {
- err = device_create_file(dev, &dev_attr_green);
- if (err)
- goto err_i2c_val;
- } else {
- err = device_create_file(dev, &dev_attr_blue);
- if (err)
- goto err_i2c_val;
- err = device_create_file(dev, &dev_attr_red);
- if (err)
- goto err_blue;
- }
-
- return 0;
-
-err_blue:
- device_remove_file(dev, &dev_attr_blue);
-err_i2c_val:
- if (cam->sensor.sysfs_ops)
- device_remove_file(dev, &dev_attr_i2c_val);
-err_i2c_reg:
- if (cam->sensor.sysfs_ops)
- device_remove_file(dev, &dev_attr_i2c_reg);
-err_frame_header:
- device_remove_file(dev, &dev_attr_frame_header);
-err_val:
- device_remove_file(dev, &dev_attr_val);
-err_reg:
- device_remove_file(dev, &dev_attr_reg);
-err_out:
- return err;
-}
-#endif /* CONFIG_VIDEO_ADV_DEBUG */
-
-/*****************************************************************************/
-
-static int
-sn9c102_set_pix_format(struct sn9c102_device *cam, struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
- pix->pixelformat == V4L2_PIX_FMT_JPEG) {
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
- 0x18);
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
- 0x18);
- break;
- }
- } else {
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- err += sn9c102_write_reg(cam, cam->reg[0x18] & 0x7f,
- 0x18);
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x80,
- 0x18);
- break;
- }
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int
-sn9c102_set_compression(struct sn9c102_device *cam,
- struct v4l2_jpegcompression *compression)
-{
- int i, err = 0;
-
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- if (compression->quality == 0)
- err += sn9c102_write_reg(cam, cam->reg[0x17] | 0x01,
- 0x17);
- else if (compression->quality == 1)
- err += sn9c102_write_reg(cam, cam->reg[0x17] & 0xfe,
- 0x17);
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (compression->quality == 0) {
- for (i = 0; i <= 63; i++) {
- err += sn9c102_write_reg(cam,
- SN9C102_Y_QTABLE1[i],
- 0x100 + i);
- err += sn9c102_write_reg(cam,
- SN9C102_UV_QTABLE1[i],
- 0x140 + i);
- }
- err += sn9c102_write_reg(cam, cam->reg[0x18] & 0xbf,
- 0x18);
- } else if (compression->quality == 1) {
- for (i = 0; i <= 63; i++) {
- err += sn9c102_write_reg(cam,
- SN9C102_Y_QTABLE1[i],
- 0x100 + i);
- err += sn9c102_write_reg(cam,
- SN9C102_UV_QTABLE1[i],
- 0x140 + i);
- }
- err += sn9c102_write_reg(cam, cam->reg[0x18] | 0x40,
- 0x18);
- }
- break;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int sn9c102_set_scale(struct sn9c102_device *cam, u8 scale)
-{
- u8 r = 0;
- int err = 0;
-
- if (scale == 1)
- r = cam->reg[0x18] & 0xcf;
- else if (scale == 2) {
- r = cam->reg[0x18] & 0xcf;
- r |= 0x10;
- } else if (scale == 4)
- r = cam->reg[0x18] | 0x20;
-
- err += sn9c102_write_reg(cam, r, 0x18);
- if (err)
- return -EIO;
-
- PDBGG("Scaling factor: %u", scale);
-
- return 0;
-}
-
-
-static int sn9c102_set_crop(struct sn9c102_device *cam, struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left),
- v_start = (u8)(rect->top - s->cropcap.bounds.top),
- h_size = (u8)(rect->width / 16),
- v_size = (u8)(rect->height / 16);
- int err = 0;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
- err += sn9c102_write_reg(cam, h_size, 0x15);
- err += sn9c102_write_reg(cam, v_size, 0x16);
- if (err)
- return -EIO;
-
- PDBGG("h_start, v_start, h_size, v_size, ho_size, vo_size "
- "%u %u %u %u", h_start, v_start, h_size, v_size);
-
- return 0;
-}
-
-
-static int sn9c102_init(struct sn9c102_device *cam)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_control ctrl;
- struct v4l2_queryctrl *qctrl;
- struct v4l2_rect *rect;
- u8 i = 0;
- int err = 0;
-
- if (!(cam->state & DEV_INITIALIZED)) {
- mutex_init(&cam->open_mutex);
- init_waitqueue_head(&cam->wait_open);
- qctrl = s->qctrl;
- rect = &(s->cropcap.defrect);
- } else { /* use current values */
- qctrl = s->_qctrl;
- rect = &(s->_rect);
- }
-
- err += sn9c102_set_scale(cam, rect->width / s->pix_format.width);
- err += sn9c102_set_crop(cam, rect);
- if (err)
- return err;
-
- if (s->init) {
- err = s->init(cam);
- if (err) {
- DBG(3, "Sensor initialization failed");
- return err;
- }
- }
-
- if (!(cam->state & DEV_INITIALIZED))
- if (cam->bridge == BRIDGE_SN9C101 ||
- cam->bridge == BRIDGE_SN9C102 ||
- cam->bridge == BRIDGE_SN9C103) {
- if (s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- s->pix_format.pixelformat = V4L2_PIX_FMT_SBGGR8;
- cam->compression.quality = cam->reg[0x17] & 0x01 ?
- 0 : 1;
- } else {
- if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X)
- s->pix_format.pixelformat = V4L2_PIX_FMT_JPEG;
- cam->compression.quality = cam->reg[0x18] & 0x40 ?
- 0 : 1;
- err += sn9c102_set_compression(cam, &cam->compression);
- }
- else
- err += sn9c102_set_compression(cam, &cam->compression);
- err += sn9c102_set_pix_format(cam, &s->pix_format);
- if (s->set_pix_format)
- err += s->set_pix_format(cam, &s->pix_format);
- if (err)
- return err;
-
- if (s->pix_format.pixelformat == V4L2_PIX_FMT_SN9C10X ||
- s->pix_format.pixelformat == V4L2_PIX_FMT_JPEG)
- DBG(3, "Compressed video format is active, quality %d",
- cam->compression.quality);
- else
- DBG(3, "Uncompressed video format is active");
-
- if (s->set_crop) {
- err = s->set_crop(cam, rect);
- if (err) {
- DBG(3, "set_crop() failed");
- return err;
- }
- }
-
- if (s->set_ctrl) {
- for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
- if (s->qctrl[i].id != 0 &&
- !(s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)) {
- ctrl.id = s->qctrl[i].id;
- ctrl.value = qctrl[i].default_value;
- err = s->set_ctrl(cam, &ctrl);
- if (err) {
- DBG(3, "Set %s control failed",
- s->qctrl[i].name);
- return err;
- }
- DBG(3, "Image sensor supports '%s' control",
- s->qctrl[i].name);
- }
- }
-
- if (!(cam->state & DEV_INITIALIZED)) {
- mutex_init(&cam->fileop_mutex);
- spin_lock_init(&cam->queue_lock);
- init_waitqueue_head(&cam->wait_frame);
- init_waitqueue_head(&cam->wait_stream);
- cam->nreadbuffers = 2;
- memcpy(s->_qctrl, s->qctrl, sizeof(s->qctrl));
- memcpy(&(s->_rect), &(s->cropcap.defrect),
- sizeof(struct v4l2_rect));
- cam->state |= DEV_INITIALIZED;
- }
-
- DBG(2, "Initialization succeeded");
- return 0;
-}
-
-/*****************************************************************************/
-
-static void sn9c102_release_resources(struct kref *kref)
-{
- struct sn9c102_device *cam;
-
- mutex_lock(&sn9c102_sysfs_lock);
-
- cam = container_of(kref, struct sn9c102_device, kref);
-
- DBG(2, "V4L2 device %s deregistered",
- video_device_node_name(cam->v4ldev));
- video_set_drvdata(cam->v4ldev, NULL);
- video_unregister_device(cam->v4ldev);
- v4l2_device_unregister(&cam->v4l2_dev);
- usb_put_dev(cam->usbdev);
- kfree(cam->control_buffer);
- kfree(cam);
-
- mutex_unlock(&sn9c102_sysfs_lock);
-
-}
-
-
-static int sn9c102_open(struct file *filp)
-{
- struct sn9c102_device *cam;
- int err = 0;
-
- /*
- A read_trylock() in open() is the only safe way to prevent race
- conditions with disconnect(), one close() and multiple (not
- necessarily simultaneous) attempts to open(). For example, it
- prevents from waiting for a second access, while the device
- structure is being deallocated, after a possible disconnect() and
- during a following close() holding the write lock: given that, after
- this deallocation, no access will be possible anymore, using the
- non-trylock version would have let open() gain the access to the
- device structure improperly.
- For this reason the lock must also not be per-device.
- */
- if (!down_read_trylock(&sn9c102_dev_lock))
- return -ERESTARTSYS;
-
- cam = video_drvdata(filp);
-
- if (wait_for_completion_interruptible(&cam->probe)) {
- up_read(&sn9c102_dev_lock);
- return -ERESTARTSYS;
- }
-
- kref_get(&cam->kref);
-
- /*
- Make sure to isolate all the simultaneous opens.
- */
- if (mutex_lock_interruptible(&cam->open_mutex)) {
- kref_put(&cam->kref, sn9c102_release_resources);
- up_read(&sn9c102_dev_lock);
- return -ERESTARTSYS;
- }
-
- if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present");
- err = -ENODEV;
- goto out;
- }
-
- if (cam->users) {
- DBG(2, "Device %s is already in use",
- video_device_node_name(cam->v4ldev));
- DBG(3, "Simultaneous opens are not supported");
- /*
- open() must follow the open flags and should block
- eventually while the device is in use.
- */
- if ((filp->f_flags & O_NONBLOCK) ||
- (filp->f_flags & O_NDELAY)) {
- err = -EWOULDBLOCK;
- goto out;
- }
- DBG(2, "A blocking open() has been requested. Wait for the "
- "device to be released...");
- up_read(&sn9c102_dev_lock);
- /*
- We will not release the "open_mutex" lock, so that only one
- process can be in the wait queue below. This way the process
- will be sleeping while holding the lock, without losing its
- priority after any wake_up().
- */
- err = wait_event_interruptible_exclusive(cam->wait_open,
- (cam->state & DEV_DISCONNECTED)
- || !cam->users);
- down_read(&sn9c102_dev_lock);
- if (err)
- goto out;
- if (cam->state & DEV_DISCONNECTED) {
- err = -ENODEV;
- goto out;
- }
- }
-
- if (cam->state & DEV_MISCONFIGURED) {
- err = sn9c102_init(cam);
- if (err) {
- DBG(1, "Initialization failed again. "
- "I will retry on next open().");
- goto out;
- }
- cam->state &= ~DEV_MISCONFIGURED;
- }
-
- err = sn9c102_start_transfer(cam);
- if (err)
- goto out;
-
- filp->private_data = cam;
- cam->users++;
- cam->io = IO_NONE;
- cam->stream = STREAM_OFF;
- cam->nbuffers = 0;
- cam->frame_count = 0;
- sn9c102_empty_framequeues(cam);
-
- DBG(3, "Video device %s is open", video_device_node_name(cam->v4ldev));
-
-out:
- mutex_unlock(&cam->open_mutex);
- if (err)
- kref_put(&cam->kref, sn9c102_release_resources);
-
- up_read(&sn9c102_dev_lock);
- return err;
-}
-
-
-static int sn9c102_release(struct file *filp)
-{
- struct sn9c102_device *cam;
-
- down_write(&sn9c102_dev_lock);
-
- cam = video_drvdata(filp);
-
- sn9c102_stop_transfer(cam);
- sn9c102_release_buffers(cam);
- cam->users--;
- wake_up_interruptible_nr(&cam->wait_open, 1);
-
- DBG(3, "Video device %s closed", video_device_node_name(cam->v4ldev));
-
- kref_put(&cam->kref, sn9c102_release_resources);
-
- up_write(&sn9c102_dev_lock);
-
- return 0;
-}
-
-
-static ssize_t
-sn9c102_read(struct file *filp, char __user *buf, size_t count, loff_t *f_pos)
-{
- struct sn9c102_device *cam = video_drvdata(filp);
- struct sn9c102_frame_t *f, *i;
- unsigned long lock_flags;
- long timeout;
- int err = 0;
-
- if (mutex_lock_interruptible(&cam->fileop_mutex))
- return -ERESTARTSYS;
-
- if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present");
- mutex_unlock(&cam->fileop_mutex);
- return -ENODEV;
- }
-
- if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it "
- "again.");
- mutex_unlock(&cam->fileop_mutex);
- return -EIO;
- }
-
- if (cam->io == IO_MMAP) {
- DBG(3, "Close and open the device again to choose "
- "the read method");
- mutex_unlock(&cam->fileop_mutex);
- return -EBUSY;
- }
-
- if (cam->io == IO_NONE) {
- if (!sn9c102_request_buffers(cam, cam->nreadbuffers, IO_READ)) {
- DBG(1, "read() failed, not enough memory");
- mutex_unlock(&cam->fileop_mutex);
- return -ENOMEM;
- }
- cam->io = IO_READ;
- cam->stream = STREAM_ON;
- }
-
- if (list_empty(&cam->inqueue)) {
- if (!list_empty(&cam->outqueue))
- sn9c102_empty_framequeues(cam);
- sn9c102_queue_unusedframes(cam);
- }
-
- if (!count) {
- mutex_unlock(&cam->fileop_mutex);
- return 0;
- }
-
- if (list_empty(&cam->outqueue)) {
- if (filp->f_flags & O_NONBLOCK) {
- mutex_unlock(&cam->fileop_mutex);
- return -EAGAIN;
- }
- if (!cam->module_param.frame_timeout) {
- err = wait_event_interruptible
- (cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED));
- if (err) {
- mutex_unlock(&cam->fileop_mutex);
- return err;
- }
- } else {
- timeout = wait_event_interruptible_timeout
- (cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- msecs_to_jiffies(
- cam->module_param.frame_timeout * 1000
- )
- );
- if (timeout < 0) {
- mutex_unlock(&cam->fileop_mutex);
- return timeout;
- } else if (timeout == 0 &&
- !(cam->state & DEV_DISCONNECTED)) {
- DBG(1, "Video frame timeout elapsed");
- mutex_unlock(&cam->fileop_mutex);
- return -EIO;
- }
- }
- if (cam->state & DEV_DISCONNECTED) {
- mutex_unlock(&cam->fileop_mutex);
- return -ENODEV;
- }
- if (cam->state & DEV_MISCONFIGURED) {
- mutex_unlock(&cam->fileop_mutex);
- return -EIO;
- }
- }
-
- f = list_entry(cam->outqueue.prev, struct sn9c102_frame_t, frame);
-
- if (count > f->buf.bytesused)
- count = f->buf.bytesused;
-
- if (copy_to_user(buf, f->bufmem, count)) {
- err = -EFAULT;
- goto exit;
- }
- *f_pos += count;
-
-exit:
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- list_for_each_entry(i, &cam->outqueue, frame)
- i->state = F_UNUSED;
- INIT_LIST_HEAD(&cam->outqueue);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
- sn9c102_queue_unusedframes(cam);
-
- PDBGG("Frame #%lu, bytes read: %zu",
- (unsigned long)f->buf.index, count);
-
- mutex_unlock(&cam->fileop_mutex);
-
- return count;
-}
-
-
-static unsigned int sn9c102_poll(struct file *filp, poll_table *wait)
-{
- struct sn9c102_device *cam = video_drvdata(filp);
- struct sn9c102_frame_t *f;
- unsigned long lock_flags;
- unsigned int mask = 0;
-
- if (mutex_lock_interruptible(&cam->fileop_mutex))
- return POLLERR;
-
- if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present");
- goto error;
- }
-
- if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it "
- "again.");
- goto error;
- }
-
- if (cam->io == IO_NONE) {
- if (!sn9c102_request_buffers(cam, cam->nreadbuffers,
- IO_READ)) {
- DBG(1, "poll() failed, not enough memory");
- goto error;
- }
- cam->io = IO_READ;
- cam->stream = STREAM_ON;
- }
-
- if (cam->io == IO_READ) {
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- list_for_each_entry(f, &cam->outqueue, frame)
- f->state = F_UNUSED;
- INIT_LIST_HEAD(&cam->outqueue);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
- sn9c102_queue_unusedframes(cam);
- }
-
- poll_wait(filp, &cam->wait_frame, wait);
-
- if (!list_empty(&cam->outqueue))
- mask |= POLLIN | POLLRDNORM;
-
- mutex_unlock(&cam->fileop_mutex);
-
- return mask;
-
-error:
- mutex_unlock(&cam->fileop_mutex);
- return POLLERR;
-}
-
-
-static void sn9c102_vm_open(struct vm_area_struct *vma)
-{
- struct sn9c102_frame_t *f = vma->vm_private_data;
- f->vma_use_count++;
-}
-
-
-static void sn9c102_vm_close(struct vm_area_struct *vma)
-{
- /* NOTE: buffers are not freed here */
- struct sn9c102_frame_t *f = vma->vm_private_data;
- f->vma_use_count--;
-}
-
-
-static const struct vm_operations_struct sn9c102_vm_ops = {
- .open = sn9c102_vm_open,
- .close = sn9c102_vm_close,
-};
-
-
-static int sn9c102_mmap(struct file *filp, struct vm_area_struct *vma)
-{
- struct sn9c102_device *cam = video_drvdata(filp);
- unsigned long size = vma->vm_end - vma->vm_start,
- start = vma->vm_start;
- void *pos;
- u32 i;
-
- if (mutex_lock_interruptible(&cam->fileop_mutex))
- return -ERESTARTSYS;
-
- if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present");
- mutex_unlock(&cam->fileop_mutex);
- return -ENODEV;
- }
-
- if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it "
- "again.");
- mutex_unlock(&cam->fileop_mutex);
- return -EIO;
- }
-
- if (!(vma->vm_flags & (VM_WRITE | VM_READ))) {
- mutex_unlock(&cam->fileop_mutex);
- return -EACCES;
- }
-
- if (cam->io != IO_MMAP ||
- size != PAGE_ALIGN(cam->frame[0].buf.length)) {
- mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
- }
-
- for (i = 0; i < cam->nbuffers; i++) {
- if ((cam->frame[i].buf.m.offset>>PAGE_SHIFT) == vma->vm_pgoff)
- break;
- }
- if (i == cam->nbuffers) {
- mutex_unlock(&cam->fileop_mutex);
- return -EINVAL;
- }
-
- vma->vm_flags |= VM_IO | VM_DONTEXPAND | VM_DONTDUMP;
-
- pos = cam->frame[i].bufmem;
- while (size > 0) { /* size is page-aligned */
- if (vm_insert_page(vma, start, vmalloc_to_page(pos))) {
- mutex_unlock(&cam->fileop_mutex);
- return -EAGAIN;
- }
- start += PAGE_SIZE;
- pos += PAGE_SIZE;
- size -= PAGE_SIZE;
- }
-
- vma->vm_ops = &sn9c102_vm_ops;
- vma->vm_private_data = &cam->frame[i];
- sn9c102_vm_open(vma);
-
- mutex_unlock(&cam->fileop_mutex);
-
- return 0;
-}
-
-/*****************************************************************************/
-
-static int
-sn9c102_vidioc_querycap(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_capability cap = {
- .driver = "sn9c102",
- .version = LINUX_VERSION_CODE,
- .capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_READWRITE |
- V4L2_CAP_STREAMING,
- };
-
- strlcpy(cap.card, cam->v4ldev->name, sizeof(cap.card));
- if (usb_make_path(cam->usbdev, cap.bus_info, sizeof(cap.bus_info)) < 0)
- strlcpy(cap.bus_info, dev_name(&cam->usbdev->dev),
- sizeof(cap.bus_info));
-
- if (copy_to_user(arg, &cap, sizeof(cap)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_enuminput(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_input i;
-
- if (copy_from_user(&i, arg, sizeof(i)))
- return -EFAULT;
-
- if (i.index)
- return -EINVAL;
-
- memset(&i, 0, sizeof(i));
- strcpy(i.name, "Camera");
- i.type = V4L2_INPUT_TYPE_CAMERA;
- i.capabilities = V4L2_IN_CAP_STD;
-
- if (copy_to_user(arg, &i, sizeof(i)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_input(struct sn9c102_device *cam, void __user *arg)
-{
- int index = 0;
-
- if (copy_to_user(arg, &index, sizeof(index)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_input(struct sn9c102_device *cam, void __user *arg)
-{
- int index;
-
- if (copy_from_user(&index, arg, sizeof(index)))
- return -EFAULT;
-
- if (index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_query_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_queryctrl qc;
- u8 i;
-
- if (copy_from_user(&qc, arg, sizeof(qc)))
- return -EFAULT;
-
- for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
- if (qc.id && qc.id == s->qctrl[i].id) {
- memcpy(&qc, &(s->qctrl[i]), sizeof(qc));
- if (copy_to_user(arg, &qc, sizeof(qc)))
- return -EFAULT;
- return 0;
- }
-
- return -EINVAL;
-}
-
-
-static int
-sn9c102_vidioc_g_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_control ctrl;
- int err = 0;
- u8 i;
-
- if (!s->get_ctrl && !s->set_ctrl)
- return -EINVAL;
-
- if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
- return -EFAULT;
-
- if (!s->get_ctrl) {
- for (i = 0; i < ARRAY_SIZE(s->qctrl); i++)
- if (ctrl.id && ctrl.id == s->qctrl[i].id) {
- ctrl.value = s->_qctrl[i].default_value;
- goto exit;
- }
- return -EINVAL;
- } else
- err = s->get_ctrl(cam, &ctrl);
-
-exit:
- if (copy_to_user(arg, &ctrl, sizeof(ctrl)))
- return -EFAULT;
-
- PDBGG("VIDIOC_G_CTRL: id %lu, value %lu",
- (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
- return err;
-}
-
-
-static int
-sn9c102_vidioc_s_ctrl(struct sn9c102_device *cam, void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_control ctrl;
- u8 i;
- int err = 0;
-
- if (!s->set_ctrl)
- return -EINVAL;
-
- if (copy_from_user(&ctrl, arg, sizeof(ctrl)))
- return -EFAULT;
-
- for (i = 0; i < ARRAY_SIZE(s->qctrl); i++) {
- if (ctrl.id == s->qctrl[i].id) {
- if (s->qctrl[i].flags & V4L2_CTRL_FLAG_DISABLED)
- return -EINVAL;
- if (ctrl.value < s->qctrl[i].minimum ||
- ctrl.value > s->qctrl[i].maximum)
- return -ERANGE;
- ctrl.value -= ctrl.value % s->qctrl[i].step;
- break;
- }
- }
- if (i == ARRAY_SIZE(s->qctrl))
- return -EINVAL;
- err = s->set_ctrl(cam, &ctrl);
- if (err)
- return err;
-
- s->_qctrl[i].default_value = ctrl.value;
-
- PDBGG("VIDIOC_S_CTRL: id %lu, value %lu",
- (unsigned long)ctrl.id, (unsigned long)ctrl.value);
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_cropcap(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_cropcap *cc = &(cam->sensor.cropcap);
-
- cc->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- cc->pixelaspect.numerator = 1;
- cc->pixelaspect.denominator = 1;
-
- if (copy_to_user(arg, cc, sizeof(*cc)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_crop(struct sn9c102_device *cam, void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_crop crop = {
- .type = V4L2_BUF_TYPE_VIDEO_CAPTURE,
- };
-
- memcpy(&(crop.c), &(s->_rect), sizeof(struct v4l2_rect));
-
- if (copy_to_user(arg, &crop, sizeof(crop)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_crop(struct sn9c102_device *cam, void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_crop crop;
- struct v4l2_rect *rect;
- struct v4l2_rect *bounds = &(s->cropcap.bounds);
- struct v4l2_pix_format *pix_format = &(s->pix_format);
- u8 scale;
- const enum sn9c102_stream_state stream = cam->stream;
- const u32 nbuffers = cam->nbuffers;
- u32 i;
- int err = 0;
-
- if (copy_from_user(&crop, arg, sizeof(crop)))
- return -EFAULT;
-
- rect = &(crop.c);
-
- if (crop.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- if (cam->module_param.force_munmap)
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_S_CROP failed. "
- "Unmap the buffers first.");
- return -EBUSY;
- }
-
- /* Preserve R,G or B origin */
- rect->left = (s->_rect.left & 1L) ? rect->left | 1L : rect->left & ~1L;
- rect->top = (s->_rect.top & 1L) ? rect->top | 1L : rect->top & ~1L;
-
- if (rect->width < 16)
- rect->width = 16;
- if (rect->height < 16)
- rect->height = 16;
- if (rect->width > bounds->width)
- rect->width = bounds->width;
- if (rect->height > bounds->height)
- rect->height = bounds->height;
- if (rect->left < bounds->left)
- rect->left = bounds->left;
- if (rect->top < bounds->top)
- rect->top = bounds->top;
- if (rect->left + rect->width > bounds->left + bounds->width)
- rect->left = bounds->left+bounds->width - rect->width;
- if (rect->top + rect->height > bounds->top + bounds->height)
- rect->top = bounds->top+bounds->height - rect->height;
-
- rect->width &= ~15L;
- rect->height &= ~15L;
-
- if (SN9C102_PRESERVE_IMGSCALE) {
- /* Calculate the actual scaling factor */
- u32 a, b;
- a = rect->width * rect->height;
- b = pix_format->width * pix_format->height;
- scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
- } else
- scale = 1;
-
- if (cam->stream == STREAM_ON) {
- err = sn9c102_stream_interrupt(cam);
- if (err)
- return err;
- }
-
- if (copy_to_user(arg, &crop, sizeof(crop))) {
- cam->stream = stream;
- return -EFAULT;
- }
-
- if (cam->module_param.force_munmap || cam->io == IO_READ)
- sn9c102_release_buffers(cam);
-
- err = sn9c102_set_crop(cam, rect);
- if (s->set_crop)
- err += s->set_crop(cam, rect);
- err += sn9c102_set_scale(cam, scale);
-
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_CROP failed because of hardware problems. To "
- "use the camera, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -EIO;
- }
-
- s->pix_format.width = rect->width/scale;
- s->pix_format.height = rect->height/scale;
- memcpy(&(s->_rect), rect, sizeof(*rect));
-
- if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
- nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_CROP failed because of not enough memory. To "
- "use the camera, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -ENOMEM;
- }
-
- if (cam->io == IO_READ)
- sn9c102_empty_framequeues(cam);
- else if (cam->module_param.force_munmap)
- sn9c102_requeue_outqueue(cam);
-
- cam->stream = stream;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_framesizes(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_frmsizeenum frmsize;
-
- if (copy_from_user(&frmsize, arg, sizeof(frmsize)))
- return -EFAULT;
-
- if (frmsize.index != 0)
- return -EINVAL;
-
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- if (frmsize.pixel_format != V4L2_PIX_FMT_SN9C10X &&
- frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
- return -EINVAL;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (frmsize.pixel_format != V4L2_PIX_FMT_JPEG &&
- frmsize.pixel_format != V4L2_PIX_FMT_SBGGR8)
- return -EINVAL;
- break;
- }
-
- frmsize.type = V4L2_FRMSIZE_TYPE_STEPWISE;
- frmsize.stepwise.min_width = frmsize.stepwise.step_width = 16;
- frmsize.stepwise.min_height = frmsize.stepwise.step_height = 16;
- frmsize.stepwise.max_width = cam->sensor.cropcap.bounds.width;
- frmsize.stepwise.max_height = cam->sensor.cropcap.bounds.height;
- memset(&frmsize.reserved, 0, sizeof(frmsize.reserved));
-
- if (copy_to_user(arg, &frmsize, sizeof(frmsize)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_enum_fmt(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_fmtdesc fmtd;
-
- if (copy_from_user(&fmtd, arg, sizeof(fmtd)))
- return -EFAULT;
-
- if (fmtd.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- if (fmtd.index == 0) {
- strcpy(fmtd.description, "bayer rgb");
- fmtd.pixelformat = V4L2_PIX_FMT_SBGGR8;
- } else if (fmtd.index == 1) {
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- strcpy(fmtd.description, "compressed");
- fmtd.pixelformat = V4L2_PIX_FMT_SN9C10X;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- strcpy(fmtd.description, "JPEG");
- fmtd.pixelformat = V4L2_PIX_FMT_JPEG;
- break;
- }
- fmtd.flags = V4L2_FMT_FLAG_COMPRESSED;
- } else
- return -EINVAL;
-
- fmtd.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
- memset(&fmtd.reserved, 0, sizeof(fmtd.reserved));
-
- if (copy_to_user(arg, &fmtd, sizeof(fmtd)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_fmt(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_format format;
- struct v4l2_pix_format *pfmt = &(cam->sensor.pix_format);
-
- if (copy_from_user(&format, arg, sizeof(format)))
- return -EFAULT;
-
- if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- pfmt->colorspace = (pfmt->pixelformat == V4L2_PIX_FMT_JPEG) ?
- V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
- pfmt->bytesperline = (pfmt->pixelformat == V4L2_PIX_FMT_SN9C10X ||
- pfmt->pixelformat == V4L2_PIX_FMT_JPEG)
- ? 0 : (pfmt->width * pfmt->priv) / 8;
- pfmt->sizeimage = pfmt->height * ((pfmt->width*pfmt->priv)/8);
- pfmt->field = V4L2_FIELD_NONE;
- memcpy(&(format.fmt.pix), pfmt, sizeof(*pfmt));
-
- if (copy_to_user(arg, &format, sizeof(format)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_try_s_fmt(struct sn9c102_device *cam, unsigned int cmd,
- void __user *arg)
-{
- struct sn9c102_sensor *s = &cam->sensor;
- struct v4l2_format format;
- struct v4l2_pix_format *pix;
- struct v4l2_pix_format *pfmt = &(s->pix_format);
- struct v4l2_rect *bounds = &(s->cropcap.bounds);
- struct v4l2_rect rect;
- u8 scale;
- const enum sn9c102_stream_state stream = cam->stream;
- const u32 nbuffers = cam->nbuffers;
- u32 i;
- int err = 0;
-
- if (copy_from_user(&format, arg, sizeof(format)))
- return -EFAULT;
-
- pix = &(format.fmt.pix);
-
- if (format.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- memcpy(&rect, &(s->_rect), sizeof(rect));
-
- { /* calculate the actual scaling factor */
- u32 a, b;
- a = rect.width * rect.height;
- b = pix->width * pix->height;
- scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
- }
-
- rect.width = scale * pix->width;
- rect.height = scale * pix->height;
-
- if (rect.width < 16)
- rect.width = 16;
- if (rect.height < 16)
- rect.height = 16;
- if (rect.width > bounds->left + bounds->width - rect.left)
- rect.width = bounds->left + bounds->width - rect.left;
- if (rect.height > bounds->top + bounds->height - rect.top)
- rect.height = bounds->top + bounds->height - rect.top;
-
- rect.width &= ~15L;
- rect.height &= ~15L;
-
- { /* adjust the scaling factor */
- u32 a, b;
- a = rect.width * rect.height;
- b = pix->width * pix->height;
- scale = b ? (u8)((a / b) < 4 ? 1 : ((a / b) < 16 ? 2 : 4)) : 1;
- }
-
- pix->width = rect.width / scale;
- pix->height = rect.height / scale;
-
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- if (pix->pixelformat != V4L2_PIX_FMT_SN9C10X &&
- pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
- pix->pixelformat = pfmt->pixelformat;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (pix->pixelformat != V4L2_PIX_FMT_JPEG &&
- pix->pixelformat != V4L2_PIX_FMT_SBGGR8)
- pix->pixelformat = pfmt->pixelformat;
- break;
- }
- pix->priv = pfmt->priv; /* bpp */
- pix->colorspace = (pix->pixelformat == V4L2_PIX_FMT_JPEG) ?
- V4L2_COLORSPACE_JPEG : V4L2_COLORSPACE_SRGB;
- pix->bytesperline = (pix->pixelformat == V4L2_PIX_FMT_SN9C10X ||
- pix->pixelformat == V4L2_PIX_FMT_JPEG)
- ? 0 : (pix->width * pix->priv) / 8;
- pix->sizeimage = pix->height * ((pix->width * pix->priv) / 8);
- pix->field = V4L2_FIELD_NONE;
-
- if (cmd == VIDIOC_TRY_FMT) {
- if (copy_to_user(arg, &format, sizeof(format)))
- return -EFAULT;
- return 0;
- }
-
- if (cam->module_param.force_munmap)
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_S_FMT failed. Unmap the "
- "buffers first.");
- return -EBUSY;
- }
-
- if (cam->stream == STREAM_ON) {
- err = sn9c102_stream_interrupt(cam);
- if (err)
- return err;
- }
-
- if (copy_to_user(arg, &format, sizeof(format))) {
- cam->stream = stream;
- return -EFAULT;
- }
-
- if (cam->module_param.force_munmap || cam->io == IO_READ)
- sn9c102_release_buffers(cam);
-
- err += sn9c102_set_pix_format(cam, pix);
- err += sn9c102_set_crop(cam, &rect);
- if (s->set_pix_format)
- err += s->set_pix_format(cam, pix);
- if (s->set_crop)
- err += s->set_crop(cam, &rect);
- err += sn9c102_set_scale(cam, scale);
-
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_FMT failed because of hardware problems. To "
- "use the camera, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -EIO;
- }
-
- memcpy(pfmt, pix, sizeof(*pix));
- memcpy(&(s->_rect), &rect, sizeof(rect));
-
- if ((cam->module_param.force_munmap || cam->io == IO_READ) &&
- nbuffers != sn9c102_request_buffers(cam, nbuffers, cam->io)) {
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_FMT failed because of not enough memory. To "
- "use the camera, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -ENOMEM;
- }
-
- if (cam->io == IO_READ)
- sn9c102_empty_framequeues(cam);
- else if (cam->module_param.force_munmap)
- sn9c102_requeue_outqueue(cam);
-
- cam->stream = stream;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_jpegcomp(struct sn9c102_device *cam, void __user *arg)
-{
- if (copy_to_user(arg, &cam->compression, sizeof(cam->compression)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_jpegcomp(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_jpegcompression jc;
- const enum sn9c102_stream_state stream = cam->stream;
- int err = 0;
-
- if (copy_from_user(&jc, arg, sizeof(jc)))
- return -EFAULT;
-
- if (jc.quality != 0 && jc.quality != 1)
- return -EINVAL;
-
- if (cam->stream == STREAM_ON) {
- err = sn9c102_stream_interrupt(cam);
- if (err)
- return err;
- }
-
- err += sn9c102_set_compression(cam, &jc);
- if (err) { /* atomic, no rollback in ioctl() */
- cam->state |= DEV_MISCONFIGURED;
- DBG(1, "VIDIOC_S_JPEGCOMP failed because of hardware problems. "
- "To use the camera, close and open %s again.",
- video_device_node_name(cam->v4ldev));
- return -EIO;
- }
-
- cam->compression.quality = jc.quality;
-
- cam->stream = stream;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_reqbufs(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_requestbuffers rb;
- u32 i;
- int err;
-
- if (copy_from_user(&rb, arg, sizeof(rb)))
- return -EFAULT;
-
- if (rb.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- rb.memory != V4L2_MEMORY_MMAP)
- return -EINVAL;
-
- if (cam->io == IO_READ) {
- DBG(3, "Close and open the device again to choose the mmap "
- "I/O method");
- return -EBUSY;
- }
-
- for (i = 0; i < cam->nbuffers; i++)
- if (cam->frame[i].vma_use_count) {
- DBG(3, "VIDIOC_REQBUFS failed. Previous buffers are "
- "still mapped.");
- return -EBUSY;
- }
-
- if (cam->stream == STREAM_ON) {
- err = sn9c102_stream_interrupt(cam);
- if (err)
- return err;
- }
-
- sn9c102_empty_framequeues(cam);
-
- sn9c102_release_buffers(cam);
- if (rb.count)
- rb.count = sn9c102_request_buffers(cam, rb.count, IO_MMAP);
-
- if (copy_to_user(arg, &rb, sizeof(rb))) {
- sn9c102_release_buffers(cam);
- cam->io = IO_NONE;
- return -EFAULT;
- }
-
- cam->io = rb.count ? IO_MMAP : IO_NONE;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_querybuf(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_buffer b;
-
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
-
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b.index >= cam->nbuffers || cam->io != IO_MMAP)
- return -EINVAL;
-
- b = cam->frame[b.index].buf;
-
- if (cam->frame[b.index].vma_use_count)
- b.flags |= V4L2_BUF_FLAG_MAPPED;
-
- if (cam->frame[b.index].state == F_DONE)
- b.flags |= V4L2_BUF_FLAG_DONE;
- else if (cam->frame[b.index].state != F_UNUSED)
- b.flags |= V4L2_BUF_FLAG_QUEUED;
-
- if (copy_to_user(arg, &b, sizeof(b)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_qbuf(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_buffer b;
- unsigned long lock_flags;
-
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
-
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
- b.index >= cam->nbuffers || cam->io != IO_MMAP)
- return -EINVAL;
-
- if (cam->frame[b.index].state != F_UNUSED)
- return -EINVAL;
-
- cam->frame[b.index].state = F_QUEUED;
-
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- list_add_tail(&cam->frame[b.index].frame, &cam->inqueue);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
- PDBGG("Frame #%lu queued", (unsigned long)b.index);
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_dqbuf(struct sn9c102_device *cam, struct file *filp,
- void __user *arg)
-{
- struct v4l2_buffer b;
- struct sn9c102_frame_t *f;
- unsigned long lock_flags;
- long timeout;
- int err = 0;
-
- if (copy_from_user(&b, arg, sizeof(b)))
- return -EFAULT;
-
- if (b.type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
- return -EINVAL;
-
- if (list_empty(&cam->outqueue)) {
- if (cam->stream == STREAM_OFF)
- return -EINVAL;
- if (filp->f_flags & O_NONBLOCK)
- return -EAGAIN;
- if (!cam->module_param.frame_timeout) {
- err = wait_event_interruptible
- (cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED));
- if (err)
- return err;
- } else {
- timeout = wait_event_interruptible_timeout
- (cam->wait_frame,
- (!list_empty(&cam->outqueue)) ||
- (cam->state & DEV_DISCONNECTED) ||
- (cam->state & DEV_MISCONFIGURED),
- cam->module_param.frame_timeout *
- 1000 * msecs_to_jiffies(1));
- if (timeout < 0)
- return timeout;
- else if (timeout == 0 &&
- !(cam->state & DEV_DISCONNECTED)) {
- DBG(1, "Video frame timeout elapsed");
- return -EIO;
- }
- }
- if (cam->state & DEV_DISCONNECTED)
- return -ENODEV;
- if (cam->state & DEV_MISCONFIGURED)
- return -EIO;
- }
-
- spin_lock_irqsave(&cam->queue_lock, lock_flags);
- f = list_entry(cam->outqueue.next, struct sn9c102_frame_t, frame);
- list_del(cam->outqueue.next);
- spin_unlock_irqrestore(&cam->queue_lock, lock_flags);
-
- f->state = F_UNUSED;
-
- b = f->buf;
- if (f->vma_use_count)
- b.flags |= V4L2_BUF_FLAG_MAPPED;
-
- if (copy_to_user(arg, &b, sizeof(b)))
- return -EFAULT;
-
- PDBGG("Frame #%lu dequeued", (unsigned long)f->buf.index);
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamon(struct sn9c102_device *cam, void __user *arg)
-{
- int type;
-
- if (copy_from_user(&type, arg, sizeof(type)))
- return -EFAULT;
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
- return -EINVAL;
-
- cam->stream = STREAM_ON;
-
- DBG(3, "Stream on");
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_streamoff(struct sn9c102_device *cam, void __user *arg)
-{
- int type, err;
-
- if (copy_from_user(&type, arg, sizeof(type)))
- return -EFAULT;
-
- if (type != V4L2_BUF_TYPE_VIDEO_CAPTURE || cam->io != IO_MMAP)
- return -EINVAL;
-
- if (cam->stream == STREAM_ON) {
- err = sn9c102_stream_interrupt(cam);
- if (err)
- return err;
- }
-
- sn9c102_empty_framequeues(cam);
-
- DBG(3, "Stream off");
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_parm(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_streamparm sp;
-
- if (copy_from_user(&sp, arg, sizeof(sp)))
- return -EFAULT;
-
- if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- sp.parm.capture.extendedmode = 0;
- sp.parm.capture.readbuffers = cam->nreadbuffers;
-
- if (copy_to_user(arg, &sp, sizeof(sp)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_parm(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_streamparm sp;
-
- if (copy_from_user(&sp, arg, sizeof(sp)))
- return -EFAULT;
-
- if (sp.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
- return -EINVAL;
-
- sp.parm.capture.extendedmode = 0;
-
- if (sp.parm.capture.readbuffers == 0)
- sp.parm.capture.readbuffers = cam->nreadbuffers;
-
- if (sp.parm.capture.readbuffers > SN9C102_MAX_FRAMES)
- sp.parm.capture.readbuffers = SN9C102_MAX_FRAMES;
-
- if (copy_to_user(arg, &sp, sizeof(sp)))
- return -EFAULT;
-
- cam->nreadbuffers = sp.parm.capture.readbuffers;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_enumaudio(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_audio audio;
-
- if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
- return -EINVAL;
-
- if (copy_from_user(&audio, arg, sizeof(audio)))
- return -EFAULT;
-
- if (audio.index != 0)
- return -EINVAL;
-
- strcpy(audio.name, "Microphone");
- audio.capability = 0;
- audio.mode = 0;
-
- if (copy_to_user(arg, &audio, sizeof(audio)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_g_audio(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_audio audio;
-
- if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
- return -EINVAL;
-
- if (copy_from_user(&audio, arg, sizeof(audio)))
- return -EFAULT;
-
- memset(&audio, 0, sizeof(audio));
- strcpy(audio.name, "Microphone");
-
- if (copy_to_user(arg, &audio, sizeof(audio)))
- return -EFAULT;
-
- return 0;
-}
-
-
-static int
-sn9c102_vidioc_s_audio(struct sn9c102_device *cam, void __user *arg)
-{
- struct v4l2_audio audio;
-
- if (cam->bridge == BRIDGE_SN9C101 || cam->bridge == BRIDGE_SN9C102)
- return -EINVAL;
-
- if (copy_from_user(&audio, arg, sizeof(audio)))
- return -EFAULT;
-
- if (audio.index != 0)
- return -EINVAL;
-
- return 0;
-}
-
-
-static long sn9c102_ioctl_v4l2(struct file *filp,
- unsigned int cmd, void __user *arg)
-{
- struct sn9c102_device *cam = video_drvdata(filp);
-
- switch (cmd) {
-
- case VIDIOC_QUERYCAP:
- return sn9c102_vidioc_querycap(cam, arg);
-
- case VIDIOC_ENUMINPUT:
- return sn9c102_vidioc_enuminput(cam, arg);
-
- case VIDIOC_G_INPUT:
- return sn9c102_vidioc_g_input(cam, arg);
-
- case VIDIOC_S_INPUT:
- return sn9c102_vidioc_s_input(cam, arg);
-
- case VIDIOC_QUERYCTRL:
- return sn9c102_vidioc_query_ctrl(cam, arg);
-
- case VIDIOC_G_CTRL:
- return sn9c102_vidioc_g_ctrl(cam, arg);
-
- case VIDIOC_S_CTRL:
- return sn9c102_vidioc_s_ctrl(cam, arg);
-
- case VIDIOC_CROPCAP:
- return sn9c102_vidioc_cropcap(cam, arg);
-
- case VIDIOC_G_CROP:
- return sn9c102_vidioc_g_crop(cam, arg);
-
- case VIDIOC_S_CROP:
- return sn9c102_vidioc_s_crop(cam, arg);
-
- case VIDIOC_ENUM_FRAMESIZES:
- return sn9c102_vidioc_enum_framesizes(cam, arg);
-
- case VIDIOC_ENUM_FMT:
- return sn9c102_vidioc_enum_fmt(cam, arg);
-
- case VIDIOC_G_FMT:
- return sn9c102_vidioc_g_fmt(cam, arg);
-
- case VIDIOC_TRY_FMT:
- case VIDIOC_S_FMT:
- return sn9c102_vidioc_try_s_fmt(cam, cmd, arg);
-
- case VIDIOC_G_JPEGCOMP:
- return sn9c102_vidioc_g_jpegcomp(cam, arg);
-
- case VIDIOC_S_JPEGCOMP:
- return sn9c102_vidioc_s_jpegcomp(cam, arg);
-
- case VIDIOC_REQBUFS:
- return sn9c102_vidioc_reqbufs(cam, arg);
-
- case VIDIOC_QUERYBUF:
- return sn9c102_vidioc_querybuf(cam, arg);
-
- case VIDIOC_QBUF:
- return sn9c102_vidioc_qbuf(cam, arg);
-
- case VIDIOC_DQBUF:
- return sn9c102_vidioc_dqbuf(cam, filp, arg);
-
- case VIDIOC_STREAMON:
- return sn9c102_vidioc_streamon(cam, arg);
-
- case VIDIOC_STREAMOFF:
- return sn9c102_vidioc_streamoff(cam, arg);
-
- case VIDIOC_G_PARM:
- return sn9c102_vidioc_g_parm(cam, arg);
-
- case VIDIOC_S_PARM:
- return sn9c102_vidioc_s_parm(cam, arg);
-
- case VIDIOC_ENUMAUDIO:
- return sn9c102_vidioc_enumaudio(cam, arg);
-
- case VIDIOC_G_AUDIO:
- return sn9c102_vidioc_g_audio(cam, arg);
-
- case VIDIOC_S_AUDIO:
- return sn9c102_vidioc_s_audio(cam, arg);
-
- default:
- return -ENOTTY;
-
- }
-}
-
-
-static long sn9c102_ioctl(struct file *filp,
- unsigned int cmd, unsigned long arg)
-{
- struct sn9c102_device *cam = video_drvdata(filp);
- int err = 0;
-
- if (mutex_lock_interruptible(&cam->fileop_mutex))
- return -ERESTARTSYS;
-
- if (cam->state & DEV_DISCONNECTED) {
- DBG(1, "Device not present");
- mutex_unlock(&cam->fileop_mutex);
- return -ENODEV;
- }
-
- if (cam->state & DEV_MISCONFIGURED) {
- DBG(1, "The camera is misconfigured. Close and open it "
- "again.");
- mutex_unlock(&cam->fileop_mutex);
- return -EIO;
- }
-
- V4LDBG(3, "sn9c102", cmd);
-
- err = sn9c102_ioctl_v4l2(filp, cmd, (void __user *)arg);
-
- mutex_unlock(&cam->fileop_mutex);
-
- return err;
-}
-
-/*****************************************************************************/
-
-static const struct v4l2_file_operations sn9c102_fops = {
- .owner = THIS_MODULE,
- .open = sn9c102_open,
- .release = sn9c102_release,
- .unlocked_ioctl = sn9c102_ioctl,
- .read = sn9c102_read,
- .poll = sn9c102_poll,
- .mmap = sn9c102_mmap,
-};
-
-/*****************************************************************************/
-
-/* It exists a single interface only. We do not need to validate anything. */
-static int
-sn9c102_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
- struct usb_device *udev = interface_to_usbdev(intf);
- struct sn9c102_device *cam;
- static unsigned int dev_nr;
- unsigned int i;
- int err = 0, r;
-
- cam = kzalloc(sizeof(struct sn9c102_device), GFP_KERNEL);
- if (!cam)
- return -ENOMEM;
-
- cam->usbdev = udev;
-
- /* register v4l2_device early so it can be used for printks */
- if (v4l2_device_register(&intf->dev, &cam->v4l2_dev)) {
- dev_err(&intf->dev, "v4l2_device_register failed\n");
- err = -ENOMEM;
- goto fail;
- }
-
- cam->control_buffer = kzalloc(8, GFP_KERNEL);
- if (!cam->control_buffer) {
- DBG(1, "kzalloc() failed");
- err = -ENOMEM;
- goto fail;
- }
-
- cam->v4ldev = video_device_alloc();
- if (!cam->v4ldev) {
- DBG(1, "video_device_alloc() failed");
- err = -ENOMEM;
- goto fail;
- }
-
- r = sn9c102_read_reg(cam, 0x00);
- if (r < 0 || (r != 0x10 && r != 0x11 && r != 0x12)) {
- DBG(1, "Sorry, this is not a SN9C1xx-based camera "
- "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
- err = -ENODEV;
- goto fail;
- }
-
- cam->bridge = id->driver_info;
- switch (cam->bridge) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- DBG(2, "SN9C10[12] PC Camera Controller detected "
- "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
- break;
- case BRIDGE_SN9C103:
- DBG(2, "SN9C103 PC Camera Controller detected "
- "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
- break;
- case BRIDGE_SN9C105:
- DBG(2, "SN9C105 PC Camera Controller detected "
- "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
- break;
- case BRIDGE_SN9C120:
- DBG(2, "SN9C120 PC Camera Controller detected "
- "(vid:pid 0x%04X:0x%04X)", id->idVendor, id->idProduct);
- break;
- }
-
- for (i = 0; i < ARRAY_SIZE(sn9c102_sensor_table); i++) {
- err = sn9c102_sensor_table[i](cam);
- if (!err)
- break;
- }
-
- if (!err) {
- DBG(2, "%s image sensor detected", cam->sensor.name);
- DBG(3, "Support for %s maintained by %s",
- cam->sensor.name, cam->sensor.maintainer);
- } else {
- DBG(1, "No supported image sensor detected for this bridge");
- err = -ENODEV;
- goto fail;
- }
-
- if (!(cam->bridge & cam->sensor.supported_bridge)) {
- DBG(1, "Bridge not supported");
- err = -ENODEV;
- goto fail;
- }
-
- if (sn9c102_init(cam)) {
- DBG(1, "Initialization failed. I will retry on open().");
- cam->state |= DEV_MISCONFIGURED;
- }
-
- strcpy(cam->v4ldev->name, "SN9C1xx PC Camera");
- cam->v4ldev->fops = &sn9c102_fops;
- cam->v4ldev->release = video_device_release;
- cam->v4ldev->v4l2_dev = &cam->v4l2_dev;
-
- init_completion(&cam->probe);
-
- err = video_register_device(cam->v4ldev, VFL_TYPE_GRABBER,
- video_nr[dev_nr]);
- if (err) {
- DBG(1, "V4L2 device registration failed");
- if (err == -ENFILE && video_nr[dev_nr] == -1)
- DBG(1, "Free /dev/videoX node not found");
- video_nr[dev_nr] = -1;
- dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
- complete_all(&cam->probe);
- goto fail;
- }
-
- DBG(2, "V4L2 device registered as %s",
- video_device_node_name(cam->v4ldev));
-
- video_set_drvdata(cam->v4ldev, cam);
- cam->module_param.force_munmap = force_munmap[dev_nr];
- cam->module_param.frame_timeout = frame_timeout[dev_nr];
-
- dev_nr = (dev_nr < SN9C102_MAX_DEVICES-1) ? dev_nr+1 : 0;
-
-#ifdef CONFIG_VIDEO_ADV_DEBUG
- err = sn9c102_create_sysfs(cam);
- if (!err)
- DBG(2, "Optional device control through 'sysfs' "
- "interface ready");
- else
- DBG(2, "Failed to create optional 'sysfs' interface for "
- "device controlling. Error #%d", err);
-#else
- DBG(2, "Optional device control through 'sysfs' interface disabled");
- DBG(3, "Compile the kernel with the 'CONFIG_VIDEO_ADV_DEBUG' "
- "configuration option to enable it.");
-#endif
-
- usb_set_intfdata(intf, cam);
- kref_init(&cam->kref);
- usb_get_dev(cam->usbdev);
-
- complete_all(&cam->probe);
-
- return 0;
-
-fail:
- if (cam) {
- kfree(cam->control_buffer);
- if (cam->v4ldev)
- video_device_release(cam->v4ldev);
- v4l2_device_unregister(&cam->v4l2_dev);
- kfree(cam);
- }
- return err;
-}
-
-
-static void sn9c102_usb_disconnect(struct usb_interface *intf)
-{
- struct sn9c102_device *cam;
-
- down_write(&sn9c102_dev_lock);
-
- cam = usb_get_intfdata(intf);
-
- DBG(2, "Disconnecting %s...", cam->v4ldev->name);
-
- if (cam->users) {
- DBG(2, "Device %s is open! Deregistration and memory "
- "deallocation are deferred.",
- video_device_node_name(cam->v4ldev));
- cam->state |= DEV_MISCONFIGURED;
- sn9c102_stop_transfer(cam);
- cam->state |= DEV_DISCONNECTED;
- wake_up_interruptible(&cam->wait_frame);
- wake_up(&cam->wait_stream);
- } else
- cam->state |= DEV_DISCONNECTED;
-
- wake_up_interruptible_all(&cam->wait_open);
-
- v4l2_device_disconnect(&cam->v4l2_dev);
-
- kref_put(&cam->kref, sn9c102_release_resources);
-
- up_write(&sn9c102_dev_lock);
-}
-
-
-static struct usb_driver sn9c102_usb_driver = {
- .name = "sn9c102",
- .id_table = sn9c102_id_table,
- .probe = sn9c102_usb_probe,
- .disconnect = sn9c102_usb_disconnect,
-};
-
-module_usb_driver(sn9c102_usb_driver);
diff --git a/drivers/staging/media/sn9c102/sn9c102_devtable.h b/drivers/staging/media/sn9c102/sn9c102_devtable.h
deleted file mode 100644
index b187a8a304eb..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_devtable.h
+++ /dev/null
@@ -1,145 +0,0 @@
-/***************************************************************************
- * Table of device identifiers of the SN9C1xx PC Camera Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#ifndef _SN9C102_DEVTABLE_H_
-#define _SN9C102_DEVTABLE_H_
-
-#include <linux/usb.h>
-
-struct sn9c102_device;
-
-/*
- Each SN9C1xx camera has proper PID/VID identifiers.
- SN9C103, SN9C105, SN9C120 support multiple interfaces, but we only have to
- handle the video class interface.
-*/
-#define SN9C102_USB_DEVICE(vend, prod, bridge) \
- .match_flags = USB_DEVICE_ID_MATCH_DEVICE | \
- USB_DEVICE_ID_MATCH_INT_CLASS, \
- .idVendor = (vend), \
- .idProduct = (prod), \
- .bInterfaceClass = 0xff, \
- .driver_info = (bridge)
-
-static const struct usb_device_id sn9c102_id_table[] = {
- /* SN9C101 and SN9C102 */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
- { SN9C102_USB_DEVICE(0x0c45, 0x6001, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6005, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6007, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6009, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x600d, BRIDGE_SN9C102), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6011, BRIDGE_SN9C102), }, OV6650 */
- { SN9C102_USB_DEVICE(0x0c45, 0x6019, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6024, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6025, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6028, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x6029, BRIDGE_SN9C102), },
- { SN9C102_USB_DEVICE(0x0c45, 0x602a, BRIDGE_SN9C102), },
-#endif
- { SN9C102_USB_DEVICE(0x0c45, 0x602b, BRIDGE_SN9C102), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
- { SN9C102_USB_DEVICE(0x0c45, 0x602c, BRIDGE_SN9C102), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x602d, BRIDGE_SN9C102), }, HV7131R */
- { SN9C102_USB_DEVICE(0x0c45, 0x602e, BRIDGE_SN9C102), },
-#endif
- { SN9C102_USB_DEVICE(0x0c45, 0x6030, BRIDGE_SN9C102), }, /* not in sonixb */
- /* SN9C103 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6080, BRIDGE_SN9C103), }, non existent ? */
- { SN9C102_USB_DEVICE(0x0c45, 0x6082, BRIDGE_SN9C103), }, /* not in sonixb */
-#if !defined CONFIG_USB_GSPCA_SONIXB && !defined CONFIG_USB_GSPCA_SONIXB_MODULE
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6083, BRIDGE_SN9C103), }, HY7131D/E */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6088, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x608a, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x608b, BRIDGE_SN9C103), }, non existent ? */
- { SN9C102_USB_DEVICE(0x0c45, 0x608c, BRIDGE_SN9C103), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x608e, BRIDGE_SN9C103), }, CISVF10 */
- { SN9C102_USB_DEVICE(0x0c45, 0x608f, BRIDGE_SN9C103), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60a0, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60a2, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60a3, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60a8, BRIDGE_SN9C103), }, PAS106 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60aa, BRIDGE_SN9C103), }, TAS5130 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ab, BRIDGE_SN9C103), }, TAS5110, non existent */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ac, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ae, BRIDGE_SN9C103), }, non existent ? */
- { SN9C102_USB_DEVICE(0x0c45, 0x60af, BRIDGE_SN9C103), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60b0, BRIDGE_SN9C103), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60b2, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60b3, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60b8, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ba, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60bb, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60bc, BRIDGE_SN9C103), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60be, BRIDGE_SN9C103), }, non existent ? */
-#endif
- /* SN9C105 */
-#if !defined CONFIG_USB_GSPCA_SONIXJ && !defined CONFIG_USB_GSPCA_SONIXJ_MODULE
- { SN9C102_USB_DEVICE(0x045e, 0x00f5, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x045e, 0x00f7, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x0471, 0x0327, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x0471, 0x0328, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60c0, BRIDGE_SN9C105), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60c2, BRIDGE_SN9C105), }, PO1030 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60c8, BRIDGE_SN9C105), }, OM6801 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60cc, BRIDGE_SN9C105), }, HV7131GP */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ea, BRIDGE_SN9C105), }, non existent ? */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ec, BRIDGE_SN9C105), }, MO4000 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60ef, BRIDGE_SN9C105), }, ICM105C */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x60fa, BRIDGE_SN9C105), }, OV7648 */
- { SN9C102_USB_DEVICE(0x0c45, 0x60fb, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60fc, BRIDGE_SN9C105), },
- { SN9C102_USB_DEVICE(0x0c45, 0x60fe, BRIDGE_SN9C105), },
- /* SN9C120 */
- { SN9C102_USB_DEVICE(0x0458, 0x7025, BRIDGE_SN9C120), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6102, BRIDGE_SN9C120), }, po2030 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6108, BRIDGE_SN9C120), }, om6801 */
-/* { SN9C102_USB_DEVICE(0x0c45, 0x610f, BRIDGE_SN9C120), }, S5K53BEB */
- { SN9C102_USB_DEVICE(0x0c45, 0x6130, BRIDGE_SN9C120), },
-/* { SN9C102_USB_DEVICE(0x0c45, 0x6138, BRIDGE_SN9C120), }, MO8000 */
- { SN9C102_USB_DEVICE(0x0c45, 0x613a, BRIDGE_SN9C120), },
- { SN9C102_USB_DEVICE(0x0c45, 0x613b, BRIDGE_SN9C120), },
- { SN9C102_USB_DEVICE(0x0c45, 0x613c, BRIDGE_SN9C120), },
- { SN9C102_USB_DEVICE(0x0c45, 0x613e, BRIDGE_SN9C120), },
-#endif
- { }
-};
-
-/*
- Probing functions: on success, you must attach the sensor to the camera
- by calling sn9c102_attach_sensor().
- To enable the I2C communication, you might need to perform a really basic
- initialization of the SN9C1XX chip.
- Functions must return 0 on success, the appropriate error otherwise.
-*/
-extern int sn9c102_probe_hv7131d(struct sn9c102_device *cam);
-extern int sn9c102_probe_hv7131r(struct sn9c102_device *cam);
-extern int sn9c102_probe_mi0343(struct sn9c102_device *cam);
-extern int sn9c102_probe_mi0360(struct sn9c102_device *cam);
-extern int sn9c102_probe_mt9v111(struct sn9c102_device *cam);
-extern int sn9c102_probe_ov7630(struct sn9c102_device *cam);
-extern int sn9c102_probe_ov7660(struct sn9c102_device *cam);
-extern int sn9c102_probe_pas106b(struct sn9c102_device *cam);
-extern int sn9c102_probe_pas202bcb(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5110d(struct sn9c102_device *cam);
-extern int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam);
-
-#endif /* _SN9C102_DEVTABLE_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c b/drivers/staging/media/sn9c102/sn9c102_hv7131d.c
deleted file mode 100644
index f1d94f0190c6..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_hv7131d.c
+++ /dev/null
@@ -1,269 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131D image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131d_init(struct sn9c102_device *cam)
-{
- int err;
-
- err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
- {0x00, 0x14}, {0x60, 0x17},
- {0x0e, 0x18}, {0xf2, 0x19});
-
- err += sn9c102_i2c_write(cam, 0x01, 0x04);
- err += sn9c102_i2c_write(cam, 0x02, 0x00);
- err += sn9c102_i2c_write(cam, 0x28, 0x00);
-
- return err;
-}
-
-
-static int hv7131d_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- {
- int r1 = sn9c102_i2c_read(cam, 0x26),
- r2 = sn9c102_i2c_read(cam, 0x27);
- if (r1 < 0 || r2 < 0)
- return -EIO;
- ctrl->value = (r1 << 8) | (r2 & 0xff);
- }
- return 0;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x31);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = 0x3f - (ctrl->value & 0x3f);
- return 0;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x33);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = 0x3f - (ctrl->value & 0x3f);
- return 0;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x32);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = 0x3f - (ctrl->value & 0x3f);
- return 0;
- case SN9C102_V4L2_CID_RESET_LEVEL:
- ctrl->value = sn9c102_i2c_read(cam, 0x30);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x3f;
- return 0;
- case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
- ctrl->value = sn9c102_i2c_read(cam, 0x34);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x07;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-static int hv7131d_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x26, ctrl->value >> 8);
- err += sn9c102_i2c_write(cam, 0x27, ctrl->value & 0xff);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_write(cam, 0x31, 0x3f - ctrl->value);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_write(cam, 0x33, 0x3f - ctrl->value);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_write(cam, 0x32, 0x3f - ctrl->value);
- break;
- case SN9C102_V4L2_CID_RESET_LEVEL:
- err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
- break;
- case SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE:
- err += sn9c102_i2c_write(cam, 0x34, ctrl->value);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int hv7131d_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 2,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int hv7131d_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x42, 0x19);
- else
- err += sn9c102_write_reg(cam, 0xf2, 0x19);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor hv7131d = {
- .name = "HV7131D",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x11,
- .init = &hv7131d_init,
- .qctrl = {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x0250,
- .maximum = 0xffff,
- .step = 0x0001,
- .default_value = 0x0250,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x1e,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_RESET_LEVEL,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "reset level",
- .minimum = 0x19,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x30,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "pixel bias voltage",
- .minimum = 0x00,
- .maximum = 0x07,
- .step = 0x01,
- .default_value = 0x02,
- .flags = 0,
- },
- },
- .get_ctrl = &hv7131d_get_ctrl,
- .set_ctrl = &hv7131d_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &hv7131d_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &hv7131d_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131d(struct sn9c102_device *cam)
-{
- int r0 = 0, r1 = 0, err;
-
- err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17});
-
- r0 = sn9c102_i2c_try_read(cam, &hv7131d, 0x00);
- r1 = sn9c102_i2c_try_read(cam, &hv7131d, 0x01);
- if (err || r0 < 0 || r1 < 0)
- return -EIO;
-
- if ((r0 != 0x00 && r0 != 0x01) || r1 != 0x04)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &hv7131d);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c b/drivers/staging/media/sn9c102/sn9c102_hv7131r.c
deleted file mode 100644
index 51b24e000e88..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_hv7131r.c
+++ /dev/null
@@ -1,369 +0,0 @@
-/***************************************************************************
- * Plug-in for HV7131R image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int hv7131r_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C103:
- err = sn9c102_write_const_regs(cam, {0x00, 0x03}, {0x1a, 0x04},
- {0x20, 0x05}, {0x20, 0x06},
- {0x03, 0x10}, {0x00, 0x14},
- {0x60, 0x17}, {0x0a, 0x18},
- {0xf0, 0x19}, {0x1d, 0x1a},
- {0x10, 0x1b}, {0x02, 0x1c},
- {0x03, 0x1d}, {0x0f, 0x1e},
- {0x0c, 0x1f}, {0x00, 0x20},
- {0x10, 0x21}, {0x20, 0x22},
- {0x30, 0x23}, {0x40, 0x24},
- {0x50, 0x25}, {0x60, 0x26},
- {0x70, 0x27}, {0x80, 0x28},
- {0x90, 0x29}, {0xa0, 0x2a},
- {0xb0, 0x2b}, {0xc0, 0x2c},
- {0xd0, 0x2d}, {0xe0, 0x2e},
- {0xf0, 0x2f}, {0xff, 0x30});
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
- {0x00, 0x03}, {0x1a, 0x04},
- {0x44, 0x05}, {0x3e, 0x06},
- {0x1a, 0x07}, {0x03, 0x10},
- {0x08, 0x14}, {0xa3, 0x17},
- {0x4b, 0x18}, {0x00, 0x19},
- {0x1d, 0x1a}, {0x10, 0x1b},
- {0x02, 0x1c}, {0x03, 0x1d},
- {0x0f, 0x1e}, {0x0c, 0x1f},
- {0x00, 0x20}, {0x29, 0x21},
- {0x40, 0x22}, {0x54, 0x23},
- {0x66, 0x24}, {0x76, 0x25},
- {0x85, 0x26}, {0x94, 0x27},
- {0xa1, 0x28}, {0xae, 0x29},
- {0xbb, 0x2a}, {0xc7, 0x2b},
- {0xd3, 0x2c}, {0xde, 0x2d},
- {0xea, 0x2e}, {0xf4, 0x2f},
- {0xff, 0x30}, {0x00, 0x3F},
- {0xC7, 0x40}, {0x01, 0x41},
- {0x44, 0x42}, {0x00, 0x43},
- {0x44, 0x44}, {0x00, 0x45},
- {0x44, 0x46}, {0x00, 0x47},
- {0xC7, 0x48}, {0x01, 0x49},
- {0xC7, 0x4A}, {0x01, 0x4B},
- {0xC7, 0x4C}, {0x01, 0x4D},
- {0x44, 0x4E}, {0x00, 0x4F},
- {0x44, 0x50}, {0x00, 0x51},
- {0x44, 0x52}, {0x00, 0x53},
- {0xC7, 0x54}, {0x01, 0x55},
- {0xC7, 0x56}, {0x01, 0x57},
- {0xC7, 0x58}, {0x01, 0x59},
- {0x44, 0x5A}, {0x00, 0x5B},
- {0x44, 0x5C}, {0x00, 0x5D},
- {0x44, 0x5E}, {0x00, 0x5F},
- {0xC7, 0x60}, {0x01, 0x61},
- {0xC7, 0x62}, {0x01, 0x63},
- {0xC7, 0x64}, {0x01, 0x65},
- {0x44, 0x66}, {0x00, 0x67},
- {0x44, 0x68}, {0x00, 0x69},
- {0x44, 0x6A}, {0x00, 0x6B},
- {0xC7, 0x6C}, {0x01, 0x6D},
- {0xC7, 0x6E}, {0x01, 0x6F},
- {0xC7, 0x70}, {0x01, 0x71},
- {0x44, 0x72}, {0x00, 0x73},
- {0x44, 0x74}, {0x00, 0x75},
- {0x44, 0x76}, {0x00, 0x77},
- {0xC7, 0x78}, {0x01, 0x79},
- {0xC7, 0x7A}, {0x01, 0x7B},
- {0xC7, 0x7C}, {0x01, 0x7D},
- {0x44, 0x7E}, {0x00, 0x7F},
- {0x14, 0x84}, {0x00, 0x85},
- {0x27, 0x86}, {0x00, 0x87},
- {0x07, 0x88}, {0x00, 0x89},
- {0xEC, 0x8A}, {0x0f, 0x8B},
- {0xD8, 0x8C}, {0x0f, 0x8D},
- {0x3D, 0x8E}, {0x00, 0x8F},
- {0x3D, 0x90}, {0x00, 0x91},
- {0xCD, 0x92}, {0x0f, 0x93},
- {0xf7, 0x94}, {0x0f, 0x95},
- {0x0C, 0x96}, {0x00, 0x97},
- {0x00, 0x98}, {0x66, 0x99},
- {0x05, 0x9A}, {0x00, 0x9B},
- {0x04, 0x9C}, {0x00, 0x9D},
- {0x08, 0x9E}, {0x00, 0x9F},
- {0x2D, 0xC0}, {0x2D, 0xC1},
- {0x3A, 0xC2}, {0x05, 0xC3},
- {0x04, 0xC4}, {0x3F, 0xC5},
- {0x00, 0xC6}, {0x00, 0xC7},
- {0x50, 0xC8}, {0x3C, 0xC9},
- {0x28, 0xCA}, {0xD8, 0xCB},
- {0x14, 0xCC}, {0xEC, 0xCD},
- {0x32, 0xCE}, {0xDD, 0xCF},
- {0x32, 0xD0}, {0xDD, 0xD1},
- {0x6A, 0xD2}, {0x50, 0xD3},
- {0x00, 0xD4}, {0x00, 0xD5},
- {0x00, 0xD6});
- break;
- default:
- break;
- }
-
- err += sn9c102_i2c_write(cam, 0x20, 0x00);
- err += sn9c102_i2c_write(cam, 0x21, 0xd6);
- err += sn9c102_i2c_write(cam, 0x25, 0x06);
-
- return err;
-}
-
-
-static int hv7131r_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x30);
- if (ctrl->value < 0)
- return -EIO;
- return 0;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x31);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = ctrl->value & 0x3f;
- return 0;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x33);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = ctrl->value & 0x3f;
- return 0;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x32);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = ctrl->value & 0x3f;
- return 0;
- case V4L2_CID_BLACK_LEVEL:
- ctrl->value = sn9c102_i2c_read(cam, 0x01);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x08) ? 1 : 0;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-static int hv7131r_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x30, ctrl->value);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_write(cam, 0x31, ctrl->value);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_write(cam, 0x33, ctrl->value);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_write(cam, 0x32, ctrl->value);
- break;
- case V4L2_CID_BLACK_LEVEL:
- {
- int r = sn9c102_i2c_read(cam, 0x01);
-
- if (r < 0)
- return -EIO;
- err += sn9c102_i2c_write(cam, 0x01,
- (ctrl->value<<3) | (r&0xf7));
- }
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int hv7131r_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int hv7131r_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C103:
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
- err += sn9c102_write_reg(cam, 0xa0, 0x19);
- err += sn9c102_i2c_write(cam, 0x01, 0x04);
- } else {
- err += sn9c102_write_reg(cam, 0x30, 0x19);
- err += sn9c102_i2c_write(cam, 0x01, 0x04);
- }
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
- err += sn9c102_write_reg(cam, 0xa5, 0x17);
- err += sn9c102_i2c_write(cam, 0x01, 0x24);
- } else {
- err += sn9c102_write_reg(cam, 0xa3, 0x17);
- err += sn9c102_i2c_write(cam, 0x01, 0x04);
- }
- break;
- default:
- break;
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor hv7131r = {
- .name = "HV7131R",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x11,
- .init = &hv7131r_init,
- .qctrl = {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = 0x40,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x08,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x1a,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x2f,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLACK_LEVEL,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "auto black level compensation",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- },
- .get_ctrl = &hv7131r_get_ctrl,
- .set_ctrl = &hv7131r_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &hv7131r_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &hv7131r_set_pix_format
-};
-
-
-int sn9c102_probe_hv7131r(struct sn9c102_device *cam)
-{
- int devid, err;
-
- err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x02},
- {0x34, 0x01}, {0x20, 0x17},
- {0x34, 0x01}, {0x46, 0x01});
-
- devid = sn9c102_i2c_try_read(cam, &hv7131r, 0x00);
- if (err || devid < 0)
- return -EIO;
-
- if (devid != 0x02)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &hv7131r);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0343.c b/drivers/staging/media/sn9c102/sn9c102_mi0343.c
deleted file mode 100644
index b20fdb6541d3..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mi0343.c
+++ /dev/null
@@ -1,352 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0343 image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0343_init(struct sn9c102_device *cam)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
- {0x0a, 0x14}, {0x40, 0x01},
- {0x20, 0x17}, {0x07, 0x18},
- {0xa0, 0x19});
-
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
- 0x01, 0xe1, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
- 0x02, 0x81, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
- 0x00, 0x17, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
- 0x00, 0x11, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
- 0x04, 0x9a, 0, 0);
-
- return err;
-}
-
-
-static int mi0343_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- u8 data[2];
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[0];
- return 0;
- case V4L2_CID_GAIN:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
- data) < 0)
- return -EIO;
- break;
- case V4L2_CID_HFLIP:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1] & 0x20 ? 1 : 0;
- return 0;
- case V4L2_CID_VFLIP:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1] & 0x80 ? 1 : 0;
- return 0;
- case V4L2_CID_RED_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
- data) < 0)
- return -EIO;
- break;
- case V4L2_CID_BLUE_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
- data) < 0)
- return -EIO;
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
- data) < 0)
- return -EIO;
- break;
- default:
- return -EINVAL;
- }
-
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- case V4L2_CID_RED_BALANCE:
- case V4L2_CID_BLUE_BALANCE:
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = data[1] | (data[0] << 8);
- if (ctrl->value >= 0x10 && ctrl->value <= 0x3f)
- ctrl->value -= 0x10;
- else if (ctrl->value >= 0x60 && ctrl->value <= 0x7f)
- ctrl->value -= 0x60;
- else if (ctrl->value >= 0xe0 && ctrl->value <= 0xff)
- ctrl->value -= 0xe0;
- }
-
- return 0;
-}
-
-
-static int mi0343_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- u16 reg = 0;
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- case V4L2_CID_RED_BALANCE:
- case V4L2_CID_BLUE_BALANCE:
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (ctrl->value <= (0x3f-0x10))
- reg = 0x10 + ctrl->value;
- else if (ctrl->value <= ((0x3f-0x10) + (0x7f-0x60)))
- reg = 0x60 + (ctrl->value - (0x3f-0x10));
- else
- reg = 0xe0 + (ctrl->value - (0x3f-0x10) - (0x7f-0x60));
- break;
- }
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x09, ctrl->value, 0x00,
- 0, 0);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x35, reg >> 8, reg & 0xff,
- 0, 0);
- break;
- case V4L2_CID_HFLIP:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x20, ctrl->value ? 0x40:0x00,
- ctrl->value ? 0x20:0x00,
- 0, 0);
- break;
- case V4L2_CID_VFLIP:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x20, ctrl->value ? 0x80:0x00,
- ctrl->value ? 0x80:0x00,
- 0, 0);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2d, reg >> 8, reg & 0xff,
- 0, 0);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2c, reg >> 8, reg & 0xff,
- 0, 0);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2b, reg >> 8, reg & 0xff,
- 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2e, reg >> 8, reg & 0xff,
- 0, 0);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int mi0343_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 2;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int mi0343_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X) {
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x0a, 0x00, 0x03, 0, 0);
- err += sn9c102_write_reg(cam, 0x20, 0x19);
- } else {
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x0a, 0x00, 0x05, 0, 0);
- err += sn9c102_write_reg(cam, 0xa0, 0x19);
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor mi0343 = {
- .name = "MI-0343",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x5d,
- .init = &mi0343_init,
- .qctrl = {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = 0x0f,
- .step = 0x01,
- .default_value = 0x06,
- .flags = 0,
- },
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),/*0x6d*/
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_HFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "horizontal mirror",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- },
- {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical mirror",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = (0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0),
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = ((0x3f-0x10)+(0x7f-0x60)+(0xff-0xe0)),
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- },
- .get_ctrl = &mi0343_get_ctrl,
- .set_ctrl = &mi0343_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &mi0343_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &mi0343_set_pix_format
-};
-
-
-int sn9c102_probe_mi0343(struct sn9c102_device *cam)
-{
- u8 data[2];
-
- if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17}))
- return -EIO;
-
- if (sn9c102_i2c_try_raw_read(cam, &mi0343, mi0343.i2c_slave_id, 0x00,
- 2, data) < 0)
- return -EIO;
-
- if (data[1] != 0x42 || data[0] != 0xe3)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &mi0343);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mi0360.c b/drivers/staging/media/sn9c102/sn9c102_mi0360.c
deleted file mode 100644
index 5f21d1b43e32..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mi0360.c
+++ /dev/null
@@ -1,453 +0,0 @@
-/***************************************************************************
- * Plug-in for MI-0360 image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mi0360_init(struct sn9c102_device *cam)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C103:
- err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
- {0x0a, 0x14}, {0x40, 0x01},
- {0x20, 0x17}, {0x07, 0x18},
- {0xa0, 0x19}, {0x02, 0x1c},
- {0x03, 0x1d}, {0x0f, 0x1e},
- {0x0c, 0x1f}, {0x00, 0x20},
- {0x10, 0x21}, {0x20, 0x22},
- {0x30, 0x23}, {0x40, 0x24},
- {0x50, 0x25}, {0x60, 0x26},
- {0x70, 0x27}, {0x80, 0x28},
- {0x90, 0x29}, {0xa0, 0x2a},
- {0xb0, 0x2b}, {0xc0, 0x2c},
- {0xd0, 0x2d}, {0xe0, 0x2e},
- {0xf0, 0x2f}, {0xff, 0x30});
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
- {0x00, 0x03}, {0x1a, 0x04},
- {0x50, 0x05}, {0x20, 0x06},
- {0x10, 0x07}, {0x03, 0x10},
- {0x08, 0x14}, {0xa2, 0x17},
- {0x47, 0x18}, {0x00, 0x19},
- {0x1d, 0x1a}, {0x10, 0x1b},
- {0x02, 0x1c}, {0x03, 0x1d},
- {0x0f, 0x1e}, {0x0c, 0x1f},
- {0x00, 0x20}, {0x29, 0x21},
- {0x40, 0x22}, {0x54, 0x23},
- {0x66, 0x24}, {0x76, 0x25},
- {0x85, 0x26}, {0x94, 0x27},
- {0xa1, 0x28}, {0xae, 0x29},
- {0xbb, 0x2a}, {0xc7, 0x2b},
- {0xd3, 0x2c}, {0xde, 0x2d},
- {0xea, 0x2e}, {0xf4, 0x2f},
- {0xff, 0x30}, {0x00, 0x3F},
- {0xC7, 0x40}, {0x01, 0x41},
- {0x44, 0x42}, {0x00, 0x43},
- {0x44, 0x44}, {0x00, 0x45},
- {0x44, 0x46}, {0x00, 0x47},
- {0xC7, 0x48}, {0x01, 0x49},
- {0xC7, 0x4A}, {0x01, 0x4B},
- {0xC7, 0x4C}, {0x01, 0x4D},
- {0x44, 0x4E}, {0x00, 0x4F},
- {0x44, 0x50}, {0x00, 0x51},
- {0x44, 0x52}, {0x00, 0x53},
- {0xC7, 0x54}, {0x01, 0x55},
- {0xC7, 0x56}, {0x01, 0x57},
- {0xC7, 0x58}, {0x01, 0x59},
- {0x44, 0x5A}, {0x00, 0x5B},
- {0x44, 0x5C}, {0x00, 0x5D},
- {0x44, 0x5E}, {0x00, 0x5F},
- {0xC7, 0x60}, {0x01, 0x61},
- {0xC7, 0x62}, {0x01, 0x63},
- {0xC7, 0x64}, {0x01, 0x65},
- {0x44, 0x66}, {0x00, 0x67},
- {0x44, 0x68}, {0x00, 0x69},
- {0x44, 0x6A}, {0x00, 0x6B},
- {0xC7, 0x6C}, {0x01, 0x6D},
- {0xC7, 0x6E}, {0x01, 0x6F},
- {0xC7, 0x70}, {0x01, 0x71},
- {0x44, 0x72}, {0x00, 0x73},
- {0x44, 0x74}, {0x00, 0x75},
- {0x44, 0x76}, {0x00, 0x77},
- {0xC7, 0x78}, {0x01, 0x79},
- {0xC7, 0x7A}, {0x01, 0x7B},
- {0xC7, 0x7C}, {0x01, 0x7D},
- {0x44, 0x7E}, {0x00, 0x7F},
- {0x14, 0x84}, {0x00, 0x85},
- {0x27, 0x86}, {0x00, 0x87},
- {0x07, 0x88}, {0x00, 0x89},
- {0xEC, 0x8A}, {0x0f, 0x8B},
- {0xD8, 0x8C}, {0x0f, 0x8D},
- {0x3D, 0x8E}, {0x00, 0x8F},
- {0x3D, 0x90}, {0x00, 0x91},
- {0xCD, 0x92}, {0x0f, 0x93},
- {0xf7, 0x94}, {0x0f, 0x95},
- {0x0C, 0x96}, {0x00, 0x97},
- {0x00, 0x98}, {0x66, 0x99},
- {0x05, 0x9A}, {0x00, 0x9B},
- {0x04, 0x9C}, {0x00, 0x9D},
- {0x08, 0x9E}, {0x00, 0x9F},
- {0x2D, 0xC0}, {0x2D, 0xC1},
- {0x3A, 0xC2}, {0x05, 0xC3},
- {0x04, 0xC4}, {0x3F, 0xC5},
- {0x00, 0xC6}, {0x00, 0xC7},
- {0x50, 0xC8}, {0x3C, 0xC9},
- {0x28, 0xCA}, {0xD8, 0xCB},
- {0x14, 0xCC}, {0xEC, 0xCD},
- {0x32, 0xCE}, {0xDD, 0xCF},
- {0x32, 0xD0}, {0xDD, 0xD1},
- {0x6A, 0xD2}, {0x50, 0xD3},
- {0x00, 0xD4}, {0x00, 0xD5},
- {0x00, 0xD6});
- break;
- default:
- break;
- }
-
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
- 0x01, 0xe1, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
- 0x02, 0x81, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
- 0x00, 0x17, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
- 0x00, 0x11, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x62,
- 0x04, 0x9a, 0, 0);
-
- return err;
-}
-
-
-static int mi0360_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- u8 data[2];
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x09, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[0];
- return 0;
- case V4L2_CID_GAIN:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x35, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1];
- return 0;
- case V4L2_CID_RED_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2c, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1];
- return 0;
- case V4L2_CID_BLUE_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2d, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1];
- return 0;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x2e, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1];
- return 0;
- case V4L2_CID_HFLIP:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1] & 0x20 ? 1 : 0;
- return 0;
- case V4L2_CID_VFLIP:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1] & 0x80 ? 1 : 0;
- return 0;
- default:
- return -EINVAL;
- }
-
- return 0;
-}
-
-
-static int mi0360_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x09, ctrl->value, 0x00,
- 0, 0);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x35, 0x03, ctrl->value,
- 0, 0);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2c, 0x03, ctrl->value,
- 0, 0);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2d, 0x03, ctrl->value,
- 0, 0);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2b, 0x03, ctrl->value,
- 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x2e, 0x03, ctrl->value,
- 0, 0);
- break;
- case V4L2_CID_HFLIP:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x20, ctrl->value ? 0x40:0x00,
- ctrl->value ? 0x20:0x00,
- 0, 0);
- break;
- case V4L2_CID_VFLIP:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x20, ctrl->value ? 0x80:0x00,
- ctrl->value ? 0x80:0x00,
- 0, 0);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int mi0360_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C103:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 0;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
- break;
- default:
- break;
- }
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int mi0360_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x0a, 0x00, 0x05, 0, 0);
- err += sn9c102_write_reg(cam, 0x60, 0x19);
- if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
- sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
- err += sn9c102_write_reg(cam, 0xa6, 0x17);
- } else {
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x0a, 0x00, 0x02, 0, 0);
- err += sn9c102_write_reg(cam, 0x20, 0x19);
- if (sn9c102_get_bridge(cam) == BRIDGE_SN9C105 ||
- sn9c102_get_bridge(cam) == BRIDGE_SN9C120)
- err += sn9c102_write_reg(cam, 0xa2, 0x17);
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor mi0360 = {
- .name = "MI-0360",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C103 | BRIDGE_SN9C105 | BRIDGE_SN9C120,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x5d,
- .init = &mi0360_init,
- .qctrl = {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = 0x0f,
- .step = 0x01,
- .default_value = 0x05,
- .flags = 0,
- },
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x25,
- .flags = 0,
- },
- {
- .id = V4L2_CID_HFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "horizontal mirror",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- },
- {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical mirror",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x0f,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x32,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x25,
- .flags = 0,
- },
- },
- .get_ctrl = &mi0360_get_ctrl,
- .set_ctrl = &mi0360_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &mi0360_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &mi0360_set_pix_format
-};
-
-
-int sn9c102_probe_mi0360(struct sn9c102_device *cam)
-{
-
- u8 data[2];
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C103:
- if (sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17}))
- return -EIO;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
- {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17}))
- return -EIO;
- break;
- default:
- break;
- }
-
- if (sn9c102_i2c_try_raw_read(cam, &mi0360, mi0360.i2c_slave_id, 0x00,
- 2, data) < 0)
- return -EIO;
-
- if (data[0] != 0x82 || data[1] != 0x43)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &mi0360);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c b/drivers/staging/media/sn9c102/sn9c102_mt9v111.c
deleted file mode 100644
index 95986eb492e4..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_mt9v111.c
+++ /dev/null
@@ -1,260 +0,0 @@
-/***************************************************************************
- * Plug-in for MT9V111 image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int mt9v111_init(struct sn9c102_device *cam)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- err = sn9c102_write_const_regs(cam, {0x44, 0x01}, {0x40, 0x02},
- {0x00, 0x03}, {0x1a, 0x04},
- {0x1f, 0x05}, {0x20, 0x06},
- {0x1f, 0x07}, {0x81, 0x08},
- {0x5c, 0x09}, {0x00, 0x0a},
- {0x00, 0x0b}, {0x00, 0x0c},
- {0x00, 0x0d}, {0x00, 0x0e},
- {0x00, 0x0f}, {0x03, 0x10},
- {0x00, 0x11}, {0x00, 0x12},
- {0x02, 0x13}, {0x14, 0x14},
- {0x28, 0x15}, {0x1e, 0x16},
- {0xe2, 0x17}, {0x06, 0x18},
- {0x00, 0x19}, {0x00, 0x1a},
- {0x00, 0x1b}, {0x08, 0x20},
- {0x39, 0x21}, {0x51, 0x22},
- {0x63, 0x23}, {0x73, 0x24},
- {0x82, 0x25}, {0x8f, 0x26},
- {0x9b, 0x27}, {0xa7, 0x28},
- {0xb1, 0x29}, {0xbc, 0x2a},
- {0xc6, 0x2b}, {0xcf, 0x2c},
- {0xd8, 0x2d}, {0xe1, 0x2e},
- {0xea, 0x2f}, {0xf2, 0x30},
- {0x13, 0x84}, {0x00, 0x85},
- {0x25, 0x86}, {0x00, 0x87},
- {0x07, 0x88}, {0x00, 0x89},
- {0xee, 0x8a}, {0x0f, 0x8b},
- {0xe5, 0x8c}, {0x0f, 0x8d},
- {0x2e, 0x8e}, {0x00, 0x8f},
- {0x30, 0x90}, {0x00, 0x91},
- {0xd4, 0x92}, {0x0f, 0x93},
- {0xfc, 0x94}, {0x0f, 0x95},
- {0x14, 0x96}, {0x00, 0x97},
- {0x00, 0x98}, {0x60, 0x99},
- {0x07, 0x9a}, {0x40, 0x9b},
- {0x20, 0x9c}, {0x00, 0x9d},
- {0x00, 0x9e}, {0x00, 0x9f},
- {0x2d, 0xc0}, {0x2d, 0xc1},
- {0x3a, 0xc2}, {0x05, 0xc3},
- {0x04, 0xc4}, {0x3f, 0xc5},
- {0x00, 0xc6}, {0x00, 0xc7},
- {0x50, 0xc8}, {0x3c, 0xc9},
- {0x28, 0xca}, {0xd8, 0xcb},
- {0x14, 0xcc}, {0xec, 0xcd},
- {0x32, 0xce}, {0xdd, 0xcf},
- {0x2d, 0xd0}, {0xdd, 0xd1},
- {0x6a, 0xd2}, {0x50, 0xd3},
- {0x60, 0xd4}, {0x00, 0xd5},
- {0x00, 0xd6});
-
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
- 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x01, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0d,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
- 0x04, 0x80, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
- 0x00, 0x04, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x08,
- 0x00, 0x08, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x02,
- 0x00, 0x16, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x03,
- 0x01, 0xe7, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x04,
- 0x02, 0x87, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x06,
- 0x00, 0x40, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x05,
- 0x00, 0x09, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x07,
- 0x30, 0x02, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x0c,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x12,
- 0x00, 0xb0, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x13,
- 0x00, 0x7c, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x1e,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x20,
- 0x00, 0x00, 0, 0);
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id, 0x01,
- 0x00, 0x04, 0, 0);
-
- return err;
-}
-
-static int mt9v111_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- u8 data[2];
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_VFLIP:
- if (sn9c102_i2c_try_raw_read(cam, s, s->i2c_slave_id, 0x20, 2,
- data) < 0)
- return -EIO;
- ctrl->value = data[1] & 0x80 ? 1 : 0;
- return 0;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-static int mt9v111_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_VFLIP:
- err += sn9c102_i2c_try_raw_write(cam, s, 4, s->i2c_slave_id,
- 0x20,
- ctrl->value ? 0x80 : 0x00,
- ctrl->value ? 0x80 : 0x00, 0,
- 0);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-static int mt9v111_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 v_start = (u8) (rect->top - s->cropcap.bounds.top) + 2;
-
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-static int mt9v111_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
- err += sn9c102_write_reg(cam, 0xb4, 0x17);
- } else {
- err += sn9c102_write_reg(cam, 0xe2, 0x17);
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor mt9v111 = {
- .name = "MT9V111",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x5c,
- .init = &mt9v111_init,
- .qctrl = {
- {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical mirror",
- .minimum = 0,
- .maximum = 1,
- .step = 1,
- .default_value = 0,
- .flags = 0,
- },
- },
- .get_ctrl = &mt9v111_get_ctrl,
- .set_ctrl = &mt9v111_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &mt9v111_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &mt9v111_set_pix_format
-};
-
-
-int sn9c102_probe_mt9v111(struct sn9c102_device *cam)
-{
- u8 data[2];
- int err = 0;
-
- err += sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
- {0x29, 0x01}, {0x42, 0x17},
- {0x62, 0x17}, {0x08, 0x01});
- err += sn9c102_i2c_try_raw_write(cam, &mt9v111, 4,
- mt9v111.i2c_slave_id, 0x01, 0x00,
- 0x04, 0, 0);
- if (err || sn9c102_i2c_try_raw_read(cam, &mt9v111,
- mt9v111.i2c_slave_id, 0x36, 2,
- data) < 0)
- return -EIO;
-
- if (data[0] != 0x82 || data[1] != 0x3a)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &mt9v111);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7630.c b/drivers/staging/media/sn9c102/sn9c102_ov7630.c
deleted file mode 100644
index 9ec304dc4705..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_ov7630.c
+++ /dev/null
@@ -1,634 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7630 image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2006-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7630_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- err = sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17},
- {0x0f, 0x18}, {0x50, 0x19});
-
- err += sn9c102_i2c_write(cam, 0x12, 0x8d);
- err += sn9c102_i2c_write(cam, 0x12, 0x0d);
- err += sn9c102_i2c_write(cam, 0x11, 0x00);
- err += sn9c102_i2c_write(cam, 0x15, 0x35);
- err += sn9c102_i2c_write(cam, 0x16, 0x03);
- err += sn9c102_i2c_write(cam, 0x17, 0x1c);
- err += sn9c102_i2c_write(cam, 0x18, 0xbd);
- err += sn9c102_i2c_write(cam, 0x19, 0x06);
- err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
- err += sn9c102_i2c_write(cam, 0x1b, 0x04);
- err += sn9c102_i2c_write(cam, 0x20, 0x44);
- err += sn9c102_i2c_write(cam, 0x23, 0xee);
- err += sn9c102_i2c_write(cam, 0x26, 0xa0);
- err += sn9c102_i2c_write(cam, 0x27, 0x9a);
- err += sn9c102_i2c_write(cam, 0x28, 0x20);
- err += sn9c102_i2c_write(cam, 0x29, 0x30);
- err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
- err += sn9c102_i2c_write(cam, 0x30, 0x24);
- err += sn9c102_i2c_write(cam, 0x32, 0x86);
- err += sn9c102_i2c_write(cam, 0x60, 0xa9);
- err += sn9c102_i2c_write(cam, 0x61, 0x42);
- err += sn9c102_i2c_write(cam, 0x65, 0x00);
- err += sn9c102_i2c_write(cam, 0x69, 0x38);
- err += sn9c102_i2c_write(cam, 0x6f, 0x88);
- err += sn9c102_i2c_write(cam, 0x70, 0x0b);
- err += sn9c102_i2c_write(cam, 0x71, 0x00);
- err += sn9c102_i2c_write(cam, 0x74, 0x21);
- err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
- break;
- case BRIDGE_SN9C103:
- err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
- {0x1a, 0x04}, {0x20, 0x05},
- {0x20, 0x06}, {0x20, 0x07},
- {0x03, 0x10}, {0x0a, 0x14},
- {0x60, 0x17}, {0x0f, 0x18},
- {0x50, 0x19}, {0x1d, 0x1a},
- {0x10, 0x1b}, {0x02, 0x1c},
- {0x03, 0x1d}, {0x0f, 0x1e},
- {0x0c, 0x1f}, {0x00, 0x20},
- {0x10, 0x21}, {0x20, 0x22},
- {0x30, 0x23}, {0x40, 0x24},
- {0x50, 0x25}, {0x60, 0x26},
- {0x70, 0x27}, {0x80, 0x28},
- {0x90, 0x29}, {0xa0, 0x2a},
- {0xb0, 0x2b}, {0xc0, 0x2c},
- {0xd0, 0x2d}, {0xe0, 0x2e},
- {0xf0, 0x2f}, {0xff, 0x30});
-
- err += sn9c102_i2c_write(cam, 0x12, 0x8d);
- err += sn9c102_i2c_write(cam, 0x12, 0x0d);
- err += sn9c102_i2c_write(cam, 0x15, 0x34);
- err += sn9c102_i2c_write(cam, 0x11, 0x01);
- err += sn9c102_i2c_write(cam, 0x1b, 0x04);
- err += sn9c102_i2c_write(cam, 0x20, 0x44);
- err += sn9c102_i2c_write(cam, 0x23, 0xee);
- err += sn9c102_i2c_write(cam, 0x26, 0xa0);
- err += sn9c102_i2c_write(cam, 0x27, 0x9a);
- err += sn9c102_i2c_write(cam, 0x28, 0x20);
- err += sn9c102_i2c_write(cam, 0x29, 0x30);
- err += sn9c102_i2c_write(cam, 0x2f, 0x3d);
- err += sn9c102_i2c_write(cam, 0x30, 0x24);
- err += sn9c102_i2c_write(cam, 0x32, 0x86);
- err += sn9c102_i2c_write(cam, 0x60, 0xa9);
- err += sn9c102_i2c_write(cam, 0x61, 0x42);
- err += sn9c102_i2c_write(cam, 0x65, 0x00);
- err += sn9c102_i2c_write(cam, 0x69, 0x38);
- err += sn9c102_i2c_write(cam, 0x6f, 0x88);
- err += sn9c102_i2c_write(cam, 0x70, 0x0b);
- err += sn9c102_i2c_write(cam, 0x71, 0x00);
- err += sn9c102_i2c_write(cam, 0x74, 0x21);
- err += sn9c102_i2c_write(cam, 0x7d, 0xf7);
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
- {0x1a, 0x04}, {0x03, 0x10},
- {0x0a, 0x14}, {0xe2, 0x17},
- {0x0b, 0x18}, {0x00, 0x19},
- {0x1d, 0x1a}, {0x10, 0x1b},
- {0x02, 0x1c}, {0x03, 0x1d},
- {0x0f, 0x1e}, {0x0c, 0x1f},
- {0x00, 0x20}, {0x24, 0x21},
- {0x3b, 0x22}, {0x47, 0x23},
- {0x60, 0x24}, {0x71, 0x25},
- {0x80, 0x26}, {0x8f, 0x27},
- {0x9d, 0x28}, {0xaa, 0x29},
- {0xb8, 0x2a}, {0xc4, 0x2b},
- {0xd1, 0x2c}, {0xdd, 0x2d},
- {0xe8, 0x2e}, {0xf4, 0x2f},
- {0xff, 0x30}, {0x00, 0x3f},
- {0xc7, 0x40}, {0x01, 0x41},
- {0x44, 0x42}, {0x00, 0x43},
- {0x44, 0x44}, {0x00, 0x45},
- {0x44, 0x46}, {0x00, 0x47},
- {0xc7, 0x48}, {0x01, 0x49},
- {0xc7, 0x4a}, {0x01, 0x4b},
- {0xc7, 0x4c}, {0x01, 0x4d},
- {0x44, 0x4e}, {0x00, 0x4f},
- {0x44, 0x50}, {0x00, 0x51},
- {0x44, 0x52}, {0x00, 0x53},
- {0xc7, 0x54}, {0x01, 0x55},
- {0xc7, 0x56}, {0x01, 0x57},
- {0xc7, 0x58}, {0x01, 0x59},
- {0x44, 0x5a}, {0x00, 0x5b},
- {0x44, 0x5c}, {0x00, 0x5d},
- {0x44, 0x5e}, {0x00, 0x5f},
- {0xc7, 0x60}, {0x01, 0x61},
- {0xc7, 0x62}, {0x01, 0x63},
- {0xc7, 0x64}, {0x01, 0x65},
- {0x44, 0x66}, {0x00, 0x67},
- {0x44, 0x68}, {0x00, 0x69},
- {0x44, 0x6a}, {0x00, 0x6b},
- {0xc7, 0x6c}, {0x01, 0x6d},
- {0xc7, 0x6e}, {0x01, 0x6f},
- {0xc7, 0x70}, {0x01, 0x71},
- {0x44, 0x72}, {0x00, 0x73},
- {0x44, 0x74}, {0x00, 0x75},
- {0x44, 0x76}, {0x00, 0x77},
- {0xc7, 0x78}, {0x01, 0x79},
- {0xc7, 0x7a}, {0x01, 0x7b},
- {0xc7, 0x7c}, {0x01, 0x7d},
- {0x44, 0x7e}, {0x00, 0x7f},
- {0x17, 0x84}, {0x00, 0x85},
- {0x2e, 0x86}, {0x00, 0x87},
- {0x09, 0x88}, {0x00, 0x89},
- {0xe8, 0x8a}, {0x0f, 0x8b},
- {0xda, 0x8c}, {0x0f, 0x8d},
- {0x40, 0x8e}, {0x00, 0x8f},
- {0x37, 0x90}, {0x00, 0x91},
- {0xcf, 0x92}, {0x0f, 0x93},
- {0xfa, 0x94}, {0x0f, 0x95},
- {0x00, 0x96}, {0x00, 0x97},
- {0x00, 0x98}, {0x66, 0x99},
- {0x00, 0x9a}, {0x40, 0x9b},
- {0x20, 0x9c}, {0x00, 0x9d},
- {0x00, 0x9e}, {0x00, 0x9f},
- {0x2d, 0xc0}, {0x2d, 0xc1},
- {0x3a, 0xc2}, {0x00, 0xc3},
- {0x04, 0xc4}, {0x3f, 0xc5},
- {0x00, 0xc6}, {0x00, 0xc7},
- {0x50, 0xc8}, {0x3c, 0xc9},
- {0x28, 0xca}, {0xd8, 0xcb},
- {0x14, 0xcc}, {0xec, 0xcd},
- {0x32, 0xce}, {0xdd, 0xcf},
- {0x32, 0xd0}, {0xdd, 0xd1},
- {0x6a, 0xd2}, {0x50, 0xd3},
- {0x60, 0xd4}, {0x00, 0xd5},
- {0x00, 0xd6});
-
- err += sn9c102_i2c_write(cam, 0x12, 0x80);
- err += sn9c102_i2c_write(cam, 0x12, 0x48);
- err += sn9c102_i2c_write(cam, 0x01, 0x80);
- err += sn9c102_i2c_write(cam, 0x02, 0x80);
- err += sn9c102_i2c_write(cam, 0x03, 0x80);
- err += sn9c102_i2c_write(cam, 0x04, 0x10);
- err += sn9c102_i2c_write(cam, 0x05, 0x20);
- err += sn9c102_i2c_write(cam, 0x06, 0x80);
- err += sn9c102_i2c_write(cam, 0x11, 0x00);
- err += sn9c102_i2c_write(cam, 0x0c, 0x20);
- err += sn9c102_i2c_write(cam, 0x0d, 0x20);
- err += sn9c102_i2c_write(cam, 0x15, 0x80);
- err += sn9c102_i2c_write(cam, 0x16, 0x03);
- err += sn9c102_i2c_write(cam, 0x17, 0x1b);
- err += sn9c102_i2c_write(cam, 0x18, 0xbd);
- err += sn9c102_i2c_write(cam, 0x19, 0x05);
- err += sn9c102_i2c_write(cam, 0x1a, 0xf6);
- err += sn9c102_i2c_write(cam, 0x1b, 0x04);
- err += sn9c102_i2c_write(cam, 0x21, 0x1b);
- err += sn9c102_i2c_write(cam, 0x22, 0x00);
- err += sn9c102_i2c_write(cam, 0x23, 0xde);
- err += sn9c102_i2c_write(cam, 0x24, 0x10);
- err += sn9c102_i2c_write(cam, 0x25, 0x8a);
- err += sn9c102_i2c_write(cam, 0x26, 0xa0);
- err += sn9c102_i2c_write(cam, 0x27, 0xca);
- err += sn9c102_i2c_write(cam, 0x28, 0xa2);
- err += sn9c102_i2c_write(cam, 0x29, 0x74);
- err += sn9c102_i2c_write(cam, 0x2a, 0x88);
- err += sn9c102_i2c_write(cam, 0x2b, 0x34);
- err += sn9c102_i2c_write(cam, 0x2c, 0x88);
- err += sn9c102_i2c_write(cam, 0x2e, 0x00);
- err += sn9c102_i2c_write(cam, 0x2f, 0x00);
- err += sn9c102_i2c_write(cam, 0x30, 0x00);
- err += sn9c102_i2c_write(cam, 0x32, 0xc2);
- err += sn9c102_i2c_write(cam, 0x33, 0x08);
- err += sn9c102_i2c_write(cam, 0x4c, 0x40);
- err += sn9c102_i2c_write(cam, 0x4d, 0xf3);
- err += sn9c102_i2c_write(cam, 0x60, 0x05);
- err += sn9c102_i2c_write(cam, 0x61, 0x40);
- err += sn9c102_i2c_write(cam, 0x62, 0x12);
- err += sn9c102_i2c_write(cam, 0x63, 0x57);
- err += sn9c102_i2c_write(cam, 0x64, 0x73);
- err += sn9c102_i2c_write(cam, 0x65, 0x00);
- err += sn9c102_i2c_write(cam, 0x66, 0x55);
- err += sn9c102_i2c_write(cam, 0x67, 0x01);
- err += sn9c102_i2c_write(cam, 0x68, 0xac);
- err += sn9c102_i2c_write(cam, 0x69, 0x38);
- err += sn9c102_i2c_write(cam, 0x6f, 0x1f);
- err += sn9c102_i2c_write(cam, 0x70, 0x01);
- err += sn9c102_i2c_write(cam, 0x71, 0x00);
- err += sn9c102_i2c_write(cam, 0x72, 0x10);
- err += sn9c102_i2c_write(cam, 0x73, 0x50);
- err += sn9c102_i2c_write(cam, 0x74, 0x20);
- err += sn9c102_i2c_write(cam, 0x76, 0x01);
- err += sn9c102_i2c_write(cam, 0x77, 0xf3);
- err += sn9c102_i2c_write(cam, 0x78, 0x90);
- err += sn9c102_i2c_write(cam, 0x79, 0x98);
- err += sn9c102_i2c_write(cam, 0x7a, 0x98);
- err += sn9c102_i2c_write(cam, 0x7b, 0x00);
- err += sn9c102_i2c_write(cam, 0x7c, 0x38);
- err += sn9c102_i2c_write(cam, 0x7d, 0xff);
- break;
- default:
- break;
- }
-
- return err;
-}
-
-
-static int ov7630_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- ctrl->value = sn9c102_i2c_read(cam, 0x10);
- if (ctrl->value < 0)
- return -EIO;
- break;
- case V4L2_CID_RED_BALANCE:
- if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
- ctrl->value = sn9c102_pread_reg(cam, 0x05);
- else
- ctrl->value = sn9c102_pread_reg(cam, 0x07);
- break;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_pread_reg(cam, 0x06);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
- ctrl->value = sn9c102_pread_reg(cam, 0x07);
- else
- ctrl->value = sn9c102_pread_reg(cam, 0x05);
- break;
- break;
- case V4L2_CID_GAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x00);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x3f;
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x0c);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x3f;
- break;
- case V4L2_CID_WHITENESS:
- ctrl->value = sn9c102_i2c_read(cam, 0x0d);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x3f;
- break;
- case V4L2_CID_AUTOGAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x13);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x01;
- break;
- case V4L2_CID_VFLIP:
- ctrl->value = sn9c102_i2c_read(cam, 0x75);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x80) ? 1 : 0;
- break;
- case SN9C102_V4L2_CID_GAMMA:
- ctrl->value = sn9c102_i2c_read(cam, 0x14);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
- break;
- case SN9C102_V4L2_CID_BAND_FILTER:
- ctrl->value = sn9c102_i2c_read(cam, 0x2d);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x02) ? 1 : 0;
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- enum sn9c102_bridge bridge = sn9c102_get_bridge(cam);
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
- break;
- case V4L2_CID_RED_BALANCE:
- if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
- err += sn9c102_write_reg(cam, ctrl->value, 0x05);
- else
- err += sn9c102_write_reg(cam, ctrl->value, 0x07);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x06);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- if (bridge == BRIDGE_SN9C105 || bridge == BRIDGE_SN9C120)
- err += sn9c102_write_reg(cam, ctrl->value, 0x07);
- else
- err += sn9c102_write_reg(cam, ctrl->value, 0x05);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x00, ctrl->value);
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
- break;
- case V4L2_CID_WHITENESS:
- err += sn9c102_i2c_write(cam, 0x0d, ctrl->value);
- break;
- case V4L2_CID_AUTOGAIN:
- err += sn9c102_i2c_write(cam, 0x13, ctrl->value |
- (ctrl->value << 1));
- break;
- case V4L2_CID_VFLIP:
- err += sn9c102_i2c_write(cam, 0x75, 0x0e | (ctrl->value << 7));
- break;
- case SN9C102_V4L2_CID_GAMMA:
- err += sn9c102_i2c_write(cam, 0x14, ctrl->value << 2);
- break;
- case SN9C102_V4L2_CID_BAND_FILTER:
- err += sn9c102_i2c_write(cam, 0x2d, ctrl->value << 2);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int ov7630_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = 0, v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1;
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
- break;
- default:
- break;
- }
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int ov7630_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- case BRIDGE_SN9C103:
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8)
- err += sn9c102_write_reg(cam, 0x50, 0x19);
- else
- err += sn9c102_write_reg(cam, 0x20, 0x19);
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- if (pix->pixelformat == V4L2_PIX_FMT_SBGGR8) {
- err += sn9c102_write_reg(cam, 0xe5, 0x17);
- err += sn9c102_i2c_write(cam, 0x11, 0x04);
- } else {
- err += sn9c102_write_reg(cam, 0xe2, 0x17);
- err += sn9c102_i2c_write(cam, 0x11, 0x02);
- }
- break;
- default:
- break;
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor ov7630 = {
- .name = "OV7630",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103 |
- BRIDGE_SN9C105 | BRIDGE_SN9C120,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x21,
- .init = &ov7630_init,
- .qctrl = {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x14,
- .flags = 0,
- },
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = 0x60,
- .flags = 0,
- },
- {
- .id = V4L2_CID_WHITENESS,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "white balance background: red",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = V4L2_CID_DO_WHITE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "white balance background: blue",
- .minimum = 0x00,
- .maximum = 0x3f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = V4L2_CID_AUTOGAIN,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "auto adjust",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_VFLIP,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "vertical flip",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x01,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x20,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_BAND_FILTER,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "band filter",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GAMMA,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "rgb gamma",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- },
- .get_ctrl = &ov7630_get_ctrl,
- .set_ctrl = &ov7630_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &ov7630_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SN9C10X,
- .priv = 8,
- },
- .set_pix_format = &ov7630_set_pix_format
-};
-
-
-int sn9c102_probe_ov7630(struct sn9c102_device *cam)
-{
- int pid, ver, err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17});
- break;
- case BRIDGE_SN9C103: /* do _not_ change anything! */
- err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x42, 0x01},
- {0x28, 0x17}, {0x44, 0x02});
- pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
- if (err || pid < 0) /* try a different initialization */
- err += sn9c102_write_const_regs(cam, {0x01, 0x01},
- {0x00, 0x01});
- break;
- case BRIDGE_SN9C105:
- case BRIDGE_SN9C120:
- err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
- {0x29, 0x01}, {0x74, 0x02},
- {0x0e, 0x01}, {0x44, 0x01});
- break;
- default:
- break;
- }
-
- pid = sn9c102_i2c_try_read(cam, &ov7630, 0x0a);
- ver = sn9c102_i2c_try_read(cam, &ov7630, 0x0b);
- if (err || pid < 0 || ver < 0)
- return -EIO;
- if (pid != 0x76 || ver != 0x31)
- return -ENODEV;
- sn9c102_attach_sensor(cam, &ov7630);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_ov7660.c b/drivers/staging/media/sn9c102/sn9c102_ov7660.c
deleted file mode 100644
index ac07805d122e..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_ov7660.c
+++ /dev/null
@@ -1,546 +0,0 @@
-/***************************************************************************
- * Plug-in for OV7660 image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int ov7660_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- err = sn9c102_write_const_regs(cam, {0x40, 0x02}, {0x00, 0x03},
- {0x1a, 0x04}, {0x03, 0x10},
- {0x08, 0x14}, {0x20, 0x17},
- {0x8b, 0x18}, {0x00, 0x19},
- {0x1d, 0x1a}, {0x10, 0x1b},
- {0x02, 0x1c}, {0x03, 0x1d},
- {0x0f, 0x1e}, {0x0c, 0x1f},
- {0x00, 0x20}, {0x29, 0x21},
- {0x40, 0x22}, {0x54, 0x23},
- {0x66, 0x24}, {0x76, 0x25},
- {0x85, 0x26}, {0x94, 0x27},
- {0xa1, 0x28}, {0xae, 0x29},
- {0xbb, 0x2a}, {0xc7, 0x2b},
- {0xd3, 0x2c}, {0xde, 0x2d},
- {0xea, 0x2e}, {0xf4, 0x2f},
- {0xff, 0x30}, {0x00, 0x3f},
- {0xc7, 0x40}, {0x01, 0x41},
- {0x44, 0x42}, {0x00, 0x43},
- {0x44, 0x44}, {0x00, 0x45},
- {0x44, 0x46}, {0x00, 0x47},
- {0xc7, 0x48}, {0x01, 0x49},
- {0xc7, 0x4a}, {0x01, 0x4b},
- {0xc7, 0x4c}, {0x01, 0x4d},
- {0x44, 0x4e}, {0x00, 0x4f},
- {0x44, 0x50}, {0x00, 0x51},
- {0x44, 0x52}, {0x00, 0x53},
- {0xc7, 0x54}, {0x01, 0x55},
- {0xc7, 0x56}, {0x01, 0x57},
- {0xc7, 0x58}, {0x01, 0x59},
- {0x44, 0x5a}, {0x00, 0x5b},
- {0x44, 0x5c}, {0x00, 0x5d},
- {0x44, 0x5e}, {0x00, 0x5f},
- {0xc7, 0x60}, {0x01, 0x61},
- {0xc7, 0x62}, {0x01, 0x63},
- {0xc7, 0x64}, {0x01, 0x65},
- {0x44, 0x66}, {0x00, 0x67},
- {0x44, 0x68}, {0x00, 0x69},
- {0x44, 0x6a}, {0x00, 0x6b},
- {0xc7, 0x6c}, {0x01, 0x6d},
- {0xc7, 0x6e}, {0x01, 0x6f},
- {0xc7, 0x70}, {0x01, 0x71},
- {0x44, 0x72}, {0x00, 0x73},
- {0x44, 0x74}, {0x00, 0x75},
- {0x44, 0x76}, {0x00, 0x77},
- {0xc7, 0x78}, {0x01, 0x79},
- {0xc7, 0x7a}, {0x01, 0x7b},
- {0xc7, 0x7c}, {0x01, 0x7d},
- {0x44, 0x7e}, {0x00, 0x7f},
- {0x14, 0x84}, {0x00, 0x85},
- {0x27, 0x86}, {0x00, 0x87},
- {0x07, 0x88}, {0x00, 0x89},
- {0xec, 0x8a}, {0x0f, 0x8b},
- {0xd8, 0x8c}, {0x0f, 0x8d},
- {0x3d, 0x8e}, {0x00, 0x8f},
- {0x3d, 0x90}, {0x00, 0x91},
- {0xcd, 0x92}, {0x0f, 0x93},
- {0xf7, 0x94}, {0x0f, 0x95},
- {0x0c, 0x96}, {0x00, 0x97},
- {0x00, 0x98}, {0x66, 0x99},
- {0x05, 0x9a}, {0x00, 0x9b},
- {0x04, 0x9c}, {0x00, 0x9d},
- {0x08, 0x9e}, {0x00, 0x9f},
- {0x2d, 0xc0}, {0x2d, 0xc1},
- {0x3a, 0xc2}, {0x05, 0xc3},
- {0x04, 0xc4}, {0x3f, 0xc5},
- {0x00, 0xc6}, {0x00, 0xc7},
- {0x50, 0xc8}, {0x3C, 0xc9},
- {0x28, 0xca}, {0xd8, 0xcb},
- {0x14, 0xcc}, {0xec, 0xcd},
- {0x32, 0xce}, {0xdd, 0xcf},
- {0x32, 0xd0}, {0xdd, 0xd1},
- {0x6a, 0xd2}, {0x50, 0xd3},
- {0x00, 0xd4}, {0x00, 0xd5},
- {0x00, 0xd6});
-
- err += sn9c102_i2c_write(cam, 0x12, 0x80);
- err += sn9c102_i2c_write(cam, 0x11, 0x09);
- err += sn9c102_i2c_write(cam, 0x00, 0x0A);
- err += sn9c102_i2c_write(cam, 0x01, 0x80);
- err += sn9c102_i2c_write(cam, 0x02, 0x80);
- err += sn9c102_i2c_write(cam, 0x03, 0x00);
- err += sn9c102_i2c_write(cam, 0x04, 0x00);
- err += sn9c102_i2c_write(cam, 0x05, 0x08);
- err += sn9c102_i2c_write(cam, 0x06, 0x0B);
- err += sn9c102_i2c_write(cam, 0x07, 0x00);
- err += sn9c102_i2c_write(cam, 0x08, 0x1C);
- err += sn9c102_i2c_write(cam, 0x09, 0x01);
- err += sn9c102_i2c_write(cam, 0x0A, 0x76);
- err += sn9c102_i2c_write(cam, 0x0B, 0x60);
- err += sn9c102_i2c_write(cam, 0x0C, 0x00);
- err += sn9c102_i2c_write(cam, 0x0D, 0x08);
- err += sn9c102_i2c_write(cam, 0x0E, 0x04);
- err += sn9c102_i2c_write(cam, 0x0F, 0x6F);
- err += sn9c102_i2c_write(cam, 0x10, 0x20);
- err += sn9c102_i2c_write(cam, 0x11, 0x03);
- err += sn9c102_i2c_write(cam, 0x12, 0x05);
- err += sn9c102_i2c_write(cam, 0x13, 0xC7);
- err += sn9c102_i2c_write(cam, 0x14, 0x2C);
- err += sn9c102_i2c_write(cam, 0x15, 0x00);
- err += sn9c102_i2c_write(cam, 0x16, 0x02);
- err += sn9c102_i2c_write(cam, 0x17, 0x10);
- err += sn9c102_i2c_write(cam, 0x18, 0x60);
- err += sn9c102_i2c_write(cam, 0x19, 0x02);
- err += sn9c102_i2c_write(cam, 0x1A, 0x7B);
- err += sn9c102_i2c_write(cam, 0x1B, 0x02);
- err += sn9c102_i2c_write(cam, 0x1C, 0x7F);
- err += sn9c102_i2c_write(cam, 0x1D, 0xA2);
- err += sn9c102_i2c_write(cam, 0x1E, 0x01);
- err += sn9c102_i2c_write(cam, 0x1F, 0x0E);
- err += sn9c102_i2c_write(cam, 0x20, 0x05);
- err += sn9c102_i2c_write(cam, 0x21, 0x05);
- err += sn9c102_i2c_write(cam, 0x22, 0x05);
- err += sn9c102_i2c_write(cam, 0x23, 0x05);
- err += sn9c102_i2c_write(cam, 0x24, 0x68);
- err += sn9c102_i2c_write(cam, 0x25, 0x58);
- err += sn9c102_i2c_write(cam, 0x26, 0xD4);
- err += sn9c102_i2c_write(cam, 0x27, 0x80);
- err += sn9c102_i2c_write(cam, 0x28, 0x80);
- err += sn9c102_i2c_write(cam, 0x29, 0x30);
- err += sn9c102_i2c_write(cam, 0x2A, 0x00);
- err += sn9c102_i2c_write(cam, 0x2B, 0x00);
- err += sn9c102_i2c_write(cam, 0x2C, 0x80);
- err += sn9c102_i2c_write(cam, 0x2D, 0x00);
- err += sn9c102_i2c_write(cam, 0x2E, 0x00);
- err += sn9c102_i2c_write(cam, 0x2F, 0x0E);
- err += sn9c102_i2c_write(cam, 0x30, 0x08);
- err += sn9c102_i2c_write(cam, 0x31, 0x30);
- err += sn9c102_i2c_write(cam, 0x32, 0xB4);
- err += sn9c102_i2c_write(cam, 0x33, 0x00);
- err += sn9c102_i2c_write(cam, 0x34, 0x07);
- err += sn9c102_i2c_write(cam, 0x35, 0x84);
- err += sn9c102_i2c_write(cam, 0x36, 0x00);
- err += sn9c102_i2c_write(cam, 0x37, 0x0C);
- err += sn9c102_i2c_write(cam, 0x38, 0x02);
- err += sn9c102_i2c_write(cam, 0x39, 0x43);
- err += sn9c102_i2c_write(cam, 0x3A, 0x00);
- err += sn9c102_i2c_write(cam, 0x3B, 0x0A);
- err += sn9c102_i2c_write(cam, 0x3C, 0x6C);
- err += sn9c102_i2c_write(cam, 0x3D, 0x99);
- err += sn9c102_i2c_write(cam, 0x3E, 0x0E);
- err += sn9c102_i2c_write(cam, 0x3F, 0x41);
- err += sn9c102_i2c_write(cam, 0x40, 0xC1);
- err += sn9c102_i2c_write(cam, 0x41, 0x22);
- err += sn9c102_i2c_write(cam, 0x42, 0x08);
- err += sn9c102_i2c_write(cam, 0x43, 0xF0);
- err += sn9c102_i2c_write(cam, 0x44, 0x10);
- err += sn9c102_i2c_write(cam, 0x45, 0x78);
- err += sn9c102_i2c_write(cam, 0x46, 0xA8);
- err += sn9c102_i2c_write(cam, 0x47, 0x60);
- err += sn9c102_i2c_write(cam, 0x48, 0x80);
- err += sn9c102_i2c_write(cam, 0x49, 0x00);
- err += sn9c102_i2c_write(cam, 0x4A, 0x00);
- err += sn9c102_i2c_write(cam, 0x4B, 0x00);
- err += sn9c102_i2c_write(cam, 0x4C, 0x00);
- err += sn9c102_i2c_write(cam, 0x4D, 0x00);
- err += sn9c102_i2c_write(cam, 0x4E, 0x00);
- err += sn9c102_i2c_write(cam, 0x4F, 0x46);
- err += sn9c102_i2c_write(cam, 0x50, 0x36);
- err += sn9c102_i2c_write(cam, 0x51, 0x0F);
- err += sn9c102_i2c_write(cam, 0x52, 0x17);
- err += sn9c102_i2c_write(cam, 0x53, 0x7F);
- err += sn9c102_i2c_write(cam, 0x54, 0x96);
- err += sn9c102_i2c_write(cam, 0x55, 0x40);
- err += sn9c102_i2c_write(cam, 0x56, 0x40);
- err += sn9c102_i2c_write(cam, 0x57, 0x40);
- err += sn9c102_i2c_write(cam, 0x58, 0x0F);
- err += sn9c102_i2c_write(cam, 0x59, 0xBA);
- err += sn9c102_i2c_write(cam, 0x5A, 0x9A);
- err += sn9c102_i2c_write(cam, 0x5B, 0x22);
- err += sn9c102_i2c_write(cam, 0x5C, 0xB9);
- err += sn9c102_i2c_write(cam, 0x5D, 0x9B);
- err += sn9c102_i2c_write(cam, 0x5E, 0x10);
- err += sn9c102_i2c_write(cam, 0x5F, 0xF0);
- err += sn9c102_i2c_write(cam, 0x60, 0x05);
- err += sn9c102_i2c_write(cam, 0x61, 0x60);
- err += sn9c102_i2c_write(cam, 0x62, 0x00);
- err += sn9c102_i2c_write(cam, 0x63, 0x00);
- err += sn9c102_i2c_write(cam, 0x64, 0x50);
- err += sn9c102_i2c_write(cam, 0x65, 0x30);
- err += sn9c102_i2c_write(cam, 0x66, 0x00);
- err += sn9c102_i2c_write(cam, 0x67, 0x80);
- err += sn9c102_i2c_write(cam, 0x68, 0x7A);
- err += sn9c102_i2c_write(cam, 0x69, 0x90);
- err += sn9c102_i2c_write(cam, 0x6A, 0x80);
- err += sn9c102_i2c_write(cam, 0x6B, 0x0A);
- err += sn9c102_i2c_write(cam, 0x6C, 0x30);
- err += sn9c102_i2c_write(cam, 0x6D, 0x48);
- err += sn9c102_i2c_write(cam, 0x6E, 0x80);
- err += sn9c102_i2c_write(cam, 0x6F, 0x74);
- err += sn9c102_i2c_write(cam, 0x70, 0x64);
- err += sn9c102_i2c_write(cam, 0x71, 0x60);
- err += sn9c102_i2c_write(cam, 0x72, 0x5C);
- err += sn9c102_i2c_write(cam, 0x73, 0x58);
- err += sn9c102_i2c_write(cam, 0x74, 0x54);
- err += sn9c102_i2c_write(cam, 0x75, 0x4C);
- err += sn9c102_i2c_write(cam, 0x76, 0x40);
- err += sn9c102_i2c_write(cam, 0x77, 0x38);
- err += sn9c102_i2c_write(cam, 0x78, 0x34);
- err += sn9c102_i2c_write(cam, 0x79, 0x30);
- err += sn9c102_i2c_write(cam, 0x7A, 0x2F);
- err += sn9c102_i2c_write(cam, 0x7B, 0x2B);
- err += sn9c102_i2c_write(cam, 0x7C, 0x03);
- err += sn9c102_i2c_write(cam, 0x7D, 0x07);
- err += sn9c102_i2c_write(cam, 0x7E, 0x17);
- err += sn9c102_i2c_write(cam, 0x7F, 0x34);
- err += sn9c102_i2c_write(cam, 0x80, 0x41);
- err += sn9c102_i2c_write(cam, 0x81, 0x4D);
- err += sn9c102_i2c_write(cam, 0x82, 0x58);
- err += sn9c102_i2c_write(cam, 0x83, 0x63);
- err += sn9c102_i2c_write(cam, 0x84, 0x6E);
- err += sn9c102_i2c_write(cam, 0x85, 0x77);
- err += sn9c102_i2c_write(cam, 0x86, 0x87);
- err += sn9c102_i2c_write(cam, 0x87, 0x95);
- err += sn9c102_i2c_write(cam, 0x88, 0xAF);
- err += sn9c102_i2c_write(cam, 0x89, 0xC7);
- err += sn9c102_i2c_write(cam, 0x8A, 0xDF);
- err += sn9c102_i2c_write(cam, 0x8B, 0x99);
- err += sn9c102_i2c_write(cam, 0x8C, 0x99);
- err += sn9c102_i2c_write(cam, 0x8D, 0xCF);
- err += sn9c102_i2c_write(cam, 0x8E, 0x20);
- err += sn9c102_i2c_write(cam, 0x8F, 0x26);
- err += sn9c102_i2c_write(cam, 0x90, 0x10);
- err += sn9c102_i2c_write(cam, 0x91, 0x0C);
- err += sn9c102_i2c_write(cam, 0x92, 0x25);
- err += sn9c102_i2c_write(cam, 0x93, 0x00);
- err += sn9c102_i2c_write(cam, 0x94, 0x50);
- err += sn9c102_i2c_write(cam, 0x95, 0x50);
- err += sn9c102_i2c_write(cam, 0x96, 0x00);
- err += sn9c102_i2c_write(cam, 0x97, 0x01);
- err += sn9c102_i2c_write(cam, 0x98, 0x10);
- err += sn9c102_i2c_write(cam, 0x99, 0x40);
- err += sn9c102_i2c_write(cam, 0x9A, 0x40);
- err += sn9c102_i2c_write(cam, 0x9B, 0x20);
- err += sn9c102_i2c_write(cam, 0x9C, 0x00);
- err += sn9c102_i2c_write(cam, 0x9D, 0x99);
- err += sn9c102_i2c_write(cam, 0x9E, 0x7F);
- err += sn9c102_i2c_write(cam, 0x9F, 0x00);
- err += sn9c102_i2c_write(cam, 0xA0, 0x00);
- err += sn9c102_i2c_write(cam, 0xA1, 0x00);
-
- return err;
-}
-
-
-static int ov7660_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- ctrl->value = sn9c102_i2c_read(cam, 0x10);
- if (ctrl->value < 0)
- return -EIO;
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- ctrl->value = sn9c102_read_reg(cam, 0x02);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x04) ? 1 : 0;
- break;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_read_reg(cam, 0x05);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x7f;
- break;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_read_reg(cam, 0x06);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x7f;
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_read_reg(cam, 0x07);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x7f;
- break;
- case SN9C102_V4L2_CID_BAND_FILTER:
- ctrl->value = sn9c102_i2c_read(cam, 0x3b);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x08;
- break;
- case V4L2_CID_GAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x00);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x1f;
- break;
- case V4L2_CID_AUTOGAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x13);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x01;
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
- break;
- case V4L2_CID_DO_WHITE_BALANCE:
- err += sn9c102_write_reg(cam, 0x43 | (ctrl->value << 2), 0x02);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x05);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x06);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_write_reg(cam, ctrl->value, 0x07);
- break;
- case SN9C102_V4L2_CID_BAND_FILTER:
- err += sn9c102_i2c_write(cam, ctrl->value << 3, 0x3b);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x00, 0x60 + ctrl->value);
- break;
- case V4L2_CID_AUTOGAIN:
- err += sn9c102_i2c_write(cam, 0x13, 0xc0 |
- (ctrl->value * 0x07));
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int ov7660_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 1,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 1;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int ov7660_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int r0, err = 0;
-
- r0 = sn9c102_pread_reg(cam, 0x01);
-
- if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
- err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
- err += sn9c102_write_reg(cam, 0xa2, 0x17);
- err += sn9c102_i2c_write(cam, 0x11, 0x00);
- } else {
- err += sn9c102_write_reg(cam, r0 | 0x40, 0x01);
- err += sn9c102_write_reg(cam, 0xa2, 0x17);
- err += sn9c102_i2c_write(cam, 0x11, 0x0d);
- }
-
- return err;
-}
-
-
-static const struct sn9c102_sensor ov7660 = {
- .name = "OV7660",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C105 | BRIDGE_SN9C120,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x21,
- .init = &ov7660_init,
- .qctrl = {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x09,
- .flags = 0,
- },
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = 0x27,
- .flags = 0,
- },
- {
- .id = V4L2_CID_DO_WHITE_BALANCE,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "night mode",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x14,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x14,
- .flags = 0,
- },
- {
- .id = V4L2_CID_AUTOGAIN,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "auto adjust",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x01,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x7f,
- .step = 0x01,
- .default_value = 0x14,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_BAND_FILTER,
- .type = V4L2_CTRL_TYPE_BOOLEAN,
- .name = "band filter",
- .minimum = 0x00,
- .maximum = 0x01,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- },
- .get_ctrl = &ov7660_get_ctrl,
- .set_ctrl = &ov7660_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &ov7660_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_JPEG,
- .priv = 8,
- },
- .set_pix_format = &ov7660_set_pix_format
-};
-
-
-int sn9c102_probe_ov7660(struct sn9c102_device *cam)
-{
- int pid, ver, err;
-
- err = sn9c102_write_const_regs(cam, {0x01, 0xf1}, {0x00, 0xf1},
- {0x01, 0x01}, {0x00, 0x01},
- {0x28, 0x17});
-
- pid = sn9c102_i2c_try_read(cam, &ov7660, 0x0a);
- ver = sn9c102_i2c_try_read(cam, &ov7660, 0x0b);
- if (err || pid < 0 || ver < 0)
- return -EIO;
- if (pid != 0x76 || ver != 0x60)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &ov7660);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_pas106b.c b/drivers/staging/media/sn9c102/sn9c102_pas106b.c
deleted file mode 100644
index 895931ecac48..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_pas106b.c
+++ /dev/null
@@ -1,308 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS106B image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas106b_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
- {0x00, 0x14}, {0x20, 0x17},
- {0x20, 0x19}, {0x09, 0x18});
-
- err += sn9c102_i2c_write(cam, 0x02, 0x0c);
- err += sn9c102_i2c_write(cam, 0x05, 0x5a);
- err += sn9c102_i2c_write(cam, 0x06, 0x88);
- err += sn9c102_i2c_write(cam, 0x07, 0x80);
- err += sn9c102_i2c_write(cam, 0x10, 0x06);
- err += sn9c102_i2c_write(cam, 0x11, 0x06);
- err += sn9c102_i2c_write(cam, 0x12, 0x00);
- err += sn9c102_i2c_write(cam, 0x14, 0x02);
- err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
- msleep(400);
-
- return err;
-}
-
-
-static int pas106b_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- {
- int r1 = sn9c102_i2c_read(cam, 0x03),
- r2 = sn9c102_i2c_read(cam, 0x04);
- if (r1 < 0 || r2 < 0)
- return -EIO;
- ctrl->value = (r1 << 4) | (r2 & 0x0f);
- }
- return 0;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x0c);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x1f;
- return 0;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x09);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x1f;
- return 0;
- case V4L2_CID_GAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x0e);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x1f;
- return 0;
- case V4L2_CID_CONTRAST:
- ctrl->value = sn9c102_i2c_read(cam, 0x0f);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x07;
- return 0;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x0a);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value = (ctrl->value & 0x1f) << 1;
- return 0;
- case SN9C102_V4L2_CID_DAC_MAGNITUDE:
- ctrl->value = sn9c102_i2c_read(cam, 0x08);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0xf8;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-static int pas106b_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x03, ctrl->value >> 4);
- err += sn9c102_i2c_write(cam, 0x04, ctrl->value & 0x0f);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x0e, ctrl->value);
- break;
- case V4L2_CID_CONTRAST:
- err += sn9c102_i2c_write(cam, 0x0f, ctrl->value);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_write(cam, 0x0a, ctrl->value >> 1);
- err += sn9c102_i2c_write(cam, 0x0b, ctrl->value >> 1);
- break;
- case SN9C102_V4L2_CID_DAC_MAGNITUDE:
- err += sn9c102_i2c_write(cam, 0x08, ctrl->value << 3);
- break;
- default:
- return -EINVAL;
- }
- err += sn9c102_i2c_write(cam, 0x13, 0x01);
-
- return err ? -EIO : 0;
-}
-
-
-static int pas106b_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static int pas106b_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x2c, 0x17);
- else
- err += sn9c102_write_reg(cam, 0x20, 0x17);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor pas106b = {
- .name = "PAS106B",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x40,
- .init = &pas106b_init,
- .qctrl = {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x125,
- .maximum = 0xfff,
- .step = 0x001,
- .default_value = 0x140,
- .flags = 0,
- },
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x0d,
- .flags = 0,
- },
- {
- .id = V4L2_CID_CONTRAST,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "contrast",
- .minimum = 0x00,
- .maximum = 0x07,
- .step = 0x01,
- .default_value = 0x00, /* 0x00~0x03 have same effect */
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x04,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x06,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x3e,
- .step = 0x02,
- .default_value = 0x02,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "DAC magnitude",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x01,
- .flags = 0,
- },
- },
- .get_ctrl = &pas106b_get_ctrl,
- .set_ctrl = &pas106b_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- },
- .set_crop = &pas106b_set_crop,
- .pix_format = {
- .width = 352,
- .height = 288,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8, /* we use this field as 'bits per pixel' */
- },
- .set_pix_format = &pas106b_set_pix_format
-};
-
-
-int sn9c102_probe_pas106b(struct sn9c102_device *cam)
-{
- int r0 = 0, r1 = 0;
- unsigned int pid = 0;
-
- /*
- Minimal initialization to enable the I2C communication
- NOTE: do NOT change the values!
- */
- if (sn9c102_write_const_regs(cam,
- {0x01, 0x01}, /* sensor power down */
- {0x00, 0x01}, /* sensor power on */
- {0x28, 0x17})) /* sensor clock at 24 MHz */
- return -EIO;
-
- r0 = sn9c102_i2c_try_read(cam, &pas106b, 0x00);
- r1 = sn9c102_i2c_try_read(cam, &pas106b, 0x01);
- if (r0 < 0 || r1 < 0)
- return -EIO;
-
- pid = (r0 << 11) | ((r1 & 0xf0) >> 4);
- if (pid != 0x007)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &pas106b);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c b/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c
deleted file mode 100644
index f9e31ae2ad9f..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_pas202bcb.c
+++ /dev/null
@@ -1,340 +0,0 @@
-/***************************************************************************
- * Plug-in for PAS202BCB image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004 by Carlos Eduardo Medaglia Dyonisio *
- * <medaglia@undl.org.br> *
- * *
- * Support for SN9C103, DAC Magnitude, exposure and green gain controls *
- * added by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include <linux/delay.h>
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int pas202bcb_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- err = sn9c102_write_const_regs(cam, {0x00, 0x10}, {0x00, 0x11},
- {0x00, 0x14}, {0x20, 0x17},
- {0x30, 0x19}, {0x09, 0x18});
- break;
- case BRIDGE_SN9C103:
- err = sn9c102_write_const_regs(cam, {0x00, 0x02}, {0x00, 0x03},
- {0x1a, 0x04}, {0x20, 0x05},
- {0x20, 0x06}, {0x20, 0x07},
- {0x00, 0x10}, {0x00, 0x11},
- {0x00, 0x14}, {0x20, 0x17},
- {0x30, 0x19}, {0x09, 0x18},
- {0x02, 0x1c}, {0x03, 0x1d},
- {0x0f, 0x1e}, {0x0c, 0x1f},
- {0x00, 0x20}, {0x10, 0x21},
- {0x20, 0x22}, {0x30, 0x23},
- {0x40, 0x24}, {0x50, 0x25},
- {0x60, 0x26}, {0x70, 0x27},
- {0x80, 0x28}, {0x90, 0x29},
- {0xa0, 0x2a}, {0xb0, 0x2b},
- {0xc0, 0x2c}, {0xd0, 0x2d},
- {0xe0, 0x2e}, {0xf0, 0x2f},
- {0xff, 0x30});
- break;
- default:
- break;
- }
-
- err += sn9c102_i2c_write(cam, 0x02, 0x14);
- err += sn9c102_i2c_write(cam, 0x03, 0x40);
- err += sn9c102_i2c_write(cam, 0x0d, 0x2c);
- err += sn9c102_i2c_write(cam, 0x0e, 0x01);
- err += sn9c102_i2c_write(cam, 0x0f, 0xa9);
- err += sn9c102_i2c_write(cam, 0x10, 0x08);
- err += sn9c102_i2c_write(cam, 0x13, 0x63);
- err += sn9c102_i2c_write(cam, 0x15, 0x70);
- err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
- msleep(400);
-
- return err;
-}
-
-
-static int pas202bcb_get_ctrl(struct sn9c102_device *cam,
- struct v4l2_control *ctrl)
-{
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- {
- int r1 = sn9c102_i2c_read(cam, 0x04),
- r2 = sn9c102_i2c_read(cam, 0x05);
- if (r1 < 0 || r2 < 0)
- return -EIO;
- ctrl->value = (r1 << 6) | (r2 & 0x3f);
- }
- return 0;
- case V4L2_CID_RED_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x09);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x0f;
- return 0;
- case V4L2_CID_BLUE_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x07);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x0f;
- return 0;
- case V4L2_CID_GAIN:
- ctrl->value = sn9c102_i2c_read(cam, 0x10);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x1f;
- return 0;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- ctrl->value = sn9c102_i2c_read(cam, 0x08);
- if (ctrl->value < 0)
- return -EIO;
- ctrl->value &= 0x0f;
- return 0;
- case SN9C102_V4L2_CID_DAC_MAGNITUDE:
- ctrl->value = sn9c102_i2c_read(cam, 0x0c);
- if (ctrl->value < 0)
- return -EIO;
- return 0;
- default:
- return -EINVAL;
- }
-}
-
-
-static int pas202bcb_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x28, 0x17);
- else
- err += sn9c102_write_reg(cam, 0x20, 0x17);
-
- return err;
-}
-
-
-static int pas202bcb_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x04, ctrl->value >> 6);
- err += sn9c102_i2c_write(cam, 0x05, ctrl->value & 0x3f);
- break;
- case V4L2_CID_RED_BALANCE:
- err += sn9c102_i2c_write(cam, 0x09, ctrl->value);
- break;
- case V4L2_CID_BLUE_BALANCE:
- err += sn9c102_i2c_write(cam, 0x07, ctrl->value);
- break;
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x10, ctrl->value);
- break;
- case SN9C102_V4L2_CID_GREEN_BALANCE:
- err += sn9c102_i2c_write(cam, 0x08, ctrl->value);
- break;
- case SN9C102_V4L2_CID_DAC_MAGNITUDE:
- err += sn9c102_i2c_write(cam, 0x0c, ctrl->value);
- break;
- default:
- return -EINVAL;
- }
- err += sn9c102_i2c_write(cam, 0x11, 0x01);
-
- return err ? -EIO : 0;
-}
-
-
-static int pas202bcb_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = 0,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 3;
-
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 4;
- break;
- case BRIDGE_SN9C103:
- h_start = (u8)(rect->left - s->cropcap.bounds.left) + 3;
- break;
- default:
- break;
- }
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor pas202bcb = {
- .name = "PAS202BCB",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102 | BRIDGE_SN9C103,
- .sysfs_ops = SN9C102_I2C_READ | SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_400KHZ | SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x40,
- .init = &pas202bcb_init,
- .qctrl = {
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x01e5,
- .maximum = 0x3fff,
- .step = 0x0001,
- .default_value = 0x01e5,
- .flags = 0,
- },
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0x1f,
- .step = 0x01,
- .default_value = 0x0b,
- .flags = 0,
- },
- {
- .id = V4L2_CID_RED_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "red balance",
- .minimum = 0x00,
- .maximum = 0x0f,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_BLUE_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "blue balance",
- .minimum = 0x00,
- .maximum = 0x0f,
- .step = 0x01,
- .default_value = 0x05,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_GREEN_BALANCE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "green balance",
- .minimum = 0x00,
- .maximum = 0x0f,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = SN9C102_V4L2_CID_DAC_MAGNITUDE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "DAC magnitude",
- .minimum = 0x00,
- .maximum = 0xff,
- .step = 0x01,
- .default_value = 0x04,
- .flags = 0,
- },
- },
- .get_ctrl = &pas202bcb_get_ctrl,
- .set_ctrl = &pas202bcb_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &pas202bcb_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &pas202bcb_set_pix_format
-};
-
-
-int sn9c102_probe_pas202bcb(struct sn9c102_device *cam)
-{
- int r0 = 0, r1 = 0, err = 0;
- unsigned int pid = 0;
-
- /*
- * Minimal initialization to enable the I2C communication
- * NOTE: do NOT change the values!
- */
- switch (sn9c102_get_bridge(cam)) {
- case BRIDGE_SN9C101:
- case BRIDGE_SN9C102:
- err = sn9c102_write_const_regs(cam,
- {0x01, 0x01}, /* power down */
- {0x40, 0x01}, /* power on */
- {0x28, 0x17});/* clock 24 MHz */
- break;
- case BRIDGE_SN9C103: /* do _not_ change anything! */
- err = sn9c102_write_const_regs(cam, {0x09, 0x01}, {0x44, 0x01},
- {0x44, 0x02}, {0x29, 0x17});
- break;
- default:
- break;
- }
-
- r0 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x00);
- r1 = sn9c102_i2c_try_read(cam, &pas202bcb, 0x01);
-
- if (err || r0 < 0 || r1 < 0)
- return -EIO;
-
- pid = (r0 << 4) | ((r1 & 0xf0) >> 4);
- if (pid != 0x017)
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &pas202bcb);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_sensor.h b/drivers/staging/media/sn9c102/sn9c102_sensor.h
deleted file mode 100644
index 9f59c815d48b..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_sensor.h
+++ /dev/null
@@ -1,307 +0,0 @@
-/***************************************************************************
- * API for image sensors connected to the SN9C1xx PC Camera Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#ifndef _SN9C102_SENSOR_H_
-#define _SN9C102_SENSOR_H_
-
-#include <linux/usb.h>
-#include <linux/videodev2.h>
-#include <linux/device.h>
-#include <linux/stddef.h>
-#include <linux/errno.h>
-#include <asm/types.h>
-
-struct sn9c102_device;
-struct sn9c102_sensor;
-
-/*****************************************************************************/
-
-/*
- OVERVIEW.
- This is a small interface that allows you to add support for any CCD/CMOS
- image sensors connected to the SN9C1XX bridges. The entire API is documented
- below. In the most general case, to support a sensor there are three steps
- you have to follow:
- 1) define the main "sn9c102_sensor" structure by setting the basic fields;
- 2) write a probing function to be called by the core module when the USB
- camera is recognized, then add both the USB ids and the name of that
- function to the two corresponding tables in sn9c102_devtable.h;
- 3) implement the methods that you want/need (and fill the rest of the main
- structure accordingly).
- "sn9c102_pas106b.c" is an example of all this stuff. Remember that you do
- NOT need to touch the source code of the core module for the things to work
- properly, unless you find bugs or flaws in it. Finally, do not forget to
- read the V4L2 API for completeness.
-*/
-
-/*****************************************************************************/
-
-enum sn9c102_bridge {
- BRIDGE_SN9C101 = 0x01,
- BRIDGE_SN9C102 = 0x02,
- BRIDGE_SN9C103 = 0x04,
- BRIDGE_SN9C105 = 0x08,
- BRIDGE_SN9C120 = 0x10,
-};
-
-/* Return the bridge name */
-enum sn9c102_bridge sn9c102_get_bridge(struct sn9c102_device *cam);
-
-/* Return a pointer the sensor struct attached to the camera */
-struct sn9c102_sensor *sn9c102_get_sensor(struct sn9c102_device *cam);
-
-/* Identify a device */
-extern struct sn9c102_device*
-sn9c102_match_id(struct sn9c102_device *cam, const struct usb_device_id *id);
-
-/* Attach a probed sensor to the camera. */
-extern void
-sn9c102_attach_sensor(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor);
-
-/*
- Read/write routines: they always return -1 on error, 0 or the read value
- otherwise. NOTE that a real read operation is not supported by the SN9C1XX
- chip for some of its registers. To work around this problem, a pseudo-read
- call is provided instead: it returns the last successfully written value
- on the register (0 if it has never been written), the usual -1 on error.
-*/
-
-/* The "try" I2C I/O versions are used when probing the sensor */
-extern int sn9c102_i2c_try_read(struct sn9c102_device*,
- const struct sn9c102_sensor*, u8 address);
-
-/*
- These must be used if and only if the sensor doesn't implement the standard
- I2C protocol. There are a number of good reasons why you must use the
- single-byte versions of these functions: do not abuse. The first function
- writes n bytes, from data0 to datan, to registers 0x09 - 0x09+n of SN9C1XX
- chip. The second one programs the registers 0x09 and 0x10 with data0 and
- data1, and places the n bytes read from the sensor register table in the
- buffer pointed by 'buffer'. Both the functions return -1 on error; the write
- version returns 0 on success, while the read version returns the first read
- byte.
-*/
-extern int sn9c102_i2c_try_raw_write(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor, u8 n,
- u8 data0, u8 data1, u8 data2, u8 data3,
- u8 data4, u8 data5);
-extern int sn9c102_i2c_try_raw_read(struct sn9c102_device *cam,
- const struct sn9c102_sensor *sensor,
- u8 data0, u8 data1, u8 n, u8 buffer[]);
-
-/* To be used after the sensor struct has been attached to the camera struct */
-extern int sn9c102_i2c_write(struct sn9c102_device*, u8 address, u8 value);
-extern int sn9c102_i2c_read(struct sn9c102_device*, u8 address);
-
-/* I/O on registers in the bridge. Could be used by the sensor methods too */
-extern int sn9c102_read_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_pread_reg(struct sn9c102_device*, u16 index);
-extern int sn9c102_write_reg(struct sn9c102_device*, u8 value, u16 index);
-extern int sn9c102_write_regs(struct sn9c102_device*, const u8 valreg[][2],
- int count);
-/*
- Write multiple registers with constant values. For example:
- sn9c102_write_const_regs(cam, {0x00, 0x14}, {0x60, 0x17}, {0x0f, 0x18});
- Register addresses must be < 256.
-*/
-#define sn9c102_write_const_regs(sn9c102_device, data...) \
- ({ static const u8 _valreg[][2] = {data}; \
- sn9c102_write_regs(sn9c102_device, _valreg, ARRAY_SIZE(_valreg)); })
-
-/*****************************************************************************/
-
-enum sn9c102_i2c_sysfs_ops {
- SN9C102_I2C_READ = 0x01,
- SN9C102_I2C_WRITE = 0x02,
-};
-
-enum sn9c102_i2c_frequency { /* sensors may support both the frequencies */
- SN9C102_I2C_100KHZ = 0x01,
- SN9C102_I2C_400KHZ = 0x02,
-};
-
-enum sn9c102_i2c_interface {
- SN9C102_I2C_2WIRES,
- SN9C102_I2C_3WIRES,
-};
-
-#define SN9C102_MAX_CTRLS (V4L2_CID_LASTP1-V4L2_CID_BASE+10)
-
-struct sn9c102_sensor {
- char name[32], /* sensor name */
- maintainer[64]; /* name of the maintainer <email> */
-
- enum sn9c102_bridge supported_bridge; /* supported SN9C1xx bridges */
-
- /* Supported operations through the 'sysfs' interface */
- enum sn9c102_i2c_sysfs_ops sysfs_ops;
-
- /*
- These sensor capabilities must be provided if the SN9C1XX controller
- needs to communicate through the sensor serial interface by using
- at least one of the i2c functions available.
- */
- enum sn9c102_i2c_frequency frequency;
- enum sn9c102_i2c_interface interface;
-
- /*
- This identifier must be provided if the image sensor implements
- the standard I2C protocol.
- */
- u8 i2c_slave_id; /* reg. 0x09 */
-
- /*
- NOTE: Where not noted,most of the functions below are not mandatory.
- Set to null if you do not implement them. If implemented,
- they must return 0 on success, the proper error otherwise.
- */
-
- int (*init)(struct sn9c102_device *cam);
- /*
- This function will be called after the sensor has been attached.
- It should be used to initialize the sensor only, but may also
- configure part of the SN9C1XX chip if necessary. You don't need to
- setup picture settings like brightness, contrast, etc.. here, if
- the corresponding controls are implemented (see below), since
- they are adjusted in the core driver by calling the set_ctrl()
- method after init(), where the arguments are the default values
- specified in the v4l2_queryctrl list of supported controls;
- Same suggestions apply for other settings, _if_ the corresponding
- methods are present; if not, the initialization must configure the
- sensor according to the default configuration structures below.
- */
-
- struct v4l2_queryctrl qctrl[SN9C102_MAX_CTRLS];
- /*
- Optional list of default controls, defined as indicated in the
- V4L2 API. Menu type controls are not handled by this interface.
- */
-
- int (*get_ctrl)(struct sn9c102_device *cam, struct v4l2_control *ctrl);
- int (*set_ctrl)(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl);
- /*
- You must implement at least the set_ctrl method if you have defined
- the list above. The returned value must follow the V4L2
- specifications for the VIDIOC_G|C_CTRL ioctls. V4L2_CID_H|VCENTER
- are not supported by this driver, so do not implement them. Also,
- you don't have to check whether the passed values are out of bounds,
- given that this is done by the core module.
- */
-
- struct v4l2_cropcap cropcap;
- /*
- Think the image sensor as a grid of R,G,B monochromatic pixels
- disposed according to a particular Bayer pattern, which describes
- the complete array of pixels, from (0,0) to (xmax, ymax). We will
- use this coordinate system from now on. It is assumed the sensor
- chip can be programmed to capture/transmit a subsection of that
- array of pixels: we will call this subsection "active window".
- It is not always true that the largest achievable active window can
- cover the whole array of pixels. The V4L2 API defines another
- area called "source rectangle", which, in turn, is a subrectangle of
- the active window. The SN9C1XX chip is always programmed to read the
- source rectangle.
- The bounds of both the active window and the source rectangle are
- specified in the cropcap substructures 'bounds' and 'defrect'.
- By default, the source rectangle should cover the largest possible
- area. Again, it is not always true that the largest source rectangle
- can cover the entire active window, although it is a rare case for
- the hardware we have. The bounds of the source rectangle _must_ be
- multiple of 16 and must use the same coordinate system as indicated
- before; their centers shall align initially.
- If necessary, the sensor chip must be initialized during init() to
- set the bounds of the active sensor window; however, by default, it
- usually covers the largest achievable area (maxwidth x maxheight)
- of pixels, so no particular initialization is needed, if you have
- defined the correct default bounds in the structures.
- See the V4L2 API for further details.
- NOTE: once you have defined the bounds of the active window
- (struct cropcap.bounds) you must not change them.anymore.
- Only 'bounds' and 'defrect' fields are mandatory, other fields
- will be ignored.
- */
-
- int (*set_crop)(struct sn9c102_device *cam,
- const struct v4l2_rect *rect);
- /*
- To be called on VIDIOC_C_SETCROP. The core module always calls a
- default routine which configures the appropriate SN9C1XX regs (also
- scaling), but you may need to override/adjust specific stuff.
- 'rect' contains width and height values that are multiple of 16: in
- case you override the default function, you always have to program
- the chip to match those values; on error return the corresponding
- error code without rolling back.
- NOTE: in case, you must program the SN9C1XX chip to get rid of
- blank pixels or blank lines at the _start_ of each line or
- frame after each HSYNC or VSYNC, so that the image starts with
- real RGB data (see regs 0x12, 0x13) (having set H_SIZE and,
- V_SIZE you don't have to care about blank pixels or blank
- lines at the end of each line or frame).
- */
-
- struct v4l2_pix_format pix_format;
- /*
- What you have to define here are: 1) initial 'width' and 'height' of
- the target rectangle 2) the initial 'pixelformat', which can be
- either V4L2_PIX_FMT_SN9C10X, V4L2_PIX_FMT_JPEG (for ompressed video)
- or V4L2_PIX_FMT_SBGGR8 3) 'priv', which we'll be used to indicate
- the number of bits per pixel for uncompressed video, 8 or 9 (despite
- the current value of 'pixelformat').
- NOTE 1: both 'width' and 'height' _must_ be either 1/1 or 1/2 or 1/4
- of cropcap.defrect.width and cropcap.defrect.height. I
- suggest 1/1.
- NOTE 2: The initial compression quality is defined by the first bit
- of reg 0x17 during the initialization of the image sensor.
- NOTE 3: as said above, you have to program the SN9C1XX chip to get
- rid of any blank pixels, so that the output of the sensor
- matches the RGB bayer sequence (i.e. BGBGBG...GRGRGR).
- */
-
- int (*set_pix_format)(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix);
- /*
- To be called on VIDIOC_S_FMT, when switching from the SBGGR8 to
- SN9C10X pixel format or viceversa. On error return the corresponding
- error code without rolling back.
- */
-
- /*
- Do NOT write to the data below, it's READ ONLY. It is used by the
- core module to store successfully updated values of the above
- settings, for rollbacks..etc..in case of errors during atomic I/O
- */
- struct v4l2_queryctrl _qctrl[SN9C102_MAX_CTRLS];
- struct v4l2_rect _rect;
-};
-
-/*****************************************************************************/
-
-/* Private ioctl's for control settings supported by some image sensors */
-#define SN9C102_V4L2_CID_DAC_MAGNITUDE (V4L2_CID_PRIVATE_BASE + 0)
-#define SN9C102_V4L2_CID_GREEN_BALANCE (V4L2_CID_PRIVATE_BASE + 1)
-#define SN9C102_V4L2_CID_RESET_LEVEL (V4L2_CID_PRIVATE_BASE + 2)
-#define SN9C102_V4L2_CID_PIXEL_BIAS_VOLTAGE (V4L2_CID_PRIVATE_BASE + 3)
-#define SN9C102_V4L2_CID_GAMMA (V4L2_CID_PRIVATE_BASE + 4)
-#define SN9C102_V4L2_CID_BAND_FILTER (V4L2_CID_PRIVATE_BASE + 5)
-#define SN9C102_V4L2_CID_BRIGHT_LEVEL (V4L2_CID_PRIVATE_BASE + 6)
-
-#endif /* _SN9C102_SENSOR_H_ */
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c
deleted file mode 100644
index 6a00b626d347..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5110c1b.c
+++ /dev/null
@@ -1,154 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110C1B image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110c1b_init(struct sn9c102_device *cam)
-{
- int err = 0;
-
- err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x44, 0x01},
- {0x00, 0x10}, {0x00, 0x11},
- {0x0a, 0x14}, {0x60, 0x17},
- {0x06, 0x18}, {0xfb, 0x19});
-
- err += sn9c102_i2c_write(cam, 0xc0, 0x80);
-
- return err;
-}
-
-
-static int tas5110c1b_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int tas5110c1b_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- /* Don't change ! */
- err += sn9c102_write_reg(cam, 0x14, 0x1a);
- err += sn9c102_write_reg(cam, 0x0a, 0x1b);
- err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
- return err;
-}
-
-
-static int tas5110c1b_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x2b, 0x19);
- else
- err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor tas5110c1b = {
- .name = "TAS5110C1B",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .sysfs_ops = SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_3WIRES,
- .init = &tas5110c1b_init,
- .qctrl = {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0xf6,
- .step = 0x01,
- .default_value = 0x40,
- .flags = 0,
- },
- },
- .set_ctrl = &tas5110c1b_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- },
- .set_crop = &tas5110c1b_set_crop,
- .pix_format = {
- .width = 352,
- .height = 288,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &tas5110c1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110c1b(struct sn9c102_device *cam)
-{
- const struct usb_device_id tas5110c1b_id_table[] = {
- { USB_DEVICE(0x0c45, 0x6001), },
- { USB_DEVICE(0x0c45, 0x6005), },
- { USB_DEVICE(0x0c45, 0x60ab), },
- { }
- };
-
- /* Sensor detection is based on USB pid/vid */
- if (!sn9c102_match_id(cam, tas5110c1b_id_table))
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &tas5110c1b);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c b/drivers/staging/media/sn9c102/sn9c102_tas5110d.c
deleted file mode 100644
index eefbf8670c3e..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5110d.c
+++ /dev/null
@@ -1,119 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5110D image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5110d_init(struct sn9c102_device *cam)
-{
- int err;
-
- err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x04, 0x01},
- {0x0a, 0x14}, {0x60, 0x17},
- {0x06, 0x18}, {0xfb, 0x19});
-
- err += sn9c102_i2c_write(cam, 0x9a, 0xca);
-
- return err;
-}
-
-
-static int tas5110d_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- int err = 0;
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 69,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 9;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- err += sn9c102_write_reg(cam, 0x14, 0x1a);
- err += sn9c102_write_reg(cam, 0x0a, 0x1b);
-
- return err;
-}
-
-
-static int tas5110d_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x3b, 0x19);
- else
- err += sn9c102_write_reg(cam, 0xfb, 0x19);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor tas5110d = {
- .name = "TAS5110D",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .sysfs_ops = SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_2WIRES,
- .i2c_slave_id = 0x61,
- .init = &tas5110d_init,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 352,
- .height = 288,
- },
- },
- .set_crop = &tas5110d_set_crop,
- .pix_format = {
- .width = 352,
- .height = 288,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &tas5110d_set_pix_format
-};
-
-
-int sn9c102_probe_tas5110d(struct sn9c102_device *cam)
-{
- const struct usb_device_id tas5110d_id_table[] = {
- { USB_DEVICE(0x0c45, 0x6007), },
- { }
- };
-
- if (!sn9c102_match_id(cam, tas5110d_id_table))
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &tas5110d);
-
- return 0;
-}
diff --git a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c b/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c
deleted file mode 100644
index 725de857de45..000000000000
--- a/drivers/staging/media/sn9c102/sn9c102_tas5130d1b.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/***************************************************************************
- * Plug-in for TAS5130D1B image sensor connected to the SN9C1xx PC Camera *
- * Controllers *
- * *
- * Copyright (C) 2004-2007 by Luca Risolia <luca.risolia@studio.unibo.it> *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU General Public License as published by *
- * the Free Software Foundation; either version 2 of the License, or *
- * (at your option) any later version. *
- * *
- * This program is distributed in the hope that it will be useful, *
- * but WITHOUT ANY WARRANTY; without even the implied warranty of *
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
- * GNU General Public License for more details. *
- * *
- * You should have received a copy of the GNU General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. *
- ***************************************************************************/
-
-#include "sn9c102_sensor.h"
-#include "sn9c102_devtable.h"
-
-
-static int tas5130d1b_init(struct sn9c102_device *cam)
-{
- int err;
-
- err = sn9c102_write_const_regs(cam, {0x01, 0x01}, {0x20, 0x17},
- {0x04, 0x01}, {0x01, 0x10},
- {0x00, 0x11}, {0x00, 0x14},
- {0x60, 0x17}, {0x07, 0x18});
-
- return err;
-}
-
-
-static int tas5130d1b_set_ctrl(struct sn9c102_device *cam,
- const struct v4l2_control *ctrl)
-{
- int err = 0;
-
- switch (ctrl->id) {
- case V4L2_CID_GAIN:
- err += sn9c102_i2c_write(cam, 0x20, 0xf6 - ctrl->value);
- break;
- case V4L2_CID_EXPOSURE:
- err += sn9c102_i2c_write(cam, 0x40, 0x47 - ctrl->value);
- break;
- default:
- return -EINVAL;
- }
-
- return err ? -EIO : 0;
-}
-
-
-static int tas5130d1b_set_crop(struct sn9c102_device *cam,
- const struct v4l2_rect *rect)
-{
- struct sn9c102_sensor *s = sn9c102_get_sensor(cam);
- u8 h_start = (u8)(rect->left - s->cropcap.bounds.left) + 104,
- v_start = (u8)(rect->top - s->cropcap.bounds.top) + 12;
- int err = 0;
-
- err += sn9c102_write_reg(cam, h_start, 0x12);
- err += sn9c102_write_reg(cam, v_start, 0x13);
-
- /* Do NOT change! */
- err += sn9c102_write_reg(cam, 0x1f, 0x1a);
- err += sn9c102_write_reg(cam, 0x1a, 0x1b);
- err += sn9c102_write_reg(cam, sn9c102_pread_reg(cam, 0x19), 0x19);
-
- return err;
-}
-
-
-static int tas5130d1b_set_pix_format(struct sn9c102_device *cam,
- const struct v4l2_pix_format *pix)
-{
- int err = 0;
-
- if (pix->pixelformat == V4L2_PIX_FMT_SN9C10X)
- err += sn9c102_write_reg(cam, 0x63, 0x19);
- else
- err += sn9c102_write_reg(cam, 0xf3, 0x19);
-
- return err;
-}
-
-
-static const struct sn9c102_sensor tas5130d1b = {
- .name = "TAS5130D1B",
- .maintainer = "Luca Risolia <luca.risolia@studio.unibo.it>",
- .supported_bridge = BRIDGE_SN9C101 | BRIDGE_SN9C102,
- .sysfs_ops = SN9C102_I2C_WRITE,
- .frequency = SN9C102_I2C_100KHZ,
- .interface = SN9C102_I2C_3WIRES,
- .init = &tas5130d1b_init,
- .qctrl = {
- {
- .id = V4L2_CID_GAIN,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "global gain",
- .minimum = 0x00,
- .maximum = 0xf6,
- .step = 0x02,
- .default_value = 0x00,
- .flags = 0,
- },
- {
- .id = V4L2_CID_EXPOSURE,
- .type = V4L2_CTRL_TYPE_INTEGER,
- .name = "exposure",
- .minimum = 0x00,
- .maximum = 0x47,
- .step = 0x01,
- .default_value = 0x00,
- .flags = 0,
- },
- },
- .set_ctrl = &tas5130d1b_set_ctrl,
- .cropcap = {
- .bounds = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- .defrect = {
- .left = 0,
- .top = 0,
- .width = 640,
- .height = 480,
- },
- },
- .set_crop = &tas5130d1b_set_crop,
- .pix_format = {
- .width = 640,
- .height = 480,
- .pixelformat = V4L2_PIX_FMT_SBGGR8,
- .priv = 8,
- },
- .set_pix_format = &tas5130d1b_set_pix_format
-};
-
-
-int sn9c102_probe_tas5130d1b(struct sn9c102_device *cam)
-{
- const struct usb_device_id tas5130d1b_id_table[] = {
- { USB_DEVICE(0x0c45, 0x6024), },
- { USB_DEVICE(0x0c45, 0x6025), },
- { USB_DEVICE(0x0c45, 0x60aa), },
- { }
- };
-
- /* Sensor detection is based on USB pid/vid */
- if (!sn9c102_match_id(cam, tas5130d1b_id_table))
- return -ENODEV;
-
- sn9c102_attach_sensor(cam, &tas5130d1b);
-
- return 0;
-}
diff --git a/drivers/staging/media/solo6x10/Kconfig b/drivers/staging/media/solo6x10/Kconfig
index 6a1906fa1117..1ce2819efcb4 100644
--- a/drivers/staging/media/solo6x10/Kconfig
+++ b/drivers/staging/media/solo6x10/Kconfig
@@ -1,6 +1,7 @@
config SOLO6X10
tristate "Bluecherry / Softlogic 6x10 capture cards (MPEG-4/H.264)"
depends on PCI && VIDEO_DEV && SND && I2C
+ select BITREVERSE
select FONT_SUPPORT
select FONT_8x16
select VIDEOBUF2_DMA_SG
diff --git a/drivers/staging/media/solo6x10/solo6x10-core.c b/drivers/staging/media/solo6x10/solo6x10-core.c
index f67046955ef6..172583d736fe 100644
--- a/drivers/staging/media/solo6x10/solo6x10-core.c
+++ b/drivers/staging/media/solo6x10/solo6x10-core.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -307,8 +303,8 @@ static ssize_t p2m_timeout_store(struct device *dev,
struct solo_dev *solo_dev =
container_of(dev, struct solo_dev, dev);
unsigned long ms;
-
int ret = kstrtoul(buf, 10, &ms);
+
if (ret < 0 || ms > 200)
return -EINVAL;
solo_dev->p2m_jiffies = msecs_to_jiffies(ms);
diff --git a/drivers/staging/media/solo6x10/solo6x10-disp.c b/drivers/staging/media/solo6x10/solo6x10-disp.c
index 145295a5db72..ed88ab4455a5 100644
--- a/drivers/staging/media/solo6x10/solo6x10-disp.c
+++ b/drivers/staging/media/solo6x10/solo6x10-disp.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -211,21 +207,23 @@ int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val)
}
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
- const struct solo_motion_thresholds *thresholds)
+ const u16 *thresholds)
{
+ const unsigned size = sizeof(u16) * 64;
u32 off = SOLO_MOT_FLAG_AREA + ch * SOLO_MOT_THRESH_SIZE * 2;
- u16 buf[64];
+ u16 *buf;
int x, y;
int ret = 0;
- memset(buf, 0, sizeof(buf));
+ buf = kzalloc(size, GFP_KERNEL);
for (y = 0; y < SOLO_MOTION_SZ; y++) {
for (x = 0; x < SOLO_MOTION_SZ; x++)
- buf[x] = cpu_to_le16(thresholds->thresholds[y][x]);
+ buf[x] = cpu_to_le16(thresholds[y * SOLO_MOTION_SZ + x]);
ret |= solo_p2m_dma(solo_dev, 1, buf,
- SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * sizeof(buf),
- sizeof(buf), 0, 0);
+ SOLO_MOTION_EXT_ADDR(solo_dev) + off + y * size,
+ size, 0, 0);
}
+ kfree(buf);
return ret;
}
diff --git a/drivers/staging/media/solo6x10/solo6x10-eeprom.c b/drivers/staging/media/solo6x10/solo6x10-eeprom.c
index 9d1c9bb53d6b..af40b3aba410 100644
--- a/drivers/staging/media/solo6x10/solo6x10-eeprom.c
+++ b/drivers/staging/media/solo6x10/solo6x10-eeprom.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-enc.c b/drivers/staging/media/solo6x10/solo6x10-enc.c
index 2db53b68c62f..d19c0aef5abc 100644
--- a/drivers/staging/media/solo6x10/solo6x10-enc.c
+++ b/drivers/staging/media/solo6x10/solo6x10-enc.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-g723.c b/drivers/staging/media/solo6x10/solo6x10-g723.c
index 74f037b6166c..c7141f2e63bd 100644
--- a/drivers/staging/media/solo6x10/solo6x10-g723.c
+++ b/drivers/staging/media/solo6x10/solo6x10-g723.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-gpio.c b/drivers/staging/media/solo6x10/solo6x10-gpio.c
index 73276dc92875..6d3b4a36bc11 100644
--- a/drivers/staging/media/solo6x10/solo6x10-gpio.c
+++ b/drivers/staging/media/solo6x10/solo6x10-gpio.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-i2c.c b/drivers/staging/media/solo6x10/solo6x10-i2c.c
index 01aa417c9258..c908672b2c40 100644
--- a/drivers/staging/media/solo6x10/solo6x10-i2c.c
+++ b/drivers/staging/media/solo6x10/solo6x10-i2c.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
/* XXX: The SOLO6x10 i2c does not have separate interrupts for each i2c
diff --git a/drivers/staging/media/solo6x10/solo6x10-jpeg.h b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
index c5218ceeabca..1c66a46da514 100644
--- a/drivers/staging/media/solo6x10/solo6x10-jpeg.h
+++ b/drivers/staging/media/solo6x10/solo6x10-jpeg.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_JPEG_H
@@ -110,7 +106,7 @@ static const unsigned char jpeg_header[] = {
/* This is the byte marker for the start of the DQT */
#define DQT_START 17
#define DQT_LEN 138
-const unsigned char jpeg_dqt[4][DQT_LEN] = {
+static const unsigned char jpeg_dqt[4][DQT_LEN] = {
{
0xff, 0xdb, 0x00, 0x43, 0x00,
0x08, 0x06, 0x06, 0x07, 0x06, 0x05, 0x08, 0x07,
diff --git a/drivers/staging/media/solo6x10/solo6x10-offsets.h b/drivers/staging/media/solo6x10/solo6x10-offsets.h
index 13eeb4470dcf..d6aea7c2a676 100644
--- a/drivers/staging/media/solo6x10/solo6x10-offsets.h
+++ b/drivers/staging/media/solo6x10/solo6x10-offsets.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_OFFSETS_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-p2m.c b/drivers/staging/media/solo6x10/solo6x10-p2m.c
index 7f2f2472655b..8c8484674d2f 100644
--- a/drivers/staging/media/solo6x10/solo6x10-p2m.c
+++ b/drivers/staging/media/solo6x10/solo6x10-p2m.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
diff --git a/drivers/staging/media/solo6x10/solo6x10-regs.h b/drivers/staging/media/solo6x10/solo6x10-regs.h
index 428f6c951180..e34ac56ab101 100644
--- a/drivers/staging/media/solo6x10/solo6x10-regs.h
+++ b/drivers/staging/media/solo6x10/solo6x10-regs.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_REGISTERS_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.c b/drivers/staging/media/solo6x10/solo6x10-tw28.c
index 36daa1720b54..edd0781ee4b5 100644
--- a/drivers/staging/media/solo6x10/solo6x10-tw28.c
+++ b/drivers/staging/media/solo6x10/solo6x10-tw28.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -214,6 +210,7 @@ static void tw_write_and_verify(struct solo_dev *solo_dev, u8 addr, u8 off,
for (i = 0; i < 5; i++) {
u8 rval = solo_i2c_readbyte(solo_dev, SOLO_I2C_TW, addr, off);
+
if (rval == val)
return;
diff --git a/drivers/staging/media/solo6x10/solo6x10-tw28.h b/drivers/staging/media/solo6x10/solo6x10-tw28.h
index 1a02c87d4cf0..0966b45057a3 100644
--- a/drivers/staging/media/solo6x10/solo6x10-tw28.h
+++ b/drivers/staging/media/solo6x10/solo6x10-tw28.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_TW28_H
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
index b8ff113c20f4..2e07b497a37c 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2-enc.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -243,6 +239,8 @@ static int solo_enc_on(struct solo_enc_dev *solo_enc)
if (solo_enc->bw_weight > solo_dev->enc_bw_remain)
return -EBUSY;
solo_enc->sequence = 0;
+ solo_enc->motion_last_state = false;
+ solo_enc->frames_since_last_motion = 0;
solo_dev->enc_bw_remain -= solo_enc->bw_weight;
if (solo_enc->type == SOLO_ENC_TYPE_EXT)
@@ -476,8 +474,9 @@ static int solo_fill_jpeg(struct solo_enc_dev *solo_enc,
vb2_set_plane_payload(vb, 0, vop_jpeg_size(vh) + solo_enc->jpeg_len);
/* may discard all previous data in vbuf->sgl */
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
- DMA_FROM_DEVICE);
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
ret = solo_send_desc(solo_enc, solo_enc->jpeg_len, vbuf,
vop_jpeg_offset(vh) - SOLO_JPEG_EXT_ADDR(solo_dev),
frame_size, SOLO_JPEG_EXT_ADDR(solo_dev),
@@ -523,8 +522,9 @@ static int solo_fill_mpeg(struct solo_enc_dev *solo_enc,
frame_size = ALIGN(vop_mpeg_size(vh) + skip, DMA_ALIGN);
/* may discard all previous data in vbuf->sgl */
- dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
- DMA_FROM_DEVICE);
+ if (!dma_map_sg(&solo_dev->pdev->dev, vbuf->sgl, vbuf->nents,
+ DMA_FROM_DEVICE))
+ return -ENOMEM;
ret = solo_send_desc(solo_enc, skip, vbuf, frame_off, frame_size,
SOLO_MP4E_EXT_ADDR(solo_dev),
SOLO_MP4E_EXT_SIZE(solo_dev));
@@ -544,15 +544,6 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
const vop_header *vh = enc_buf->vh;
int ret;
- /* Check for motion flags */
- vb->v4l2_buf.flags &= ~(V4L2_BUF_FLAG_MOTION_ON |
- V4L2_BUF_FLAG_MOTION_DETECTED);
- if (solo_is_motion_on(solo_enc)) {
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_ON;
- if (enc_buf->motion)
- vb->v4l2_buf.flags |= V4L2_BUF_FLAG_MOTION_DETECTED;
- }
-
switch (solo_enc->fmt) {
case V4L2_PIX_FMT_MPEG4:
case V4L2_PIX_FMT_H264:
@@ -564,9 +555,49 @@ static int solo_enc_fillbuf(struct solo_enc_dev *solo_enc,
}
if (!ret) {
+ bool send_event = false;
+
vb->v4l2_buf.sequence = solo_enc->sequence++;
vb->v4l2_buf.timestamp.tv_sec = vop_sec(vh);
vb->v4l2_buf.timestamp.tv_usec = vop_usec(vh);
+
+ /* Check for motion flags */
+ if (solo_is_motion_on(solo_enc)) {
+ /* It takes a few frames for the hardware to detect
+ * motion. Once it does it clears the motion detection
+ * register and it takes again a few frames before
+ * motion is seen. This means in practice that when the
+ * motion field is 1, it will go back to 0 for the next
+ * frame. This leads to motion detection event being
+ * sent all the time, which is not what we want.
+ * Instead wait a few frames before deciding that the
+ * motion has halted. After some experimentation it
+ * turns out that waiting for 5 frames works well.
+ */
+ if (enc_buf->motion == 0 &&
+ solo_enc->motion_last_state &&
+ solo_enc->frames_since_last_motion++ > 5)
+ send_event = true;
+ else if (enc_buf->motion) {
+ solo_enc->frames_since_last_motion = 0;
+ send_event = !solo_enc->motion_last_state;
+ }
+ }
+
+ if (send_event) {
+ struct v4l2_event ev = {
+ .type = V4L2_EVENT_MOTION_DET,
+ .u.motion_det = {
+ .flags = V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ,
+ .frame_sequence = vb->v4l2_buf.sequence,
+ .region_mask = enc_buf->motion ? 1 : 0,
+ },
+ };
+
+ solo_enc->motion_last_state = enc_buf->motion;
+ solo_enc->frames_since_last_motion = 0;
+ v4l2_event_queue(solo_enc->vfd, &ev);
+ }
}
vb2_buffer_done(vb, ret ? VB2_BUF_STATE_ERROR : VB2_BUF_STATE_DONE);
@@ -669,6 +700,7 @@ static int solo_ring_thread(void *data)
for (;;) {
long timeout = schedule_timeout_interruptible(HZ);
+
if (timeout == -ERESTARTSYS || kthread_should_stop())
break;
solo_irq_off(solo_dev, SOLO_IRQ_ENCODER);
@@ -715,6 +747,7 @@ static int solo_ring_start(struct solo_dev *solo_dev)
SOLO6X10_NAME "_ring");
if (IS_ERR(solo_dev->ring_thread)) {
int err = PTR_ERR(solo_dev->ring_thread);
+
solo_dev->ring_thread = NULL;
return err;
}
@@ -1068,31 +1101,6 @@ static int solo_s_parm(struct file *file, void *priv,
return solo_g_parm(file, priv, sp);
}
-static long solo_enc_default(struct file *file, void *fh,
- bool valid_prio, unsigned int cmd, void *arg)
-{
- struct solo_enc_dev *solo_enc = video_drvdata(file);
- struct solo_dev *solo_dev = solo_enc->solo_dev;
- struct solo_motion_thresholds *thresholds = arg;
-
- switch (cmd) {
- case SOLO_IOC_G_MOTION_THRESHOLDS:
- *thresholds = solo_enc->motion_thresholds;
- return 0;
-
- case SOLO_IOC_S_MOTION_THRESHOLDS:
- if (!valid_prio)
- return -EBUSY;
- solo_enc->motion_thresholds = *thresholds;
- if (solo_enc->motion_enabled && !solo_enc->motion_global)
- return solo_set_motion_block(solo_dev, solo_enc->ch,
- &solo_enc->motion_thresholds);
- return 0;
- default:
- return -ENOTTY;
- }
-}
-
static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
{
struct solo_enc_dev *solo_enc =
@@ -1110,28 +1118,40 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
ctrl->val);
case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
solo_enc->gop = ctrl->val;
+ solo_reg_write(solo_dev, SOLO_VE_CH_GOP(solo_enc->ch), solo_enc->gop);
+ solo_reg_write(solo_dev, SOLO_VE_CH_GOP_E(solo_enc->ch), solo_enc->gop);
return 0;
- case V4L2_CID_MOTION_THRESHOLD:
- solo_enc->motion_thresh = ctrl->val;
+ case V4L2_CID_MPEG_VIDEO_H264_MIN_QP:
+ solo_enc->qp = ctrl->val;
+ solo_reg_write(solo_dev, SOLO_VE_CH_QP(solo_enc->ch), solo_enc->qp);
+ solo_reg_write(solo_dev, SOLO_VE_CH_QP_E(solo_enc->ch), solo_enc->qp);
+ return 0;
+ case V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD:
+ solo_enc->motion_thresh = ctrl->val << 8;
if (!solo_enc->motion_global || !solo_enc->motion_enabled)
return 0;
return solo_set_motion_threshold(solo_dev, solo_enc->ch,
- ctrl->val);
- case V4L2_CID_MOTION_MODE:
- solo_enc->motion_global = ctrl->val == 1;
- solo_enc->motion_enabled = ctrl->val > 0;
+ solo_enc->motion_thresh);
+ case V4L2_CID_DETECT_MD_MODE:
+ solo_enc->motion_global = ctrl->val == V4L2_DETECT_MD_MODE_GLOBAL;
+ solo_enc->motion_enabled = ctrl->val > V4L2_DETECT_MD_MODE_DISABLED;
if (ctrl->val) {
if (solo_enc->motion_global)
- solo_set_motion_threshold(solo_dev,
- solo_enc->ch, solo_enc->motion_thresh);
+ solo_set_motion_threshold(solo_dev, solo_enc->ch,
+ solo_enc->motion_thresh);
else
solo_set_motion_block(solo_dev, solo_enc->ch,
- &solo_enc->motion_thresholds);
+ solo_enc->md_thresholds->p_cur.p_u16);
}
solo_motion_toggle(solo_enc, ctrl->val);
return 0;
+ case V4L2_CID_DETECT_MD_THRESHOLD_GRID:
+ if (solo_enc->motion_enabled && !solo_enc->motion_global)
+ return solo_set_motion_block(solo_dev, solo_enc->ch,
+ solo_enc->md_thresholds->p_new.p_u16);
+ break;
case V4L2_CID_OSD_TEXT:
- strcpy(solo_enc->osd_text, ctrl->string);
+ strcpy(solo_enc->osd_text, ctrl->p_new.p_char);
err = solo_osd_print(solo_enc);
return err;
default:
@@ -1141,6 +1161,21 @@ static int solo_s_ctrl(struct v4l2_ctrl *ctrl)
return 0;
}
+static int solo_subscribe_event(struct v4l2_fh *fh,
+ const struct v4l2_event_subscription *sub)
+{
+
+ switch (sub->type) {
+ case V4L2_EVENT_CTRL:
+ return v4l2_ctrl_subscribe_event(fh, sub);
+ case V4L2_EVENT_MOTION_DET:
+ /* Allow for up to 30 events (1 second for NTSC) to be
+ * stored. */
+ return v4l2_event_subscribe(fh, sub, 30, NULL);
+ }
+ return -EINVAL;
+}
+
static const struct v4l2_file_operations solo_enc_fops = {
.owner = THIS_MODULE,
.open = v4l2_fh_open,
@@ -1179,9 +1214,8 @@ static const struct v4l2_ioctl_ops solo_enc_ioctl_ops = {
.vidioc_g_parm = solo_g_parm,
/* Logging and events */
.vidioc_log_status = v4l2_ctrl_log_status,
- .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+ .vidioc_subscribe_event = solo_subscribe_event,
.vidioc_unsubscribe_event = v4l2_event_unsubscribe,
- .vidioc_default = solo_enc_default,
};
static const struct video_device solo_enc_template = {
@@ -1197,33 +1231,6 @@ static const struct v4l2_ctrl_ops solo_ctrl_ops = {
.s_ctrl = solo_s_ctrl,
};
-static const struct v4l2_ctrl_config solo_motion_threshold_ctrl = {
- .ops = &solo_ctrl_ops,
- .id = V4L2_CID_MOTION_THRESHOLD,
- .name = "Motion Detection Threshold",
- .type = V4L2_CTRL_TYPE_INTEGER,
- .max = 0xffff,
- .def = SOLO_DEF_MOT_THRESH,
- .step = 1,
- .flags = V4L2_CTRL_FLAG_SLIDER,
-};
-
-static const char * const solo_motion_mode_menu[] = {
- "Disabled",
- "Global Threshold",
- "Regional Threshold",
- NULL
-};
-
-static const struct v4l2_ctrl_config solo_motion_enable_ctrl = {
- .ops = &solo_ctrl_ops,
- .id = V4L2_CID_MOTION_MODE,
- .name = "Motion Detection Mode",
- .type = V4L2_CTRL_TYPE_MENU,
- .qmenu = solo_motion_mode_menu,
- .max = 2,
-};
-
static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
.ops = &solo_ctrl_ops,
.id = V4L2_CID_OSD_TEXT,
@@ -1233,13 +1240,22 @@ static const struct v4l2_ctrl_config solo_osd_text_ctrl = {
.step = 1,
};
+/* Motion Detection Threshold matrix */
+static const struct v4l2_ctrl_config solo_md_thresholds = {
+ .ops = &solo_ctrl_ops,
+ .id = V4L2_CID_DETECT_MD_THRESHOLD_GRID,
+ .dims = { SOLO_MOTION_SZ, SOLO_MOTION_SZ },
+ .def = SOLO_DEF_MOT_THRESH,
+ .max = 65535,
+ .step = 1,
+};
+
static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
u8 ch, unsigned nr)
{
struct solo_enc_dev *solo_enc;
struct v4l2_ctrl_handler *hdl;
int ret;
- int x, y;
solo_enc = kzalloc(sizeof(*solo_enc), GFP_KERNEL);
if (!solo_enc)
@@ -1260,9 +1276,18 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
V4L2_CID_SHARPNESS, 0, 15, 1, 0);
v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
V4L2_CID_MPEG_VIDEO_GOP_SIZE, 1, 255, 1, solo_dev->fps);
- v4l2_ctrl_new_custom(hdl, &solo_motion_threshold_ctrl, NULL);
- v4l2_ctrl_new_custom(hdl, &solo_motion_enable_ctrl, NULL);
+ v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+ V4L2_CID_MPEG_VIDEO_H264_MIN_QP, 0, 31, 1, SOLO_DEFAULT_QP);
+ v4l2_ctrl_new_std_menu(hdl, &solo_ctrl_ops,
+ V4L2_CID_DETECT_MD_MODE,
+ V4L2_DETECT_MD_MODE_THRESHOLD_GRID, 0,
+ V4L2_DETECT_MD_MODE_DISABLED);
+ v4l2_ctrl_new_std(hdl, &solo_ctrl_ops,
+ V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD, 0, 0xff, 1,
+ SOLO_DEF_MOT_THRESH >> 8);
v4l2_ctrl_new_custom(hdl, &solo_osd_text_ctrl, NULL);
+ solo_enc->md_thresholds =
+ v4l2_ctrl_new_custom(hdl, &solo_md_thresholds, NULL);
if (hdl->error) {
ret = hdl->error;
goto hdl_free;
@@ -1283,11 +1308,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->mode = SOLO_ENC_MODE_CIF;
solo_enc->motion_global = true;
solo_enc->motion_thresh = SOLO_DEF_MOT_THRESH;
- for (y = 0; y < SOLO_MOTION_SZ; y++)
- for (x = 0; x < SOLO_MOTION_SZ; x++)
- solo_enc->motion_thresholds.thresholds[y][x] =
- SOLO_DEF_MOT_THRESH;
-
solo_enc->vidq.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
solo_enc->vidq.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
solo_enc->vidq.ops = &solo_enc_video_qops;
@@ -1326,7 +1346,6 @@ static struct solo_enc_dev *solo_enc_alloc(struct solo_dev *solo_dev,
solo_enc->vfd->ctrl_handler = hdl;
solo_enc->vfd->queue = &solo_enc->vidq;
solo_enc->vfd->lock = &solo_enc->lock;
- set_bit(V4L2_FL_USE_FH_PRIO, &solo_enc->vfd->flags);
video_set_drvdata(solo_enc->vfd, solo_enc);
ret = video_register_device(solo_enc->vfd, VFL_TYPE_GRABBER, nr);
if (ret < 0)
@@ -1381,6 +1400,7 @@ int solo_enc_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
if (i != solo_dev->nr_chans) {
int ret = PTR_ERR(solo_dev->v4l2_enc[i]);
+
while (i--)
solo_enc_free(solo_dev->v4l2_enc[i]);
pci_free_consistent(solo_dev->pdev, solo_dev->vh_size,
diff --git a/drivers/staging/media/solo6x10/solo6x10-v4l2.c b/drivers/staging/media/solo6x10/solo6x10-v4l2.c
index 5d0100eb38e6..63ae8a61f603 100644
--- a/drivers/staging/media/solo6x10/solo6x10-v4l2.c
+++ b/drivers/staging/media/solo6x10/solo6x10-v4l2.c
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include <linux/kernel.h>
@@ -98,6 +94,7 @@ static int solo_v4l2_ch_ext_4up(struct solo_dev *solo_dev, u8 idx, int on)
if (!on) {
u8 i;
+
for (i = ch; i < ch + 4; i++)
solo_win_setup(solo_dev, i, solo_dev->video_hsize,
solo_vlines(solo_dev),
@@ -206,6 +203,7 @@ static void solo_fillbuf(struct solo_dev *solo_dev,
if (erase_off(solo_dev)) {
void *p = vb2_plane_vaddr(vb, 0);
int image_size = solo_image_size(solo_dev);
+
for (i = 0; i < image_size; i += 2) {
((u8 *)p)[i] = 0x80;
((u8 *)p)[i + 1] = 0x00;
@@ -275,6 +273,7 @@ static int solo_thread(void *data)
for (;;) {
long timeout = schedule_timeout_interruptible(HZ);
+
if (timeout == -ERESTARTSYS || kthread_should_stop())
break;
solo_thread_try(solo_dev);
@@ -414,6 +413,7 @@ static int solo_enum_input(struct file *file, void *priv,
if (input->index >= solo_dev->nr_chans) {
int ret = solo_enum_ext_input(solo_dev, input);
+
if (ret < 0)
return ret;
} else {
@@ -666,7 +666,6 @@ int solo_v4l2_init(struct solo_dev *solo_dev, unsigned nr)
goto fail;
}
solo_dev->vfd->ctrl_handler = &solo_dev->disp_hdl;
- set_bit(V4L2_FL_USE_FH_PRIO, &solo_dev->vfd->flags);
video_set_drvdata(solo_dev->vfd, solo_dev);
diff --git a/drivers/staging/media/solo6x10/solo6x10.h b/drivers/staging/media/solo6x10/solo6x10.h
index 8964f8be158e..c6154b00fcbd 100644
--- a/drivers/staging/media/solo6x10/solo6x10.h
+++ b/drivers/staging/media/solo6x10/solo6x10.h
@@ -16,10 +16,6 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#ifndef __SOLO6X10_H
@@ -96,14 +92,7 @@
#define SOLO_DEFAULT_QP 3
-#ifndef V4L2_BUF_FLAG_MOTION_ON
-#define V4L2_BUF_FLAG_MOTION_ON 0x10000
-#define V4L2_BUF_FLAG_MOTION_DETECTED 0x20000
-#endif
-
#define SOLO_CID_CUSTOM_BASE (V4L2_CID_USER_BASE | 0xf000)
-#define V4L2_CID_MOTION_MODE (SOLO_CID_CUSTOM_BASE+0)
-#define V4L2_CID_MOTION_THRESHOLD (SOLO_CID_CUSTOM_BASE+1)
#define V4L2_CID_MOTION_TRACE (SOLO_CID_CUSTOM_BASE+2)
#define V4L2_CID_OSD_TEXT (SOLO_CID_CUSTOM_BASE+3)
@@ -113,19 +102,10 @@
* effect, 44x30 samples are used for NTSC, and 44x36 for PAL.
* The 5th sample on the 10th row is (10*64)+5 = 645.
*
- * Using a 64x64 array will result in a problem on some architectures like
- * the powerpc where the size of the argument is limited to 13 bits.
- * Since both PAL and NTSC do not use the full table anyway I've chosen
- * to limit the array to 45x45 (45*16 = 720, which is the maximum PAL/NTSC
- * width).
+ * Internally it is stored as a 45x45 array (45*16 = 720, which is the
+ * maximum PAL/NTSC width).
*/
#define SOLO_MOTION_SZ (45)
-struct solo_motion_thresholds {
- __u16 thresholds[SOLO_MOTION_SZ][SOLO_MOTION_SZ];
-};
-
-#define SOLO_IOC_G_MOTION_THRESHOLDS _IOR('V', BASE_VIDIOC_PRIVATE+0, struct solo_motion_thresholds)
-#define SOLO_IOC_S_MOTION_THRESHOLDS _IOW('V', BASE_VIDIOC_PRIVATE+1, struct solo_motion_thresholds)
enum SOLO_I2C_STATE {
IIC_STATE_IDLE,
@@ -168,6 +148,7 @@ struct solo_enc_dev {
struct solo_dev *solo_dev;
/* V4L2 Items */
struct v4l2_ctrl_handler hdl;
+ struct v4l2_ctrl *md_thresholds;
struct video_device *vfd;
/* General accounting */
struct mutex lock;
@@ -176,9 +157,10 @@ struct solo_enc_dev {
u8 mode, gop, qp, interlaced, interval;
u8 bw_weight;
u16 motion_thresh;
- struct solo_motion_thresholds motion_thresholds;
bool motion_global;
bool motion_enabled;
+ bool motion_last_state;
+ u8 frames_since_last_motion;
u16 width;
u16 height;
@@ -404,7 +386,7 @@ void solo_update_mode(struct solo_enc_dev *solo_enc);
/* Set the threshold for motion detection */
int solo_set_motion_threshold(struct solo_dev *solo_dev, u8 ch, u16 val);
int solo_set_motion_block(struct solo_dev *solo_dev, u8 ch,
- const struct solo_motion_thresholds *thresholds);
+ const u16 *thresholds);
#define SOLO_DEF_MOT_THRESH 0x0300
/* Write text on OSD */
diff --git a/include/media/v4l2-ctrls.h b/include/media/v4l2-ctrls.h
index 16f7f2606516..8c4edd69fa4b 100644
--- a/include/media/v4l2-ctrls.h
+++ b/include/media/v4l2-ctrls.h
@@ -36,6 +36,23 @@ struct v4l2_subscribed_event;
struct v4l2_fh;
struct poll_table_struct;
+/** union v4l2_ctrl_ptr - A pointer to a control value.
+ * @p_s32: Pointer to a 32-bit signed value.
+ * @p_s64: Pointer to a 64-bit signed value.
+ * @p_u8: Pointer to a 8-bit unsigned value.
+ * @p_u16: Pointer to a 16-bit unsigned value.
+ * @p_char: Pointer to a string.
+ * @p: Pointer to a compound value.
+ */
+union v4l2_ctrl_ptr {
+ s32 *p_s32;
+ s64 *p_s64;
+ u8 *p_u8;
+ u16 *p_u16;
+ char *p_char;
+ void *p;
+};
+
/** struct v4l2_ctrl_ops - The control operations that the driver has to provide.
* @g_volatile_ctrl: Get a new value for this control. Generally only relevant
* for volatile (and usually read-only) controls such as a control
@@ -54,6 +71,23 @@ struct v4l2_ctrl_ops {
int (*s_ctrl)(struct v4l2_ctrl *ctrl);
};
+/** struct v4l2_ctrl_type_ops - The control type operations that the driver has to provide.
+ * @equal: return true if both values are equal.
+ * @init: initialize the value.
+ * @log: log the value.
+ * @validate: validate the value. Return 0 on success and a negative value otherwise.
+ */
+struct v4l2_ctrl_type_ops {
+ bool (*equal)(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr1,
+ union v4l2_ctrl_ptr ptr2);
+ void (*init)(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr);
+ void (*log)(const struct v4l2_ctrl *ctrl);
+ int (*validate)(const struct v4l2_ctrl *ctrl, u32 idx,
+ union v4l2_ctrl_ptr ptr);
+};
+
typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
/** struct v4l2_ctrl - The control structure.
@@ -66,6 +100,8 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* @is_new: Set when the user specified a new value for this control. It
* is also set when called from v4l2_ctrl_handler_setup. Drivers
* should never set this flag.
+ * @has_changed: Set when the current value differs from the new value. Drivers
+ * should never use this flag.
* @is_private: If set, then this control is private to its handler and it
* will not be added to any other handlers. Drivers can set
* this flag.
@@ -73,6 +109,13 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* members are in 'automatic' mode or 'manual' mode. This is
* used for autogain/gain type clusters. Drivers should never
* set this flag directly.
+ * @is_int: If set, then this control has a simple integer value (i.e. it
+ * uses ctrl->val).
+ * @is_string: If set, then this control has type V4L2_CTRL_TYPE_STRING.
+ * @is_ptr: If set, then this control is an array and/or has type >= V4L2_CTRL_COMPOUND_TYPES
+ * and/or has type V4L2_CTRL_TYPE_STRING. In other words, struct
+ * v4l2_ext_control uses field p to point to the data.
+ * @is_array: If set, then this control contains an N-dimensional array.
* @has_volatiles: If set, then one or more members of the cluster are volatile.
* Drivers should never touch this flag.
* @call_notify: If set, then call the handler's notify function whenever the
@@ -83,6 +126,7 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* value, then the whole cluster is in manual mode. Drivers should
* never set this flag directly.
* @ops: The control ops.
+ * @type_ops: The control type ops.
* @id: The control ID.
* @name: The control name.
* @type: The control type.
@@ -90,6 +134,10 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* @maximum: The control's maximum value.
* @default_value: The control's default value.
* @step: The control's step value for non-menu controls.
+ * @elems: The number of elements in the N-dimensional array.
+ * @elem_size: The size in bytes of the control.
+ * @dims: The size of each dimension.
+ * @nr_of_dims:The number of dimensions in @dims.
* @menu_skip_mask: The control's skip mask for menu controls. This makes it
* easy to skip menu items that are not valid. If bit X is set,
* then menu item X is skipped. Of course, this only works for
@@ -104,7 +152,6 @@ typedef void (*v4l2_ctrl_notify_fnc)(struct v4l2_ctrl *ctrl, void *priv);
* @cur: The control's current value.
* @val: The control's new s32 value.
* @val64: The control's new s64 value.
- * @string: The control's new string value.
* @priv: The control's private pointer. For use by the driver. It is
* untouched by the control framework. Note that this pointer is
* not freed when the control is deleted. Should this be needed
@@ -121,37 +168,44 @@ struct v4l2_ctrl {
unsigned int done:1;
unsigned int is_new:1;
+ unsigned int has_changed:1;
unsigned int is_private:1;
unsigned int is_auto:1;
+ unsigned int is_int:1;
+ unsigned int is_string:1;
+ unsigned int is_ptr:1;
+ unsigned int is_array:1;
unsigned int has_volatiles:1;
unsigned int call_notify:1;
unsigned int manual_mode_value:8;
const struct v4l2_ctrl_ops *ops;
+ const struct v4l2_ctrl_type_ops *type_ops;
u32 id;
const char *name;
enum v4l2_ctrl_type type;
- s32 minimum, maximum, default_value;
+ s64 minimum, maximum, default_value;
+ u32 elems;
+ u32 elem_size;
+ u32 dims[V4L2_CTRL_MAX_DIMS];
+ u32 nr_of_dims;
union {
- u32 step;
- u32 menu_skip_mask;
+ u64 step;
+ u64 menu_skip_mask;
};
union {
const char * const *qmenu;
const s64 *qmenu_int;
};
unsigned long flags;
- union {
+ void *priv;
+ s32 val;
+ struct {
s32 val;
- s64 val64;
- char *string;
} cur;
- union {
- s32 val;
- s64 val64;
- char *string;
- };
- void *priv;
+
+ union v4l2_ctrl_ptr p_new;
+ union v4l2_ctrl_ptr p_cur;
};
/** struct v4l2_ctrl_ref - The control reference.
@@ -205,6 +259,7 @@ struct v4l2_ctrl_handler {
/** struct v4l2_ctrl_config - Control configuration structure.
* @ops: The control ops.
+ * @type_ops: The control type ops. Only needed for compound controls.
* @id: The control ID.
* @name: The control name.
* @type: The control type.
@@ -212,13 +267,15 @@ struct v4l2_ctrl_handler {
* @max: The control's maximum value.
* @step: The control's step value for non-menu controls.
* @def: The control's default value.
+ * @dims: The size of each dimension.
+ * @elem_size: The size in bytes of the control.
* @flags: The control's flags.
* @menu_skip_mask: The control's skip mask for menu controls. This makes it
* easy to skip menu items that are not valid. If bit X is set,
* then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
+ * menus with <= 64 menu items. There are no menus that come
* close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
+ * then this will have to be extended to a bit array.
* @qmenu: A const char * array for all menu items. Array entries that are
* empty strings ("") correspond to non-existing menu items (this
* is in addition to the menu_skip_mask above). The last entry
@@ -228,15 +285,18 @@ struct v4l2_ctrl_handler {
*/
struct v4l2_ctrl_config {
const struct v4l2_ctrl_ops *ops;
+ const struct v4l2_ctrl_type_ops *type_ops;
u32 id;
const char *name;
enum v4l2_ctrl_type type;
- s32 min;
- s32 max;
- u32 step;
- s32 def;
+ s64 min;
+ s64 max;
+ u64 step;
+ s64 def;
+ u32 dims[V4L2_CTRL_MAX_DIMS];
+ u32 elem_size;
u32 flags;
- u32 menu_skip_mask;
+ u64 menu_skip_mask;
const char * const *qmenu;
const s64 *qmenu_int;
unsigned int is_private:1;
@@ -257,7 +317,7 @@ struct v4l2_ctrl_config {
* control framework this function will no longer be exported.
*/
void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
- s32 *min, s32 *max, s32 *step, s32 *def, u32 *flags);
+ s64 *min, s64 *max, u64 *step, s64 *def, u32 *flags);
/** v4l2_ctrl_handler_init_class() - Initialize the control handler.
@@ -307,6 +367,24 @@ int v4l2_ctrl_handler_init_class(struct v4l2_ctrl_handler *hdl,
*/
void v4l2_ctrl_handler_free(struct v4l2_ctrl_handler *hdl);
+/** v4l2_ctrl_lock() - Helper function to lock the handler
+ * associated with the control.
+ * @ctrl: The control to lock.
+ */
+static inline void v4l2_ctrl_lock(struct v4l2_ctrl *ctrl)
+{
+ mutex_lock(ctrl->handler->lock);
+}
+
+/** v4l2_ctrl_unlock() - Helper function to unlock the handler
+ * associated with the control.
+ * @ctrl: The control to unlock.
+ */
+static inline void v4l2_ctrl_unlock(struct v4l2_ctrl *ctrl)
+{
+ mutex_unlock(ctrl->handler->lock);
+}
+
/** v4l2_ctrl_handler_setup() - Call the s_ctrl op for all controls belonging
* to the handler to initialize the hardware to the current control values.
* @hdl: The control handler.
@@ -362,7 +440,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_custom(struct v4l2_ctrl_handler *hdl,
*/
struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 min, s32 max, u32 step, s32 def);
+ u32 id, s64 min, s64 max, u64 step, s64 def);
/** v4l2_ctrl_new_std_menu() - Allocate and initialize a new standard V4L2 menu control.
* @hdl: The control handler.
@@ -372,9 +450,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
* @mask: The control's skip mask for menu controls. This makes it
* easy to skip menu items that are not valid. If bit X is set,
* then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
+ * menus with <= 64 menu items. There are no menus that come
* close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
+ * then this will have to be extended to a bit array.
* @def: The control's default value.
*
* Same as v4l2_ctrl_new_std(), but @min is set to 0 and the @mask value
@@ -384,7 +462,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std(struct v4l2_ctrl_handler *hdl,
*/
struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 mask, s32 def);
+ u32 id, u8 max, u64 mask, u8 def);
/** v4l2_ctrl_new_std_menu_items() - Create a new standard V4L2 menu control
* with driver specific menu.
@@ -395,9 +473,9 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
* @mask: The control's skip mask for menu controls. This makes it
* easy to skip menu items that are not valid. If bit X is set,
* then menu item X is skipped. Of course, this only works for
- * menus with <= 32 menu items. There are no menus that come
+ * menus with <= 64 menu items. There are no menus that come
* close to that number, so this is OK. Should we ever need more,
- * then this will have to be extended to a u64 or a bit array.
+ * then this will have to be extended to a bit array.
* @def: The control's default value.
* @qmenu: The new menu.
*
@@ -406,8 +484,8 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
*
*/
struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
- const struct v4l2_ctrl_ops *ops, u32 id, s32 max,
- s32 mask, s32 def, const char * const *qmenu);
+ const struct v4l2_ctrl_ops *ops, u32 id, u8 max,
+ u64 mask, u8 def, const char * const *qmenu);
/** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
* @hdl: The control handler.
@@ -424,7 +502,7 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu_items(struct v4l2_ctrl_handler *hdl,
*/
struct v4l2_ctrl *v4l2_ctrl_new_int_menu(struct v4l2_ctrl_handler *hdl,
const struct v4l2_ctrl_ops *ops,
- u32 id, s32 max, s32 def, const s64 *qmenu_int);
+ u32 id, u8 max, u8 def, const s64 *qmenu_int);
/** v4l2_ctrl_add_ctrl() - Add a control from another handler to this handler.
* @hdl: The control handler.
@@ -542,6 +620,11 @@ void v4l2_ctrl_activate(struct v4l2_ctrl *ctrl, bool active);
*/
void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
+
+/** __v4l2_ctrl_modify_range() - Unlocked variant of v4l2_ctrl_modify_range() */
+int __v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
+ s64 min, s64 max, u64 step, s64 def);
+
/** v4l2_ctrl_modify_range() - Update the range of a control.
* @ctrl: The control to update.
* @min: The control's minimum value.
@@ -559,25 +642,16 @@ void v4l2_ctrl_grab(struct v4l2_ctrl *ctrl, bool grabbed);
* This function assumes that the control handler is not locked and will
* take the lock itself.
*/
-int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
- s32 min, s32 max, u32 step, s32 def);
-
-/** v4l2_ctrl_lock() - Helper function to lock the handler
- * associated with the control.
- * @ctrl: The control to lock.
- */
-static inline void v4l2_ctrl_lock(struct v4l2_ctrl *ctrl)
+static inline int v4l2_ctrl_modify_range(struct v4l2_ctrl *ctrl,
+ s64 min, s64 max, u64 step, s64 def)
{
- mutex_lock(ctrl->handler->lock);
-}
+ int rval;
-/** v4l2_ctrl_unlock() - Helper function to unlock the handler
- * associated with the control.
- * @ctrl: The control to unlock.
- */
-static inline void v4l2_ctrl_unlock(struct v4l2_ctrl *ctrl)
-{
- mutex_unlock(ctrl->handler->lock);
+ v4l2_ctrl_lock(ctrl);
+ rval = __v4l2_ctrl_modify_range(ctrl, min, max, step, def);
+ v4l2_ctrl_unlock(ctrl);
+
+ return rval;
}
/** v4l2_ctrl_notify() - Function to set a notify callback for a control.
@@ -605,6 +679,8 @@ void v4l2_ctrl_notify(struct v4l2_ctrl *ctrl, v4l2_ctrl_notify_fnc notify, void
*/
s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
+/** __v4l2_ctrl_s_ctrl() - Unlocked variant of v4l2_ctrl_s_ctrl(). */
+int __v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
/** v4l2_ctrl_s_ctrl() - Helper function to set the control's value from within a driver.
* @ctrl: The control.
* @val: The new value.
@@ -615,7 +691,16 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
*
* This function is for integer type controls only.
*/
-int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
+static inline int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
+{
+ int rval;
+
+ v4l2_ctrl_lock(ctrl);
+ rval = __v4l2_ctrl_s_ctrl(ctrl, val);
+ v4l2_ctrl_unlock(ctrl);
+
+ return rval;
+}
/** v4l2_ctrl_g_ctrl_int64() - Helper function to get a 64-bit control's value from within a driver.
* @ctrl: The control.
@@ -628,6 +713,9 @@ int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
*/
s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl);
+/** __v4l2_ctrl_s_ctrl_int64() - Unlocked variant of v4l2_ctrl_s_ctrl_int64(). */
+int __v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val);
+
/** v4l2_ctrl_s_ctrl_int64() - Helper function to set a 64-bit control's value from within a driver.
* @ctrl: The control.
* @val: The new value.
@@ -638,7 +726,16 @@ s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl);
*
* This function is for 64-bit integer type controls only.
*/
-int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val);
+static inline int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
+{
+ int rval;
+
+ v4l2_ctrl_lock(ctrl);
+ rval = __v4l2_ctrl_s_ctrl_int64(ctrl, val);
+ v4l2_ctrl_unlock(ctrl);
+
+ return rval;
+}
/* Internal helper functions that deal with control events. */
extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
@@ -659,6 +756,7 @@ unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait);
/* Helpers for ioctl_ops. If hdl == NULL then they will all return -EINVAL. */
int v4l2_queryctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_queryctrl *qc);
+int v4l2_query_ext_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_query_ext_ctrl *qc);
int v4l2_querymenu(struct v4l2_ctrl_handler *hdl, struct v4l2_querymenu *qm);
int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *ctrl);
int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
diff --git a/include/media/v4l2-dev.h b/include/media/v4l2-dev.h
index eec6e460f649..eb76cfd47189 100644
--- a/include/media/v4l2-dev.h
+++ b/include/media/v4l2-dev.h
@@ -44,8 +44,6 @@ struct v4l2_ctrl_handler;
#define V4L2_FL_REGISTERED (0)
/* file->private_data points to struct v4l2_fh */
#define V4L2_FL_USES_V4L2_FH (1)
-/* Use the prio field of v4l2_fh for core priority checking */
-#define V4L2_FL_USE_FH_PRIO (2)
/* Priority helper functions */
diff --git a/include/media/v4l2-ioctl.h b/include/media/v4l2-ioctl.h
index 50cf7c110a70..53605f0f9903 100644
--- a/include/media/v4l2-ioctl.h
+++ b/include/media/v4l2-ioctl.h
@@ -158,6 +158,8 @@ struct v4l2_ioctl_ops {
/* Control handling */
int (*vidioc_queryctrl) (struct file *file, void *fh,
struct v4l2_queryctrl *a);
+ int (*vidioc_query_ext_ctrl) (struct file *file, void *fh,
+ struct v4l2_query_ext_ctrl *a);
int (*vidioc_g_ctrl) (struct file *file, void *fh,
struct v4l2_control *a);
int (*vidioc_s_ctrl) (struct file *file, void *fh,
diff --git a/include/media/videobuf2-core.h b/include/media/videobuf2-core.h
index 8fab6fa0dbfb..1a262aeb1741 100644
--- a/include/media/videobuf2-core.h
+++ b/include/media/videobuf2-core.h
@@ -375,6 +375,7 @@ struct v4l2_fh;
* @streaming: current streaming state
* @start_streaming_called: start_streaming() was called successfully and we
* started streaming.
+ * @error: a fatal error occurred on the queue
* @fileio: file io emulator internal data, used only if emulator is active
* @threadio: thread io internal data, used only if thread is active
*/
@@ -411,6 +412,7 @@ struct vb2_queue {
unsigned int streaming:1;
unsigned int start_streaming_called:1;
+ unsigned int error:1;
struct vb2_fileio_data *fileio;
struct vb2_threadio_data *threadio;
@@ -444,6 +446,7 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
int __must_check vb2_queue_init(struct vb2_queue *q);
void vb2_queue_release(struct vb2_queue *q);
+void vb2_queue_error(struct vb2_queue *q);
int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b);
int vb2_expbuf(struct vb2_queue *q, struct v4l2_exportbuffer *eb);
diff --git a/include/uapi/linux/v4l2-controls.h b/include/uapi/linux/v4l2-controls.h
index 2ac5597f3ee1..db526d1c8309 100644
--- a/include/uapi/linux/v4l2-controls.h
+++ b/include/uapi/linux/v4l2-controls.h
@@ -61,6 +61,7 @@
#define V4L2_CTRL_CLASS_DV 0x00a00000 /* Digital Video controls */
#define V4L2_CTRL_CLASS_FM_RX 0x00a10000 /* FM Receiver controls */
#define V4L2_CTRL_CLASS_RF_TUNER 0x00a20000 /* RF tuner controls */
+#define V4L2_CTRL_CLASS_DETECT 0x00a30000 /* Detection controls */
/* User-class control IDs */
@@ -914,4 +915,20 @@ enum v4l2_deemphasis {
#define V4L2_CID_RF_TUNER_IF_GAIN (V4L2_CID_RF_TUNER_CLASS_BASE + 62)
#define V4L2_CID_RF_TUNER_PLL_LOCK (V4L2_CID_RF_TUNER_CLASS_BASE + 91)
+
+/* Detection-class control IDs defined by V4L2 */
+#define V4L2_CID_DETECT_CLASS_BASE (V4L2_CTRL_CLASS_DETECT | 0x900)
+#define V4L2_CID_DETECT_CLASS (V4L2_CTRL_CLASS_DETECT | 1)
+
+#define V4L2_CID_DETECT_MD_MODE (V4L2_CID_DETECT_CLASS_BASE + 1)
+enum v4l2_detect_md_mode {
+ V4L2_DETECT_MD_MODE_DISABLED = 0,
+ V4L2_DETECT_MD_MODE_GLOBAL = 1,
+ V4L2_DETECT_MD_MODE_THRESHOLD_GRID = 2,
+ V4L2_DETECT_MD_MODE_REGION_GRID = 3,
+};
+#define V4L2_CID_DETECT_MD_GLOBAL_THRESHOLD (V4L2_CID_DETECT_CLASS_BASE + 2)
+#define V4L2_CID_DETECT_MD_THRESHOLD_GRID (V4L2_CID_DETECT_CLASS_BASE + 3)
+#define V4L2_CID_DETECT_MD_REGION_GRID (V4L2_CID_DETECT_CLASS_BASE + 4)
+
#endif
diff --git a/include/uapi/linux/videodev2.h b/include/uapi/linux/videodev2.h
index 168ff507bf75..5fd42027877a 100644
--- a/include/uapi/linux/videodev2.h
+++ b/include/uapi/linux/videodev2.h
@@ -124,6 +124,10 @@ enum v4l2_field {
(field) == V4L2_FIELD_INTERLACED_BT ||\
(field) == V4L2_FIELD_SEQ_TB ||\
(field) == V4L2_FIELD_SEQ_BT)
+#define V4L2_FIELD_HAS_T_OR_B(field) \
+ ((field) == V4L2_FIELD_BOTTOM ||\
+ (field) == V4L2_FIELD_TOP ||\
+ (field) == V4L2_FIELD_ALTERNATE)
enum v4l2_buf_type {
V4L2_BUF_TYPE_VIDEO_CAPTURE = 1,
@@ -268,6 +272,7 @@ struct v4l2_capability {
#define V4L2_CAP_MODULATOR 0x00080000 /* has a modulator */
#define V4L2_CAP_SDR_CAPTURE 0x00100000 /* Is a SDR capture device */
+#define V4L2_CAP_EXT_PIX_FORMAT 0x00200000 /* Supports the extended pixel format */
#define V4L2_CAP_READWRITE 0x01000000 /* read/write systemcalls */
#define V4L2_CAP_ASYNCIO 0x02000000 /* async I/O */
@@ -287,6 +292,7 @@ struct v4l2_pix_format {
__u32 sizeimage;
__u32 colorspace; /* enum v4l2_colorspace */
__u32 priv; /* private data, depends on pixelformat */
+ __u32 flags; /* format flags (V4L2_PIX_FMT_FLAG_*) */
};
/* Pixel format FOURCC depth Description */
@@ -294,7 +300,11 @@ struct v4l2_pix_format {
/* RGB formats */
#define V4L2_PIX_FMT_RGB332 v4l2_fourcc('R', 'G', 'B', '1') /* 8 RGB-3-3-2 */
#define V4L2_PIX_FMT_RGB444 v4l2_fourcc('R', '4', '4', '4') /* 16 xxxxrrrr ggggbbbb */
+#define V4L2_PIX_FMT_ARGB444 v4l2_fourcc('A', 'R', '1', '2') /* 16 aaaarrrr ggggbbbb */
+#define V4L2_PIX_FMT_XRGB444 v4l2_fourcc('X', 'R', '1', '2') /* 16 xxxxrrrr ggggbbbb */
#define V4L2_PIX_FMT_RGB555 v4l2_fourcc('R', 'G', 'B', 'O') /* 16 RGB-5-5-5 */
+#define V4L2_PIX_FMT_ARGB555 v4l2_fourcc('A', 'R', '1', '5') /* 16 ARGB-1-5-5-5 */
+#define V4L2_PIX_FMT_XRGB555 v4l2_fourcc('X', 'R', '1', '5') /* 16 XRGB-1-5-5-5 */
#define V4L2_PIX_FMT_RGB565 v4l2_fourcc('R', 'G', 'B', 'P') /* 16 RGB-5-6-5 */
#define V4L2_PIX_FMT_RGB555X v4l2_fourcc('R', 'G', 'B', 'Q') /* 16 RGB-5-5-5 BE */
#define V4L2_PIX_FMT_RGB565X v4l2_fourcc('R', 'G', 'B', 'R') /* 16 RGB-5-6-5 BE */
@@ -302,7 +312,11 @@ struct v4l2_pix_format {
#define V4L2_PIX_FMT_BGR24 v4l2_fourcc('B', 'G', 'R', '3') /* 24 BGR-8-8-8 */
#define V4L2_PIX_FMT_RGB24 v4l2_fourcc('R', 'G', 'B', '3') /* 24 RGB-8-8-8 */
#define V4L2_PIX_FMT_BGR32 v4l2_fourcc('B', 'G', 'R', '4') /* 32 BGR-8-8-8-8 */
+#define V4L2_PIX_FMT_ABGR32 v4l2_fourcc('A', 'R', '2', '4') /* 32 BGRA-8-8-8-8 */
+#define V4L2_PIX_FMT_XBGR32 v4l2_fourcc('X', 'R', '2', '4') /* 32 BGRX-8-8-8-8 */
#define V4L2_PIX_FMT_RGB32 v4l2_fourcc('R', 'G', 'B', '4') /* 32 RGB-8-8-8-8 */
+#define V4L2_PIX_FMT_ARGB32 v4l2_fourcc('B', 'A', '2', '4') /* 32 ARGB-8-8-8-8 */
+#define V4L2_PIX_FMT_XRGB32 v4l2_fourcc('B', 'X', '2', '4') /* 32 XRGB-8-8-8-8 */
/* Grey formats */
#define V4L2_PIX_FMT_GREY v4l2_fourcc('G', 'R', 'E', 'Y') /* 8 Greyscale */
@@ -439,6 +453,15 @@ struct v4l2_pix_format {
/* SDR formats - used only for Software Defined Radio devices */
#define V4L2_SDR_FMT_CU8 v4l2_fourcc('C', 'U', '0', '8') /* IQ u8 */
#define V4L2_SDR_FMT_CU16LE v4l2_fourcc('C', 'U', '1', '6') /* IQ u16le */
+#define V4L2_SDR_FMT_CS8 v4l2_fourcc('C', 'S', '0', '8') /* complex s8 */
+#define V4L2_SDR_FMT_CS14LE v4l2_fourcc('C', 'S', '1', '4') /* complex s14le */
+#define V4L2_SDR_FMT_RU12LE v4l2_fourcc('R', 'U', '1', '2') /* real u12le */
+
+/* priv field value to indicates that subsequent fields are valid. */
+#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe
+
+/* Flags */
+#define V4L2_PIX_FMT_FLAG_PREMUL_ALPHA 0x00000001
/*
* F O R M A T E N U M E R A T I O N
@@ -744,7 +767,16 @@ struct v4l2_framebuffer {
/* FIXME: in theory we should pass something like PCI device + memory
* region + offset instead of some physical address */
void *base;
- struct v4l2_pix_format fmt;
+ struct {
+ __u32 width;
+ __u32 height;
+ __u32 pixelformat;
+ __u32 field; /* enum v4l2_field */
+ __u32 bytesperline; /* for padding, zero if unused */
+ __u32 sizeimage;
+ __u32 colorspace; /* enum v4l2_colorspace */
+ __u32 priv; /* reserved field, set to 0 */
+ } fmt;
};
/* Flags for the 'capability' field. Read only */
#define V4L2_FBUF_CAP_EXTERNOVERLAY 0x0001
@@ -1254,6 +1286,9 @@ struct v4l2_ext_control {
__s32 value;
__s64 value64;
char *string;
+ __u8 *p_u8;
+ __u16 *p_u16;
+ void *ptr;
};
} __attribute__ ((packed));
@@ -1268,6 +1303,7 @@ struct v4l2_ext_controls {
#define V4L2_CTRL_ID_MASK (0x0fffffff)
#define V4L2_CTRL_ID2CLASS(id) ((id) & 0x0fff0000UL)
#define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
+#define V4L2_CTRL_MAX_DIMS (4)
enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_INTEGER = 1,
@@ -1278,7 +1314,12 @@ enum v4l2_ctrl_type {
V4L2_CTRL_TYPE_CTRL_CLASS = 6,
V4L2_CTRL_TYPE_STRING = 7,
V4L2_CTRL_TYPE_BITMASK = 8,
- V4L2_CTRL_TYPE_INTEGER_MENU = 9,
+ V4L2_CTRL_TYPE_INTEGER_MENU = 9,
+
+ /* Compound types are >= 0x0100 */
+ V4L2_CTRL_COMPOUND_TYPES = 0x0100,
+ V4L2_CTRL_TYPE_U8 = 0x0100,
+ V4L2_CTRL_TYPE_U16 = 0x0101,
};
/* Used in the VIDIOC_QUERYCTRL ioctl for querying controls */
@@ -1294,6 +1335,23 @@ struct v4l2_queryctrl {
__u32 reserved[2];
};
+/* Used in the VIDIOC_QUERY_EXT_CTRL ioctl for querying extended controls */
+struct v4l2_query_ext_ctrl {
+ __u32 id;
+ __u32 type;
+ char name[32];
+ __s64 minimum;
+ __s64 maximum;
+ __u64 step;
+ __s64 default_value;
+ __u32 flags;
+ __u32 elem_size;
+ __u32 elems;
+ __u32 nr_of_dims;
+ __u32 dims[V4L2_CTRL_MAX_DIMS];
+ __u32 reserved[32];
+};
+
/* Used in the VIDIOC_QUERYMENU ioctl for querying menu items */
struct v4l2_querymenu {
__u32 id;
@@ -1314,9 +1372,11 @@ struct v4l2_querymenu {
#define V4L2_CTRL_FLAG_SLIDER 0x0020
#define V4L2_CTRL_FLAG_WRITE_ONLY 0x0040
#define V4L2_CTRL_FLAG_VOLATILE 0x0080
+#define V4L2_CTRL_FLAG_HAS_PAYLOAD 0x0100
-/* Query flag, to be ORed with the control ID */
+/* Query flags, to be ORed with the control ID */
#define V4L2_CTRL_FLAG_NEXT_CTRL 0x80000000
+#define V4L2_CTRL_FLAG_NEXT_COMPOUND 0x40000000
/* User-class control IDs defined by V4L2 */
#define V4L2_CID_MAX_CTRLS 1024
@@ -1582,6 +1642,12 @@ struct v4l2_vbi_format {
#define V4L2_VBI_UNSYNC (1 << 0)
#define V4L2_VBI_INTERLACED (1 << 1)
+/* ITU-R start lines for each field */
+#define V4L2_VBI_ITU_525_F1_START (1)
+#define V4L2_VBI_ITU_525_F2_START (264)
+#define V4L2_VBI_ITU_625_F1_START (1)
+#define V4L2_VBI_ITU_625_F2_START (314)
+
/* Sliced VBI
*
* This implements is a proposal V4L2 API to allow SLICED VBI
@@ -1705,6 +1771,7 @@ struct v4l2_plane_pix_format {
* @colorspace: enum v4l2_colorspace; supplemental to pixelformat
* @plane_fmt: per-plane information
* @num_planes: number of planes for this format
+ * @flags: format flags (V4L2_PIX_FMT_FLAG_*)
*/
struct v4l2_pix_format_mplane {
__u32 width;
@@ -1715,16 +1782,19 @@ struct v4l2_pix_format_mplane {
struct v4l2_plane_pix_format plane_fmt[VIDEO_MAX_PLANES];
__u8 num_planes;
- __u8 reserved[11];
+ __u8 flags;
+ __u8 reserved[10];
} __attribute__ ((packed));
/**
* struct v4l2_sdr_format - SDR format definition
* @pixelformat: little endian four character code (fourcc)
+ * @buffersize: maximum size in bytes required for data
*/
struct v4l2_sdr_format {
__u32 pixelformat;
- __u8 reserved[28];
+ __u32 buffersize;
+ __u8 reserved[24];
} __attribute__ ((packed));
/**
@@ -1771,6 +1841,7 @@ struct v4l2_streamparm {
#define V4L2_EVENT_CTRL 3
#define V4L2_EVENT_FRAME_SYNC 4
#define V4L2_EVENT_SOURCE_CHANGE 5
+#define V4L2_EVENT_MOTION_DET 6
#define V4L2_EVENT_PRIVATE_START 0x08000000
/* Payload for V4L2_EVENT_VSYNC */
@@ -1808,6 +1879,21 @@ struct v4l2_event_src_change {
__u32 changes;
};
+#define V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ (1 << 0)
+
+/**
+ * struct v4l2_event_motion_det - motion detection event
+ * @flags: if V4L2_EVENT_MD_FL_HAVE_FRAME_SEQ is set, then the
+ * frame_sequence field is valid.
+ * @frame_sequence: the frame sequence number associated with this event.
+ * @region_mask: which regions detected motion.
+ */
+struct v4l2_event_motion_det {
+ __u32 flags;
+ __u32 frame_sequence;
+ __u32 region_mask;
+};
+
struct v4l2_event {
__u32 type;
union {
@@ -1815,6 +1901,7 @@ struct v4l2_event {
struct v4l2_event_ctrl ctrl;
struct v4l2_event_frame_sync frame_sync;
struct v4l2_event_src_change src_change;
+ struct v4l2_event_motion_det motion_det;
__u8 data[64];
} u;
__u32 pending;
@@ -2005,6 +2092,8 @@ struct v4l2_create_buffers {
Never use these in applications! */
#define VIDIOC_DBG_G_CHIP_INFO _IOWR('V', 102, struct v4l2_dbg_chip_info)
+#define VIDIOC_QUERY_EXT_CTRL _IOWR('V', 103, struct v4l2_query_ext_ctrl)
+
/* Reminder: when adding new ioctls please add support for them to
drivers/media/video/v4l2-compat-ioctl32.c as well! */