]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge branch 'samsung_platform_data' into staging/for_v3.7
authorMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 6 Oct 2012 01:32:05 +0000 (22:32 -0300)
committerMauro Carvalho Chehab <mchehab@redhat.com>
Sat, 6 Oct 2012 01:32:05 +0000 (22:32 -0300)
* samsung_platform_data:
  ARM: samsung: move platform_data definitions
  ARM: orion: move platform_data definitions
  ARM: nomadik: move platform_data definitions
  ARM: w90x900: move platform_data definitions
  ARM: vt8500: move platform_data definitions
  ARM: tegra: move sdhci platform_data definition
  ARM: sa1100: move platform_data definitions
  ARM: pxa: move platform_data definitions
  ARM: netx: move platform_data definitions
  ARM: msm: move platform_data definitions
  ARM: imx: move platform_data definitions
  ARM: ep93xx: move platform_data definitions
  ARM: davinci: move platform_data definitions
  ARM: at91: move platform_data definitions

2636 files changed:
Documentation/ABI/testing/sysfs-bus-pci
Documentation/DocBook/media/Makefile
Documentation/DocBook/media/dvb/audio.xml
Documentation/DocBook/media/dvb/ca.xml
Documentation/DocBook/media/dvb/demux.xml
Documentation/DocBook/media/dvb/dvbapi.xml
Documentation/DocBook/media/dvb/dvbproperty.xml
Documentation/DocBook/media/dvb/frontend.xml
Documentation/DocBook/media/dvb/intro.xml
Documentation/DocBook/media/dvb/kdapi.xml
Documentation/DocBook/media/dvb/net.xml
Documentation/DocBook/media/dvb/video.xml
Documentation/DocBook/media/v4l/biblio.xml
Documentation/DocBook/media/v4l/common.xml
Documentation/DocBook/media/v4l/compat.xml
Documentation/DocBook/media/v4l/controls.xml
Documentation/DocBook/media/v4l/dev-osd.xml
Documentation/DocBook/media/v4l/dev-rds.xml
Documentation/DocBook/media/v4l/dev-subdev.xml
Documentation/DocBook/media/v4l/gen-errors.xml
Documentation/DocBook/media/v4l/io.xml
Documentation/DocBook/media/v4l/pixfmt-srggb10dpcm8.xml
Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/pixfmt.xml
Documentation/DocBook/media/v4l/selection-api.xml
Documentation/DocBook/media/v4l/subdev-formats.xml
Documentation/DocBook/media/v4l/v4l2.xml
Documentation/DocBook/media/v4l/vidioc-cropcap.xml
Documentation/DocBook/media/v4l/vidioc-decoder-cmd.xml
Documentation/DocBook/media/v4l/vidioc-encoder-cmd.xml
Documentation/DocBook/media/v4l/vidioc-enum-dv-presets.xml
Documentation/DocBook/media/v4l/vidioc-enum-dv-timings.xml
Documentation/DocBook/media/v4l/vidioc-enum-fmt.xml
Documentation/DocBook/media/v4l/vidioc-enum-framesizes.xml
Documentation/DocBook/media/v4l/vidioc-enuminput.xml
Documentation/DocBook/media/v4l/vidioc-enumoutput.xml
Documentation/DocBook/media/v4l/vidioc-enumstd.xml
Documentation/DocBook/media/v4l/vidioc-g-crop.xml
Documentation/DocBook/media/v4l/vidioc-g-dv-preset.xml
Documentation/DocBook/media/v4l/vidioc-g-dv-timings.xml
Documentation/DocBook/media/v4l/vidioc-g-enc-index.xml
Documentation/DocBook/media/v4l/vidioc-g-fmt.xml
Documentation/DocBook/media/v4l/vidioc-g-parm.xml
Documentation/DocBook/media/v4l/vidioc-g-selection.xml
Documentation/DocBook/media/v4l/vidioc-g-std.xml
Documentation/DocBook/media/v4l/vidioc-g-tuner.xml
Documentation/DocBook/media/v4l/vidioc-qbuf.xml
Documentation/DocBook/media/v4l/vidioc-query-dv-preset.xml
Documentation/DocBook/media/v4l/vidioc-query-dv-timings.xml
Documentation/DocBook/media/v4l/vidioc-querybuf.xml
Documentation/DocBook/media/v4l/vidioc-querycap.xml
Documentation/DocBook/media/v4l/vidioc-querystd.xml
Documentation/DocBook/media/v4l/vidioc-reqbufs.xml
Documentation/DocBook/media/v4l/vidioc-s-hw-freq-seek.xml
Documentation/DocBook/media/v4l/vidioc-streamon.xml
Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml [new file with mode: 0644]
Documentation/DocBook/media/v4l/vidioc-subdev-g-selection.xml
Documentation/DocBook/media_api.tmpl
Documentation/block/00-INDEX
Documentation/block/cfq-iosched.txt
Documentation/block/queue-sysfs.txt
Documentation/devicetree/bindings/mmc/fsl-imx-esdhc.txt
Documentation/dvb/README.dvb-usb
Documentation/dvb/get_dvb_firmware
Documentation/feature-removal-schedule.txt
Documentation/i2c/busses/i2c-i801
Documentation/ioctl/ioctl-number.txt
Documentation/vfio.txt
Documentation/video4linux/CARDLIST.cx23885
Documentation/video4linux/CQcam.txt
Documentation/video4linux/README.davinci-vpbe
Documentation/video4linux/fimc.txt
Documentation/video4linux/omap3isp.txt
Documentation/video4linux/v4l2-controls.txt
Documentation/video4linux/v4l2-framework.txt
Documentation/video4linux/videobuf
Documentation/watchdog/src/watchdog-test.c
MAINTAINERS
Makefile
arch/arm/Kconfig
arch/arm/Kconfig.debug
arch/arm/Makefile
arch/arm/boot/compressed/head.S
arch/arm/boot/dts/am33xx.dtsi
arch/arm/boot/dts/at91sam9260.dtsi
arch/arm/boot/dts/at91sam9263.dtsi
arch/arm/boot/dts/at91sam9g25ek.dts
arch/arm/boot/dts/at91sam9g45.dtsi
arch/arm/boot/dts/at91sam9n12.dtsi
arch/arm/boot/dts/at91sam9x5.dtsi
arch/arm/boot/dts/imx51-babbage.dts
arch/arm/boot/dts/kirkwood-iconnect.dts
arch/arm/boot/dts/twl6030.dtsi
arch/arm/configs/armadillo800eva_defconfig
arch/arm/configs/u8500_defconfig
arch/arm/include/asm/assembler.h
arch/arm/include/asm/dma-mapping.h
arch/arm/include/asm/memory.h
arch/arm/include/asm/tlb.h
arch/arm/include/asm/uaccess.h
arch/arm/include/asm/unistd.h
arch/arm/kernel/calls.S
arch/arm/kernel/hw_breakpoint.c
arch/arm/kernel/smp_twd.c
arch/arm/kernel/traps.c
arch/arm/lib/delay.c
arch/arm/lib/getuser.S
arch/arm/lib/putuser.S
arch/arm/mach-at91/at91rm9200_time.c
arch/arm/mach-at91/at91sam9260_devices.c
arch/arm/mach-at91/at91sam9261_devices.c
arch/arm/mach-at91/at91sam9263_devices.c
arch/arm/mach-at91/at91sam9g45_devices.c
arch/arm/mach-at91/at91sam9rl_devices.c
arch/arm/mach-at91/clock.c
arch/arm/mach-davinci/Kconfig
arch/arm/mach-davinci/board-da850-evm.c
arch/arm/mach-davinci/board-dm644x-evm.c
arch/arm/mach-davinci/board-dm646x-evm.c
arch/arm/mach-davinci/da850.c
arch/arm/mach-davinci/dm644x.c
arch/arm/mach-davinci/include/mach/da8xx.h
arch/arm/mach-davinci/include/mach/mux.h
arch/arm/mach-davinci/include/mach/psc.h
arch/arm/mach-dove/common.c
arch/arm/mach-exynos/mach-nuri.c
arch/arm/mach-exynos/mach-origen.c
arch/arm/mach-exynos/mach-smdkv310.c
arch/arm/mach-exynos/mach-universal_c210.c
arch/arm/mach-gemini/irq.c
arch/arm/mach-imx/Makefile
arch/arm/mach-imx/clk-imx25.c
arch/arm/mach-imx/clk-imx27.c
arch/arm/mach-imx/clk-imx35.c
arch/arm/mach-imx/clk-imx6q.c
arch/arm/mach-imx/devices-imx27.h
arch/arm/mach-imx/headsmp.S [moved from arch/arm/mach-imx/head-v7.S with 100% similarity]
arch/arm/mach-imx/hotplug.c
arch/arm/mach-imx/mach-armadillo5x0.c
arch/arm/mach-imx/mach-imx27_visstrim_m10.c
arch/arm/mach-imx/mach-imx6q.c
arch/arm/mach-kirkwood/Makefile.boot
arch/arm/mach-kirkwood/common.c
arch/arm/mach-kirkwood/db88f6281-bp-setup.c
arch/arm/mach-mmp/sram.c
arch/arm/mach-mv78xx0/addr-map.c
arch/arm/mach-mv78xx0/common.c
arch/arm/mach-mxs/mach-mxs.c
arch/arm/mach-omap2/Kconfig
arch/arm/mach-omap2/Makefile
arch/arm/mach-omap2/board-igep0020.c
arch/arm/mach-omap2/board-omap3evm.c
arch/arm/mach-omap2/board-rx51-peripherals.c
arch/arm/mach-omap2/clock33xx_data.c
arch/arm/mach-omap2/clockdomain2xxx_3xxx.c
arch/arm/mach-omap2/cm-regbits-34xx.h
arch/arm/mach-omap2/common-board-devices.c
arch/arm/mach-omap2/common-board-devices.h
arch/arm/mach-omap2/cpuidle44xx.c
arch/arm/mach-omap2/mux.h
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-omap2/omap_hwmod.c
arch/arm/mach-omap2/omap_hwmod_3xxx_data.c
arch/arm/mach-omap2/omap_hwmod_44xx_data.c
arch/arm/mach-omap2/opp4xxx_data.c
arch/arm/mach-omap2/pm34xx.c
arch/arm/mach-omap2/sleep44xx.S
arch/arm/mach-omap2/timer.c
arch/arm/mach-omap2/twl-common.c
arch/arm/mach-orion5x/common.c
arch/arm/mach-s3c24xx/include/mach/dma.h
arch/arm/mach-shmobile/board-armadillo800eva.c
arch/arm/mach-shmobile/board-kzm9g.c
arch/arm/mach-shmobile/board-mackerel.c
arch/arm/mach-shmobile/board-marzen.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-ux500/Kconfig
arch/arm/mach-ux500/board-mop500-msp.c
arch/arm/mach-ux500/board-mop500.c
arch/arm/mm/context.c
arch/arm/mm/dma-mapping.c
arch/arm/mm/mm.h
arch/arm/mm/mmu.c
arch/arm/plat-mxc/devices/Kconfig
arch/arm/plat-mxc/devices/Makefile
arch/arm/plat-mxc/devices/platform-imx27-coda.c [new file with mode: 0644]
arch/arm/plat-mxc/include/mach/devices-common.h
arch/arm/plat-mxc/include/mach/mx25.h
arch/arm/plat-omap/dmtimer.c
arch/arm/plat-omap/include/plat/cpu.h
arch/arm/plat-omap/include/plat/multi.h
arch/arm/plat-omap/include/plat/uncompress.h
arch/arm/plat-omap/sram.c
arch/arm/plat-orion/common.c
arch/arm/plat-orion/include/plat/common.h
arch/arm/plat-s3c24xx/dma.c
arch/arm/plat-samsung/clock.c
arch/arm/plat-samsung/devs.c
arch/arm/plat-samsung/include/plat/hdmi.h [new file with mode: 0644]
arch/arm/plat-samsung/pm.c
arch/arm/plat-samsung/setup-mipiphy.c
arch/blackfin/Kconfig
arch/blackfin/Makefile
arch/blackfin/include/asm/smp.h
arch/blackfin/mach-common/smp.c
arch/c6x/include/asm/Kbuild
arch/c6x/include/asm/barrier.h [deleted file]
arch/m68k/platform/coldfire/clk.c
arch/mips/Kconfig
arch/mips/alchemy/board-mtx1.c
arch/mips/ath79/dev-usb.c
arch/mips/ath79/gpio.c
arch/mips/bcm63xx/dev-spi.c
arch/mips/cavium-octeon/octeon-irq.c
arch/mips/include/asm/mach-ath79/ar71xx_regs.h
arch/mips/include/asm/mach-ath79/cpu-feature-overrides.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_dev_spi.h
arch/mips/include/asm/mach-bcm63xx/bcm63xx_regs.h
arch/mips/include/asm/mach-cavium-octeon/irq.h
arch/mips/include/asm/module.h
arch/mips/include/asm/r4k-timer.h
arch/mips/kernel/module.c
arch/mips/kernel/smp-cmp.c
arch/mips/kernel/smp.c
arch/mips/kernel/sync-r4k.c
arch/mips/mm/gup.c
arch/mips/mti-malta/malta-int.c
arch/mips/mti-malta/malta-pci.c
arch/mips/mti-malta/malta-platform.c
arch/mips/pci/pci-ar724x.c
arch/parisc/include/asm/atomic.h
arch/parisc/kernel/process.c
arch/parisc/kernel/sys_parisc.c
arch/powerpc/boot/dts/fsl/p4080si-post.dtsi
arch/powerpc/configs/85xx/p1023rds_defconfig
arch/powerpc/configs/corenet32_smp_defconfig
arch/powerpc/configs/corenet64_smp_defconfig
arch/powerpc/configs/g5_defconfig
arch/powerpc/configs/mpc83xx_defconfig
arch/powerpc/configs/mpc85xx_defconfig
arch/powerpc/configs/mpc85xx_smp_defconfig
arch/powerpc/include/asm/cputable.h
arch/powerpc/include/asm/kvm_host.h
arch/powerpc/include/asm/kvm_ppc.h
arch/powerpc/include/asm/mpic_msgr.h
arch/powerpc/include/asm/processor.h
arch/powerpc/kernel/asm-offsets.c
arch/powerpc/kernel/dbell.c
arch/powerpc/kernel/dma-iommu.c
arch/powerpc/kernel/entry_64.S
arch/powerpc/kernel/exceptions-64s.S
arch/powerpc/kernel/hw_breakpoint.c
arch/powerpc/kernel/idle_power7.S
arch/powerpc/kernel/kgdb.c
arch/powerpc/kernel/process.c
arch/powerpc/kernel/smp.c
arch/powerpc/kernel/syscalls.c
arch/powerpc/kernel/sysfs.c
arch/powerpc/kernel/time.c
arch/powerpc/kernel/traps.c
arch/powerpc/kvm/book3s_32_mmu_host.c
arch/powerpc/kvm/book3s_64_mmu_host.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/e500_tlb.c
arch/powerpc/lib/code-patching.c
arch/powerpc/lib/copyuser_power7.S
arch/powerpc/lib/memcpy_power7.S
arch/powerpc/mm/mem.c
arch/powerpc/mm/numa.c
arch/powerpc/perf/core-book3s.c
arch/powerpc/platforms/powernv/smp.c
arch/powerpc/sysdev/fsl_pci.c
arch/powerpc/sysdev/mpic_msgr.c
arch/powerpc/sysdev/xics/icp-hv.c
arch/powerpc/xmon/xmon.c
arch/s390/include/asm/elf.h
arch/s390/include/asm/hugetlb.h
arch/s390/include/asm/posix_types.h
arch/s390/include/asm/smp.h
arch/s390/include/asm/tlbflush.h
arch/s390/kernel/setup.c
arch/s390/lib/uaccess_pt.c
arch/s390/oprofile/init.c
arch/sh/kernel/cpu/sh5/entry.S
arch/sh/kernel/entry-common.S
arch/sparc/kernel/module.c
arch/tile/include/gxio/iorpc_trio.h
arch/um/include/asm/processor-generic.h
arch/um/include/shared/common-offsets.h
arch/um/include/shared/user.h
arch/um/kernel/exec.c
arch/um/kernel/process.c
arch/um/kernel/signal.c
arch/um/kernel/syscall.c
arch/um/os-Linux/time.c
arch/um/scripts/Makefile.rules
arch/x86/Kconfig
arch/x86/Makefile
arch/x86/include/asm/spinlock.h
arch/x86/include/asm/xen/page.h
arch/x86/kernel/alternative.c
arch/x86/kernel/cpu/perf_event.h
arch/x86/kernel/cpu/perf_event_amd_ibs.c
arch/x86/kernel/cpu/perf_event_intel.c
arch/x86/kernel/cpu/perf_event_intel_ds.c
arch/x86/kernel/cpu/perf_event_intel_lbr.c
arch/x86/kernel/cpu/perf_event_intel_uncore.c
arch/x86/kernel/irq.c
arch/x86/kernel/microcode_amd.c
arch/x86/kernel/microcode_core.c
arch/x86/kvm/emulate.c
arch/x86/kvm/i8259.c
arch/x86/kvm/mmu.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c
arch/x86/mm/init.c
arch/x86/um/Kconfig
arch/x86/um/shared/sysdep/kernel-offsets.h
arch/x86/um/shared/sysdep/syscalls.h
arch/x86/um/signal.c
arch/x86/um/sys_call_table_32.c
arch/x86/um/syscalls_32.c
arch/x86/um/syscalls_64.c
arch/x86/xen/enlighten.c
arch/x86/xen/mmu.c
arch/x86/xen/p2m.c
arch/x86/xen/setup.c
arch/x86/xen/suspend.c
arch/x86/xen/xen-ops.h
block/blk-core.c
block/blk-lib.c
block/blk-merge.c
block/genhd.c
block/ioctl.c
crypto/authenc.c
drivers/acpi/bus.c
drivers/acpi/power.c
drivers/ata/Kconfig
drivers/ata/ahci.c
drivers/ata/ahci.h
drivers/ata/ata_piix.c
drivers/ata/libahci.c
drivers/ata/libata-acpi.c
drivers/ata/libata-core.c
drivers/ata/pata_atiixp.c
drivers/base/dma-contiguous.c
drivers/block/aoe/aoecmd.c
drivers/block/cciss_scsi.c
drivers/block/drbd/drbd_bitmap.c
drivers/block/drbd/drbd_int.h
drivers/block/drbd/drbd_main.c
drivers/block/drbd/drbd_nl.c
drivers/block/drbd/drbd_req.c
drivers/block/mtip32xx/mtip32xx.c
drivers/block/mtip32xx/mtip32xx.h
drivers/block/nbd.c
drivers/block/nvme.c
drivers/block/rbd.c
drivers/block/xen-blkback/blkback.c
drivers/bluetooth/ath3k.c
drivers/bluetooth/btusb.c
drivers/clk/Makefile
drivers/clk/clk-devres.c [new file with mode: 0644]
drivers/clk/clkdev.c
drivers/cpufreq/omap-cpufreq.c
drivers/cpufreq/powernow-k8.c
drivers/crypto/caam/jr.c
drivers/crypto/caam/key_gen.c
drivers/crypto/hifn_795x.c
drivers/dma/at_hdmac.c
drivers/dma/pl330.c
drivers/edac/edac_mc.c
drivers/edac/i3200_edac.c
drivers/edac/i5000_edac.c
drivers/edac/sb_edac.c
drivers/extcon/extcon-max77693.c
drivers/gpio/Kconfig
drivers/gpio/gpio-bt8xx.c
drivers/gpio/gpio-em.c
drivers/gpio/gpio-lpc32xx.c
drivers/gpio/gpio-rdc321x.c
drivers/gpio/gpiolib-of.c
drivers/gpu/drm/ast/ast_drv.c
drivers/gpu/drm/ast/ast_mode.c
drivers/gpu/drm/cirrus/cirrus_drv.c
drivers/gpu/drm/drm_crtc.c
drivers/gpu/drm/drm_edid.c
drivers/gpu/drm/exynos/Kconfig
drivers/gpu/drm/exynos/exynos_drm_dmabuf.c
drivers/gpu/drm/exynos/exynos_drm_drv.c
drivers/gpu/drm/exynos/exynos_drm_fimd.c
drivers/gpu/drm/exynos/exynos_drm_g2d.c
drivers/gpu/drm/exynos/exynos_drm_gem.c
drivers/gpu/drm/exynos/exynos_drm_hdmi.c
drivers/gpu/drm/exynos/exynos_drm_plane.c
drivers/gpu/drm/exynos/exynos_drm_vidi.c
drivers/gpu/drm/exynos/exynos_hdmi.c
drivers/gpu/drm/exynos/exynos_mixer.c
drivers/gpu/drm/gma500/oaktrail_device.c
drivers/gpu/drm/gma500/psb_intel_display.c
drivers/gpu/drm/i810/i810_dma.c
drivers/gpu/drm/i810/i810_drv.c
drivers/gpu/drm/i915/i915_dma.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/i915_gem_gtt.c
drivers/gpu/drm/i915/i915_irq.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/i915/intel_dp.c
drivers/gpu/drm/i915/intel_hdmi.c
drivers/gpu/drm/i915/intel_lvds.c
drivers/gpu/drm/i915/intel_panel.c
drivers/gpu/drm/i915/intel_pm.c
drivers/gpu/drm/i915/intel_sdvo.c
drivers/gpu/drm/i915/intel_sprite.c
drivers/gpu/drm/mgag200/mgag200_drv.c
drivers/gpu/drm/nouveau/nouveau_abi16.c
drivers/gpu/drm/nouveau/nouveau_display.c
drivers/gpu/drm/nouveau/nouveau_state.c
drivers/gpu/drm/nouveau/nv50_gpio.c
drivers/gpu/drm/nouveau/nvc0_fb.c
drivers/gpu/drm/nouveau/nvc0_fifo.c
drivers/gpu/drm/nouveau/nvd0_display.c
drivers/gpu/drm/nouveau/nve0_fifo.c
drivers/gpu/drm/radeon/atombios_crtc.c
drivers/gpu/drm/radeon/atombios_dp.c
drivers/gpu/drm/radeon/atombios_encoders.c
drivers/gpu/drm/radeon/r100.c
drivers/gpu/drm/radeon/r600_cs.c
drivers/gpu/drm/radeon/r600d.h
drivers/gpu/drm/radeon/radeon_device.c
drivers/gpu/drm/radeon/radeon_drv.c
drivers/gpu/drm/radeon/radeon_fence.c
drivers/gpu/drm/radeon/reg_srcs/r600
drivers/gpu/drm/savage/savage_drv.c
drivers/gpu/drm/sis/sis_drv.c
drivers/gpu/drm/tdfx/tdfx_drv.c
drivers/gpu/drm/udl/udl_connector.c
drivers/gpu/drm/udl/udl_drv.c
drivers/gpu/drm/via/via_drv.c
drivers/gpu/drm/vmwgfx/Kconfig
drivers/gpu/drm/vmwgfx/vmwgfx_drv.c
drivers/gpu/drm/vmwgfx/vmwgfx_drv.h
drivers/gpu/drm/vmwgfx/vmwgfx_fence.c
drivers/gpu/drm/vmwgfx/vmwgfx_resource.c
drivers/hid/hid-core.c
drivers/hid/hid-lenovo-tpkbd.c
drivers/hid/hid-logitech-dj.c
drivers/hid/hid-logitech-dj.h
drivers/hid/usbhid/hid-quirks.c
drivers/hwmon/ad7314.c
drivers/hwmon/ads7871.c
drivers/hwmon/applesmc.c
drivers/hwmon/asus_atk0110.c
drivers/hwmon/coretemp.c
drivers/hwmon/fam15h_power.c
drivers/hwmon/ina2xx.c
drivers/hwmon/twl4030-madc-hwmon.c
drivers/hwmon/via-cputemp.c
drivers/hwspinlock/hwspinlock_core.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-designware-core.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-mxs.c
drivers/i2c/busses/i2c-pnx.c
drivers/i2c/i2c-core.c
drivers/ide/ide-pm.c
drivers/iio/adc/at91_adc.c
drivers/infiniband/hw/cxgb4/cm.c
drivers/infiniband/hw/ocrdma/ocrdma_verbs.c
drivers/infiniband/hw/qib/qib_mad.c
drivers/infiniband/ulp/ipoib/ipoib.h
drivers/infiniband/ulp/ipoib/ipoib_main.c
drivers/infiniband/ulp/ipoib/ipoib_multicast.c
drivers/input/keyboard/imx_keypad.c
drivers/input/misc/ab8500-ponkey.c
drivers/input/mouse/sentelic.c
drivers/input/serio/ambakmi.c
drivers/input/serio/i8042-x86ia64io.h
drivers/input/tablet/wacom_wac.c
drivers/input/touchscreen/edt-ft5x06.c
drivers/input/touchscreen/usbtouchscreen.c
drivers/iommu/amd_iommu.c
drivers/isdn/hardware/mISDN/avmfritz.c
drivers/isdn/hardware/mISDN/hfcmulti.c
drivers/isdn/hardware/mISDN/mISDNipac.c
drivers/isdn/hardware/mISDN/mISDNisar.c
drivers/isdn/hardware/mISDN/netjet.c
drivers/isdn/hardware/mISDN/w6692.c
drivers/isdn/mISDN/hwchannel.c
drivers/md/dm-mpath.c
drivers/md/dm-table.c
drivers/md/dm-thin.c
drivers/md/dm-verity.c
drivers/md/dm.c
drivers/md/dm.h
drivers/md/md.c
drivers/md/raid10.c
drivers/md/raid5.c
drivers/media/Kconfig
drivers/media/Makefile
drivers/media/common/Kconfig
drivers/media/common/Makefile
drivers/media/common/b2c2/Kconfig [new file with mode: 0644]
drivers/media/common/b2c2/Makefile [new file with mode: 0644]
drivers/media/common/b2c2/flexcop-common.h [moved from drivers/media/dvb/b2c2/flexcop-common.h with 100% similarity]
drivers/media/common/b2c2/flexcop-eeprom.c [moved from drivers/media/dvb/b2c2/flexcop-eeprom.c with 100% similarity]
drivers/media/common/b2c2/flexcop-fe-tuner.c [moved from drivers/media/dvb/b2c2/flexcop-fe-tuner.c with 100% similarity]
drivers/media/common/b2c2/flexcop-hw-filter.c [moved from drivers/media/dvb/b2c2/flexcop-hw-filter.c with 100% similarity]
drivers/media/common/b2c2/flexcop-i2c.c [moved from drivers/media/dvb/b2c2/flexcop-i2c.c with 100% similarity]
drivers/media/common/b2c2/flexcop-misc.c [moved from drivers/media/dvb/b2c2/flexcop-misc.c with 100% similarity]
drivers/media/common/b2c2/flexcop-reg.h [moved from drivers/media/dvb/b2c2/flexcop-reg.h with 100% similarity]
drivers/media/common/b2c2/flexcop-sram.c [moved from drivers/media/dvb/b2c2/flexcop-sram.c with 100% similarity]
drivers/media/common/b2c2/flexcop.c [moved from drivers/media/dvb/b2c2/flexcop.c with 99% similarity]
drivers/media/common/b2c2/flexcop.h [moved from drivers/media/dvb/b2c2/flexcop.h with 100% similarity]
drivers/media/common/b2c2/flexcop_ibi_value_be.h [moved from drivers/media/dvb/b2c2/flexcop_ibi_value_be.h with 100% similarity]
drivers/media/common/b2c2/flexcop_ibi_value_le.h [moved from drivers/media/dvb/b2c2/flexcop_ibi_value_le.h with 100% similarity]
drivers/media/common/saa7146/Kconfig [new file with mode: 0644]
drivers/media/common/saa7146/Makefile [new file with mode: 0644]
drivers/media/common/saa7146/saa7146_core.c [moved from drivers/media/common/saa7146_core.c with 98% similarity]
drivers/media/common/saa7146/saa7146_fops.c [moved from drivers/media/common/saa7146_fops.c with 94% similarity]
drivers/media/common/saa7146/saa7146_hlp.c [moved from drivers/media/common/saa7146_hlp.c with 100% similarity]
drivers/media/common/saa7146/saa7146_i2c.c [moved from drivers/media/common/saa7146_i2c.c with 100% similarity]
drivers/media/common/saa7146/saa7146_vbi.c [moved from drivers/media/common/saa7146_vbi.c with 100% similarity]
drivers/media/common/saa7146/saa7146_video.c [moved from drivers/media/common/saa7146_video.c with 99% similarity]
drivers/media/common/siano/Kconfig [new file with mode: 0644]
drivers/media/common/siano/Makefile [moved from drivers/media/dvb/siano/Makefile with 57% similarity]
drivers/media/common/siano/sms-cards.c [moved from drivers/media/dvb/siano/sms-cards.c with 100% similarity]
drivers/media/common/siano/sms-cards.h [moved from drivers/media/dvb/siano/sms-cards.h with 100% similarity]
drivers/media/common/siano/smscoreapi.c [moved from drivers/media/dvb/siano/smscoreapi.c with 100% similarity]
drivers/media/common/siano/smscoreapi.h [moved from drivers/media/dvb/siano/smscoreapi.h with 100% similarity]
drivers/media/common/siano/smsdvb.c [moved from drivers/media/dvb/siano/smsdvb.c with 100% similarity]
drivers/media/common/siano/smsendian.c [moved from drivers/media/dvb/siano/smsendian.c with 100% similarity]
drivers/media/common/siano/smsendian.h [moved from drivers/media/dvb/siano/smsendian.h with 100% similarity]
drivers/media/common/siano/smsir.c [moved from drivers/media/dvb/siano/smsir.c with 100% similarity]
drivers/media/common/siano/smsir.h [moved from drivers/media/dvb/siano/smsir.h with 100% similarity]
drivers/media/dvb-core/Kconfig [new file with mode: 0644]
drivers/media/dvb-core/Makefile [moved from drivers/media/dvb/dvb-core/Makefile with 100% similarity]
drivers/media/dvb-core/demux.h [moved from drivers/media/dvb/dvb-core/demux.h with 100% similarity]
drivers/media/dvb-core/dmxdev.c [moved from drivers/media/dvb/dvb-core/dmxdev.c with 99% similarity]
drivers/media/dvb-core/dmxdev.h [moved from drivers/media/dvb/dvb-core/dmxdev.h with 100% similarity]
drivers/media/dvb-core/dvb-usb-ids.h [moved from drivers/media/dvb/dvb-usb/dvb-usb-ids.h with 99% similarity]
drivers/media/dvb-core/dvb_ca_en50221.c [moved from drivers/media/dvb/dvb-core/dvb_ca_en50221.c with 100% similarity]
drivers/media/dvb-core/dvb_ca_en50221.h [moved from drivers/media/dvb/dvb-core/dvb_ca_en50221.h with 100% similarity]
drivers/media/dvb-core/dvb_demux.c [moved from drivers/media/dvb/dvb-core/dvb_demux.c with 98% similarity]
drivers/media/dvb-core/dvb_demux.h [moved from drivers/media/dvb/dvb-core/dvb_demux.h with 100% similarity]
drivers/media/dvb-core/dvb_filter.c [moved from drivers/media/dvb/dvb-core/dvb_filter.c with 100% similarity]
drivers/media/dvb-core/dvb_filter.h [moved from drivers/media/dvb/dvb-core/dvb_filter.h with 100% similarity]
drivers/media/dvb-core/dvb_frontend.c [moved from drivers/media/dvb/dvb-core/dvb_frontend.c with 89% similarity]
drivers/media/dvb-core/dvb_frontend.h [moved from drivers/media/dvb/dvb-core/dvb_frontend.h with 98% similarity]
drivers/media/dvb-core/dvb_math.c [moved from drivers/media/dvb/dvb-core/dvb_math.c with 100% similarity]
drivers/media/dvb-core/dvb_math.h [moved from drivers/media/dvb/dvb-core/dvb_math.h with 100% similarity]
drivers/media/dvb-core/dvb_net.c [moved from drivers/media/dvb/dvb-core/dvb_net.c with 100% similarity]
drivers/media/dvb-core/dvb_net.h [moved from drivers/media/dvb/dvb-core/dvb_net.h with 100% similarity]
drivers/media/dvb-core/dvb_ringbuffer.c [moved from drivers/media/dvb/dvb-core/dvb_ringbuffer.c with 100% similarity]
drivers/media/dvb-core/dvb_ringbuffer.h [moved from drivers/media/dvb/dvb-core/dvb_ringbuffer.h with 100% similarity]
drivers/media/dvb-core/dvbdev.c [moved from drivers/media/dvb/dvb-core/dvbdev.c with 99% similarity]
drivers/media/dvb-core/dvbdev.h [moved from drivers/media/dvb/dvb-core/dvbdev.h with 80% similarity]
drivers/media/dvb-frontends/Kconfig [moved from drivers/media/dvb/frontends/Kconfig with 83% similarity]
drivers/media/dvb-frontends/Makefile [moved from drivers/media/dvb/frontends/Makefile with 92% similarity]
drivers/media/dvb-frontends/a8293.c [moved from drivers/media/dvb/frontends/a8293.c with 100% similarity]
drivers/media/dvb-frontends/a8293.h [moved from drivers/media/dvb/frontends/a8293.h with 100% similarity]
drivers/media/dvb-frontends/af9013.c [moved from drivers/media/dvb/frontends/af9013.c with 86% similarity]
drivers/media/dvb-frontends/af9013.h [moved from drivers/media/dvb/frontends/af9013.h with 97% similarity]
drivers/media/dvb-frontends/af9013_priv.h [moved from drivers/media/dvb/frontends/af9013_priv.h with 98% similarity]
drivers/media/dvb-frontends/af9033.c [moved from drivers/media/dvb/frontends/af9033.c with 86% similarity]
drivers/media/dvb-frontends/af9033.h [moved from drivers/media/dvb/frontends/af9033.h with 94% similarity]
drivers/media/dvb-frontends/af9033_priv.h [moved from drivers/media/dvb/frontends/af9033_priv.h with 92% similarity]
drivers/media/dvb-frontends/atbm8830.c [moved from drivers/media/dvb/frontends/atbm8830.c with 99% similarity]
drivers/media/dvb-frontends/atbm8830.h [moved from drivers/media/dvb/frontends/atbm8830.h with 100% similarity]
drivers/media/dvb-frontends/atbm8830_priv.h [moved from drivers/media/dvb/frontends/atbm8830_priv.h with 100% similarity]
drivers/media/dvb-frontends/au8522.h [moved from drivers/media/dvb/frontends/au8522.h with 100% similarity]
drivers/media/dvb-frontends/au8522_common.c [moved from drivers/media/dvb/frontends/au8522_common.c with 93% similarity]
drivers/media/dvb-frontends/au8522_decoder.c [moved from drivers/media/dvb/frontends/au8522_decoder.c with 98% similarity]
drivers/media/dvb-frontends/au8522_dig.c [moved from drivers/media/dvb/frontends/au8522_dig.c with 95% similarity]
drivers/media/dvb-frontends/au8522_priv.h [moved from drivers/media/dvb/frontends/au8522_priv.h with 93% similarity]
drivers/media/dvb-frontends/bcm3510.c [moved from drivers/media/dvb/frontends/bcm3510.c with 100% similarity]
drivers/media/dvb-frontends/bcm3510.h [moved from drivers/media/dvb/frontends/bcm3510.h with 100% similarity]
drivers/media/dvb-frontends/bcm3510_priv.h [moved from drivers/media/dvb/frontends/bcm3510_priv.h with 100% similarity]
drivers/media/dvb-frontends/bsbe1-d01a.h [moved from drivers/media/dvb/frontends/bsbe1-d01a.h with 100% similarity]
drivers/media/dvb-frontends/bsbe1.h [moved from drivers/media/dvb/frontends/bsbe1.h with 100% similarity]
drivers/media/dvb-frontends/bsru6.h [moved from drivers/media/dvb/frontends/bsru6.h with 100% similarity]
drivers/media/dvb-frontends/cx22700.c [moved from drivers/media/dvb/frontends/cx22700.c with 100% similarity]
drivers/media/dvb-frontends/cx22700.h [moved from drivers/media/dvb/frontends/cx22700.h with 100% similarity]
drivers/media/dvb-frontends/cx22702.c [moved from drivers/media/dvb/frontends/cx22702.c with 100% similarity]
drivers/media/dvb-frontends/cx22702.h [moved from drivers/media/dvb/frontends/cx22702.h with 100% similarity]
drivers/media/dvb-frontends/cx24110.c [moved from drivers/media/dvb/frontends/cx24110.c with 100% similarity]
drivers/media/dvb-frontends/cx24110.h [moved from drivers/media/dvb/frontends/cx24110.h with 100% similarity]
drivers/media/dvb-frontends/cx24113.c [moved from drivers/media/dvb/frontends/cx24113.c with 100% similarity]
drivers/media/dvb-frontends/cx24113.h [moved from drivers/media/dvb/frontends/cx24113.h with 100% similarity]
drivers/media/dvb-frontends/cx24116.c [moved from drivers/media/dvb/frontends/cx24116.c with 100% similarity]
drivers/media/dvb-frontends/cx24116.h [moved from drivers/media/dvb/frontends/cx24116.h with 100% similarity]
drivers/media/dvb-frontends/cx24123.c [moved from drivers/media/dvb/frontends/cx24123.c with 100% similarity]
drivers/media/dvb-frontends/cx24123.h [moved from drivers/media/dvb/frontends/cx24123.h with 100% similarity]
drivers/media/dvb-frontends/cxd2820r.h [moved from drivers/media/dvb/frontends/cxd2820r.h with 92% similarity]
drivers/media/dvb-frontends/cxd2820r_c.c [moved from drivers/media/dvb/frontends/cxd2820r_c.c with 89% similarity]
drivers/media/dvb-frontends/cxd2820r_core.c [moved from drivers/media/dvb/frontends/cxd2820r_core.c with 70% similarity]
drivers/media/dvb-frontends/cxd2820r_priv.h [moved from drivers/media/dvb/frontends/cxd2820r_priv.h with 89% similarity]
drivers/media/dvb-frontends/cxd2820r_t.c [moved from drivers/media/dvb/frontends/cxd2820r_t.c with 91% similarity]
drivers/media/dvb-frontends/cxd2820r_t2.c [moved from drivers/media/dvb/frontends/cxd2820r_t2.c with 91% similarity]
drivers/media/dvb-frontends/dib0070.c [moved from drivers/media/dvb/frontends/dib0070.c with 100% similarity]
drivers/media/dvb-frontends/dib0070.h [moved from drivers/media/dvb/frontends/dib0070.h with 100% similarity]
drivers/media/dvb-frontends/dib0090.c [moved from drivers/media/dvb/frontends/dib0090.c with 100% similarity]
drivers/media/dvb-frontends/dib0090.h [moved from drivers/media/dvb/frontends/dib0090.h with 100% similarity]
drivers/media/dvb-frontends/dib3000.h [moved from drivers/media/dvb/frontends/dib3000.h with 100% similarity]
drivers/media/dvb-frontends/dib3000mb.c [moved from drivers/media/dvb/frontends/dib3000mb.c with 100% similarity]
drivers/media/dvb-frontends/dib3000mb_priv.h [moved from drivers/media/dvb/frontends/dib3000mb_priv.h with 100% similarity]
drivers/media/dvb-frontends/dib3000mc.c [moved from drivers/media/dvb/frontends/dib3000mc.c with 100% similarity]
drivers/media/dvb-frontends/dib3000mc.h [moved from drivers/media/dvb/frontends/dib3000mc.h with 100% similarity]
drivers/media/dvb-frontends/dib7000m.c [moved from drivers/media/dvb/frontends/dib7000m.c with 100% similarity]
drivers/media/dvb-frontends/dib7000m.h [moved from drivers/media/dvb/frontends/dib7000m.h with 100% similarity]
drivers/media/dvb-frontends/dib7000p.c [moved from drivers/media/dvb/frontends/dib7000p.c with 100% similarity]
drivers/media/dvb-frontends/dib7000p.h [moved from drivers/media/dvb/frontends/dib7000p.h with 100% similarity]
drivers/media/dvb-frontends/dib8000.c [moved from drivers/media/dvb/frontends/dib8000.c with 100% similarity]
drivers/media/dvb-frontends/dib8000.h [moved from drivers/media/dvb/frontends/dib8000.h with 100% similarity]
drivers/media/dvb-frontends/dib9000.c [moved from drivers/media/dvb/frontends/dib9000.c with 100% similarity]
drivers/media/dvb-frontends/dib9000.h [moved from drivers/media/dvb/frontends/dib9000.h with 100% similarity]
drivers/media/dvb-frontends/dibx000_common.c [moved from drivers/media/dvb/frontends/dibx000_common.c with 100% similarity]
drivers/media/dvb-frontends/dibx000_common.h [moved from drivers/media/dvb/frontends/dibx000_common.h with 100% similarity]
drivers/media/dvb-frontends/drxd.h [moved from drivers/media/dvb/frontends/drxd.h with 100% similarity]
drivers/media/dvb-frontends/drxd_firm.c [moved from drivers/media/dvb/frontends/drxd_firm.c with 100% similarity]
drivers/media/dvb-frontends/drxd_firm.h [moved from drivers/media/dvb/frontends/drxd_firm.h with 100% similarity]
drivers/media/dvb-frontends/drxd_hard.c [moved from drivers/media/dvb/frontends/drxd_hard.c with 100% similarity]
drivers/media/dvb-frontends/drxd_map_firm.h [moved from drivers/media/dvb/frontends/drxd_map_firm.h with 100% similarity]
drivers/media/dvb-frontends/drxk.h [moved from drivers/media/dvb/frontends/drxk.h with 95% similarity]
drivers/media/dvb-frontends/drxk_hard.c [moved from drivers/media/dvb/frontends/drxk_hard.c with 99% similarity]
drivers/media/dvb-frontends/drxk_hard.h [moved from drivers/media/dvb/frontends/drxk_hard.h with 100% similarity]
drivers/media/dvb-frontends/drxk_map.h [moved from drivers/media/dvb/frontends/drxk_map.h with 100% similarity]
drivers/media/dvb-frontends/ds3000.c [moved from drivers/media/dvb/frontends/ds3000.c with 100% similarity]
drivers/media/dvb-frontends/ds3000.h [moved from drivers/media/dvb/frontends/ds3000.h with 100% similarity]
drivers/media/dvb-frontends/dvb-pll.c [moved from drivers/media/dvb/frontends/dvb-pll.c with 96% similarity]
drivers/media/dvb-frontends/dvb-pll.h [moved from drivers/media/dvb/frontends/dvb-pll.h with 97% similarity]
drivers/media/dvb-frontends/dvb_dummy_fe.c [moved from drivers/media/dvb/frontends/dvb_dummy_fe.c with 100% similarity]
drivers/media/dvb-frontends/dvb_dummy_fe.h [moved from drivers/media/dvb/frontends/dvb_dummy_fe.h with 100% similarity]
drivers/media/dvb-frontends/ec100.c [moved from drivers/media/dvb/frontends/ec100.c with 87% similarity]
drivers/media/dvb-frontends/ec100.h [moved from drivers/media/dvb/frontends/ec100.h with 95% similarity]
drivers/media/dvb-frontends/eds1547.h [moved from drivers/media/dvb/frontends/eds1547.h with 100% similarity]
drivers/media/dvb-frontends/hd29l2.c [moved from drivers/media/dvb/frontends/hd29l2.c with 89% similarity]
drivers/media/dvb-frontends/hd29l2.h [moved from drivers/media/dvb/frontends/hd29l2.h with 96% similarity]
drivers/media/dvb-frontends/hd29l2_priv.h [moved from drivers/media/dvb/frontends/hd29l2_priv.h with 96% similarity]
drivers/media/dvb-frontends/isl6405.c [moved from drivers/media/dvb/frontends/isl6405.c with 100% similarity]
drivers/media/dvb-frontends/isl6405.h [moved from drivers/media/dvb/frontends/isl6405.h with 100% similarity]
drivers/media/dvb-frontends/isl6421.c [moved from drivers/media/dvb/frontends/isl6421.c with 100% similarity]
drivers/media/dvb-frontends/isl6421.h [moved from drivers/media/dvb/frontends/isl6421.h with 100% similarity]
drivers/media/dvb-frontends/isl6423.c [moved from drivers/media/dvb/frontends/isl6423.c with 100% similarity]
drivers/media/dvb-frontends/isl6423.h [moved from drivers/media/dvb/frontends/isl6423.h with 100% similarity]
drivers/media/dvb-frontends/it913x-fe-priv.h [moved from drivers/media/dvb/frontends/it913x-fe-priv.h with 100% similarity]
drivers/media/dvb-frontends/it913x-fe.c [moved from drivers/media/dvb/frontends/it913x-fe.c with 99% similarity]
drivers/media/dvb-frontends/it913x-fe.h [moved from drivers/media/dvb/frontends/it913x-fe.h with 100% similarity]
drivers/media/dvb-frontends/itd1000.c [moved from drivers/media/dvb/frontends/itd1000.c with 100% similarity]
drivers/media/dvb-frontends/itd1000.h [moved from drivers/media/dvb/frontends/itd1000.h with 100% similarity]
drivers/media/dvb-frontends/itd1000_priv.h [moved from drivers/media/dvb/frontends/itd1000_priv.h with 100% similarity]
drivers/media/dvb-frontends/ix2505v.c [moved from drivers/media/dvb/frontends/ix2505v.c with 100% similarity]
drivers/media/dvb-frontends/ix2505v.h [moved from drivers/media/dvb/frontends/ix2505v.h with 100% similarity]
drivers/media/dvb-frontends/l64781.c [moved from drivers/media/dvb/frontends/l64781.c with 100% similarity]
drivers/media/dvb-frontends/l64781.h [moved from drivers/media/dvb/frontends/l64781.h with 100% similarity]
drivers/media/dvb-frontends/lg2160.c [moved from drivers/media/dvb/frontends/lg2160.c with 100% similarity]
drivers/media/dvb-frontends/lg2160.h [moved from drivers/media/dvb/frontends/lg2160.h with 100% similarity]
drivers/media/dvb-frontends/lgdt3305.c [moved from drivers/media/dvb/frontends/lgdt3305.c with 100% similarity]
drivers/media/dvb-frontends/lgdt3305.h [moved from drivers/media/dvb/frontends/lgdt3305.h with 100% similarity]
drivers/media/dvb-frontends/lgdt330x.c [moved from drivers/media/dvb/frontends/lgdt330x.c with 100% similarity]
drivers/media/dvb-frontends/lgdt330x.h [moved from drivers/media/dvb/frontends/lgdt330x.h with 100% similarity]
drivers/media/dvb-frontends/lgdt330x_priv.h [moved from drivers/media/dvb/frontends/lgdt330x_priv.h with 100% similarity]
drivers/media/dvb-frontends/lgs8gl5.c [moved from drivers/media/dvb/frontends/lgs8gl5.c with 99% similarity]
drivers/media/dvb-frontends/lgs8gl5.h [moved from drivers/media/dvb/frontends/lgs8gl5.h with 100% similarity]
drivers/media/dvb-frontends/lgs8gxx.c [moved from drivers/media/dvb/frontends/lgs8gxx.c with 99% similarity]
drivers/media/dvb-frontends/lgs8gxx.h [moved from drivers/media/dvb/frontends/lgs8gxx.h with 100% similarity]
drivers/media/dvb-frontends/lgs8gxx_priv.h [moved from drivers/media/dvb/frontends/lgs8gxx_priv.h with 100% similarity]
drivers/media/dvb-frontends/lnbh24.h [moved from drivers/media/dvb/frontends/lnbh24.h with 100% similarity]
drivers/media/dvb-frontends/lnbp21.c [moved from drivers/media/dvb/frontends/lnbp21.c with 100% similarity]
drivers/media/dvb-frontends/lnbp21.h [moved from drivers/media/dvb/frontends/lnbp21.h with 100% similarity]
drivers/media/dvb-frontends/lnbp22.c [moved from drivers/media/dvb/frontends/lnbp22.c with 100% similarity]
drivers/media/dvb-frontends/lnbp22.h [moved from drivers/media/dvb/frontends/lnbp22.h with 100% similarity]
drivers/media/dvb-frontends/m88rs2000.c [moved from drivers/media/dvb/frontends/m88rs2000.c with 99% similarity]
drivers/media/dvb-frontends/m88rs2000.h [moved from drivers/media/dvb/frontends/m88rs2000.h with 100% similarity]
drivers/media/dvb-frontends/mb86a16.c [moved from drivers/media/dvb/frontends/mb86a16.c with 100% similarity]
drivers/media/dvb-frontends/mb86a16.h [moved from drivers/media/dvb/frontends/mb86a16.h with 100% similarity]
drivers/media/dvb-frontends/mb86a16_priv.h [moved from drivers/media/dvb/frontends/mb86a16_priv.h with 100% similarity]
drivers/media/dvb-frontends/mb86a20s.c [moved from drivers/media/dvb/frontends/mb86a20s.c with 100% similarity]
drivers/media/dvb-frontends/mb86a20s.h [moved from drivers/media/dvb/frontends/mb86a20s.h with 100% similarity]
drivers/media/dvb-frontends/mt312.c [moved from drivers/media/dvb/frontends/mt312.c with 100% similarity]
drivers/media/dvb-frontends/mt312.h [moved from drivers/media/dvb/frontends/mt312.h with 100% similarity]
drivers/media/dvb-frontends/mt312_priv.h [moved from drivers/media/dvb/frontends/mt312_priv.h with 100% similarity]
drivers/media/dvb-frontends/mt352.c [moved from drivers/media/dvb/frontends/mt352.c with 100% similarity]
drivers/media/dvb-frontends/mt352.h [moved from drivers/media/dvb/frontends/mt352.h with 100% similarity]
drivers/media/dvb-frontends/mt352_priv.h [moved from drivers/media/dvb/frontends/mt352_priv.h with 100% similarity]
drivers/media/dvb-frontends/nxt200x.c [moved from drivers/media/dvb/frontends/nxt200x.c with 93% similarity]
drivers/media/dvb-frontends/nxt200x.h [moved from drivers/media/dvb/frontends/nxt200x.h with 100% similarity]
drivers/media/dvb-frontends/nxt6000.c [moved from drivers/media/dvb/frontends/nxt6000.c with 100% similarity]
drivers/media/dvb-frontends/nxt6000.h [moved from drivers/media/dvb/frontends/nxt6000.h with 100% similarity]
drivers/media/dvb-frontends/nxt6000_priv.h [moved from drivers/media/dvb/frontends/nxt6000_priv.h with 100% similarity]
drivers/media/dvb-frontends/or51132.c [moved from drivers/media/dvb/frontends/or51132.c with 100% similarity]
drivers/media/dvb-frontends/or51132.h [moved from drivers/media/dvb/frontends/or51132.h with 100% similarity]
drivers/media/dvb-frontends/or51211.c [moved from drivers/media/dvb/frontends/or51211.c with 100% similarity]
drivers/media/dvb-frontends/or51211.h [moved from drivers/media/dvb/frontends/or51211.h with 100% similarity]
drivers/media/dvb-frontends/rtl2830.c [moved from drivers/media/dvb/frontends/rtl2830.c with 88% similarity]
drivers/media/dvb-frontends/rtl2830.h [moved from drivers/media/dvb/frontends/rtl2830.h with 90% similarity]
drivers/media/dvb-frontends/rtl2830_priv.h [moved from drivers/media/dvb/frontends/rtl2830_priv.h with 75% similarity]
drivers/media/dvb-frontends/rtl2832.c [moved from drivers/media/dvb/frontends/rtl2832.c with 77% similarity]
drivers/media/dvb-frontends/rtl2832.h [moved from drivers/media/dvb/frontends/rtl2832.h with 84% similarity]
drivers/media/dvb-frontends/rtl2832_priv.h [moved from drivers/media/dvb/frontends/rtl2832_priv.h with 55% similarity]
drivers/media/dvb-frontends/s5h1409.c [moved from drivers/media/dvb/frontends/s5h1409.c with 100% similarity]
drivers/media/dvb-frontends/s5h1409.h [moved from drivers/media/dvb/frontends/s5h1409.h with 100% similarity]
drivers/media/dvb-frontends/s5h1411.c [moved from drivers/media/dvb/frontends/s5h1411.c with 100% similarity]
drivers/media/dvb-frontends/s5h1411.h [moved from drivers/media/dvb/frontends/s5h1411.h with 100% similarity]
drivers/media/dvb-frontends/s5h1420.c [moved from drivers/media/dvb/frontends/s5h1420.c with 100% similarity]
drivers/media/dvb-frontends/s5h1420.h [moved from drivers/media/dvb/frontends/s5h1420.h with 100% similarity]
drivers/media/dvb-frontends/s5h1420_priv.h [moved from drivers/media/dvb/frontends/s5h1420_priv.h with 100% similarity]
drivers/media/dvb-frontends/s5h1432.c [moved from drivers/media/dvb/frontends/s5h1432.c with 100% similarity]
drivers/media/dvb-frontends/s5h1432.h [moved from drivers/media/dvb/frontends/s5h1432.h with 100% similarity]
drivers/media/dvb-frontends/s921.c [moved from drivers/media/dvb/frontends/s921.c with 100% similarity]
drivers/media/dvb-frontends/s921.h [moved from drivers/media/dvb/frontends/s921.h with 100% similarity]
drivers/media/dvb-frontends/si21xx.c [moved from drivers/media/dvb/frontends/si21xx.c with 100% similarity]
drivers/media/dvb-frontends/si21xx.h [moved from drivers/media/dvb/frontends/si21xx.h with 100% similarity]
drivers/media/dvb-frontends/sp8870.c [moved from drivers/media/dvb/frontends/sp8870.c with 100% similarity]
drivers/media/dvb-frontends/sp8870.h [moved from drivers/media/dvb/frontends/sp8870.h with 100% similarity]
drivers/media/dvb-frontends/sp887x.c [moved from drivers/media/dvb/frontends/sp887x.c with 100% similarity]
drivers/media/dvb-frontends/sp887x.h [moved from drivers/media/dvb/frontends/sp887x.h with 100% similarity]
drivers/media/dvb-frontends/stb0899_algo.c [moved from drivers/media/dvb/frontends/stb0899_algo.c with 100% similarity]
drivers/media/dvb-frontends/stb0899_cfg.h [moved from drivers/media/dvb/frontends/stb0899_cfg.h with 100% similarity]
drivers/media/dvb-frontends/stb0899_drv.c [moved from drivers/media/dvb/frontends/stb0899_drv.c with 99% similarity]
drivers/media/dvb-frontends/stb0899_drv.h [moved from drivers/media/dvb/frontends/stb0899_drv.h with 100% similarity]
drivers/media/dvb-frontends/stb0899_priv.h [moved from drivers/media/dvb/frontends/stb0899_priv.h with 100% similarity]
drivers/media/dvb-frontends/stb0899_reg.h [moved from drivers/media/dvb/frontends/stb0899_reg.h with 100% similarity]
drivers/media/dvb-frontends/stb6000.c [moved from drivers/media/dvb/frontends/stb6000.c with 100% similarity]
drivers/media/dvb-frontends/stb6000.h [moved from drivers/media/dvb/frontends/stb6000.h with 100% similarity]
drivers/media/dvb-frontends/stb6100.c [moved from drivers/media/dvb/frontends/stb6100.c with 100% similarity]
drivers/media/dvb-frontends/stb6100.h [moved from drivers/media/dvb/frontends/stb6100.h with 100% similarity]
drivers/media/dvb-frontends/stb6100_cfg.h [moved from drivers/media/dvb/frontends/stb6100_cfg.h with 100% similarity]
drivers/media/dvb-frontends/stb6100_proc.h [moved from drivers/media/dvb/frontends/stb6100_proc.h with 100% similarity]
drivers/media/dvb-frontends/stv0288.c [moved from drivers/media/dvb/frontends/stv0288.c with 100% similarity]
drivers/media/dvb-frontends/stv0288.h [moved from drivers/media/dvb/frontends/stv0288.h with 100% similarity]
drivers/media/dvb-frontends/stv0297.c [moved from drivers/media/dvb/frontends/stv0297.c with 100% similarity]
drivers/media/dvb-frontends/stv0297.h [moved from drivers/media/dvb/frontends/stv0297.h with 100% similarity]
drivers/media/dvb-frontends/stv0299.c [moved from drivers/media/dvb/frontends/stv0299.c with 100% similarity]
drivers/media/dvb-frontends/stv0299.h [moved from drivers/media/dvb/frontends/stv0299.h with 100% similarity]
drivers/media/dvb-frontends/stv0367.c [moved from drivers/media/dvb/frontends/stv0367.c with 100% similarity]
drivers/media/dvb-frontends/stv0367.h [moved from drivers/media/dvb/frontends/stv0367.h with 100% similarity]
drivers/media/dvb-frontends/stv0367_priv.h [moved from drivers/media/dvb/frontends/stv0367_priv.h with 100% similarity]
drivers/media/dvb-frontends/stv0367_regs.h [moved from drivers/media/dvb/frontends/stv0367_regs.h with 100% similarity]
drivers/media/dvb-frontends/stv0900.h [moved from drivers/media/dvb/frontends/stv0900.h with 100% similarity]
drivers/media/dvb-frontends/stv0900_core.c [moved from drivers/media/dvb/frontends/stv0900_core.c with 100% similarity]
drivers/media/dvb-frontends/stv0900_init.h [moved from drivers/media/dvb/frontends/stv0900_init.h with 100% similarity]
drivers/media/dvb-frontends/stv0900_priv.h [moved from drivers/media/dvb/frontends/stv0900_priv.h with 100% similarity]
drivers/media/dvb-frontends/stv0900_reg.h [moved from drivers/media/dvb/frontends/stv0900_reg.h with 100% similarity]
drivers/media/dvb-frontends/stv0900_sw.c [moved from drivers/media/dvb/frontends/stv0900_sw.c with 100% similarity]
drivers/media/dvb-frontends/stv090x.c [moved from drivers/media/dvb/frontends/stv090x.c with 99% similarity]
drivers/media/dvb-frontends/stv090x.h [moved from drivers/media/dvb/frontends/stv090x.h with 100% similarity]
drivers/media/dvb-frontends/stv090x_priv.h [moved from drivers/media/dvb/frontends/stv090x_priv.h with 100% similarity]
drivers/media/dvb-frontends/stv090x_reg.h [moved from drivers/media/dvb/frontends/stv090x_reg.h with 100% similarity]
drivers/media/dvb-frontends/stv6110.c [moved from drivers/media/dvb/frontends/stv6110.c with 100% similarity]
drivers/media/dvb-frontends/stv6110.h [moved from drivers/media/dvb/frontends/stv6110.h with 100% similarity]
drivers/media/dvb-frontends/stv6110x.c [moved from drivers/media/dvb/frontends/stv6110x.c with 100% similarity]
drivers/media/dvb-frontends/stv6110x.h [moved from drivers/media/dvb/frontends/stv6110x.h with 100% similarity]
drivers/media/dvb-frontends/stv6110x_priv.h [moved from drivers/media/dvb/frontends/stv6110x_priv.h with 100% similarity]
drivers/media/dvb-frontends/stv6110x_reg.h [moved from drivers/media/dvb/frontends/stv6110x_reg.h with 100% similarity]
drivers/media/dvb-frontends/tda10021.c [moved from drivers/media/dvb/frontends/tda10021.c with 100% similarity]
drivers/media/dvb-frontends/tda10023.c [moved from drivers/media/dvb/frontends/tda10023.c with 100% similarity]
drivers/media/dvb-frontends/tda1002x.h [moved from drivers/media/dvb/frontends/tda1002x.h with 100% similarity]
drivers/media/dvb-frontends/tda10048.c [moved from drivers/media/dvb/frontends/tda10048.c with 100% similarity]
drivers/media/dvb-frontends/tda10048.h [moved from drivers/media/dvb/frontends/tda10048.h with 100% similarity]
drivers/media/dvb-frontends/tda1004x.c [moved from drivers/media/dvb/frontends/tda1004x.c with 99% similarity]
drivers/media/dvb-frontends/tda1004x.h [moved from drivers/media/dvb/frontends/tda1004x.h with 100% similarity]
drivers/media/dvb-frontends/tda10071.c [moved from drivers/media/dvb/frontends/tda10071.c with 99% similarity]
drivers/media/dvb-frontends/tda10071.h [moved from drivers/media/dvb/frontends/tda10071.h with 100% similarity]
drivers/media/dvb-frontends/tda10071_priv.h [moved from drivers/media/dvb/frontends/tda10071_priv.h with 98% similarity]
drivers/media/dvb-frontends/tda10086.c [moved from drivers/media/dvb/frontends/tda10086.c with 100% similarity]
drivers/media/dvb-frontends/tda10086.h [moved from drivers/media/dvb/frontends/tda10086.h with 100% similarity]
drivers/media/dvb-frontends/tda18271c2dd.c [moved from drivers/media/dvb/frontends/tda18271c2dd.c with 100% similarity]
drivers/media/dvb-frontends/tda18271c2dd.h [moved from drivers/media/dvb/frontends/tda18271c2dd.h with 100% similarity]
drivers/media/dvb-frontends/tda18271c2dd_maps.h [moved from drivers/media/dvb/frontends/tda18271c2dd_maps.h with 100% similarity]
drivers/media/dvb-frontends/tda665x.c [moved from drivers/media/dvb/frontends/tda665x.c with 100% similarity]
drivers/media/dvb-frontends/tda665x.h [moved from drivers/media/dvb/frontends/tda665x.h with 100% similarity]
drivers/media/dvb-frontends/tda8083.c [moved from drivers/media/dvb/frontends/tda8083.c with 100% similarity]
drivers/media/dvb-frontends/tda8083.h [moved from drivers/media/dvb/frontends/tda8083.h with 100% similarity]
drivers/media/dvb-frontends/tda8261.c [moved from drivers/media/dvb/frontends/tda8261.c with 86% similarity]
drivers/media/dvb-frontends/tda8261.h [moved from drivers/media/dvb/frontends/tda8261.h with 100% similarity]
drivers/media/dvb-frontends/tda8261_cfg.h [moved from drivers/media/dvb/frontends/tda8261_cfg.h with 100% similarity]
drivers/media/dvb-frontends/tda826x.c [moved from drivers/media/dvb/frontends/tda826x.c with 100% similarity]
drivers/media/dvb-frontends/tda826x.h [moved from drivers/media/dvb/frontends/tda826x.h with 100% similarity]
drivers/media/dvb-frontends/tdhd1.h [moved from drivers/media/dvb/frontends/tdhd1.h with 100% similarity]
drivers/media/dvb-frontends/tua6100.c [moved from drivers/media/dvb/frontends/tua6100.c with 100% similarity]
drivers/media/dvb-frontends/tua6100.h [moved from drivers/media/dvb/frontends/tua6100.h with 100% similarity]
drivers/media/dvb-frontends/ves1820.c [moved from drivers/media/dvb/frontends/ves1820.c with 100% similarity]
drivers/media/dvb-frontends/ves1820.h [moved from drivers/media/dvb/frontends/ves1820.h with 100% similarity]
drivers/media/dvb-frontends/ves1x93.c [moved from drivers/media/dvb/frontends/ves1x93.c with 100% similarity]
drivers/media/dvb-frontends/ves1x93.h [moved from drivers/media/dvb/frontends/ves1x93.h with 100% similarity]
drivers/media/dvb-frontends/z0194a.h [moved from drivers/media/dvb/frontends/z0194a.h with 100% similarity]
drivers/media/dvb-frontends/zl10036.c [moved from drivers/media/dvb/frontends/zl10036.c with 100% similarity]
drivers/media/dvb-frontends/zl10036.h [moved from drivers/media/dvb/frontends/zl10036.h with 100% similarity]
drivers/media/dvb-frontends/zl10039.c [moved from drivers/media/dvb/frontends/zl10039.c with 100% similarity]
drivers/media/dvb-frontends/zl10039.h [moved from drivers/media/dvb/frontends/zl10039.h with 100% similarity]
drivers/media/dvb-frontends/zl10353.c [moved from drivers/media/dvb/frontends/zl10353.c with 100% similarity]
drivers/media/dvb-frontends/zl10353.h [moved from drivers/media/dvb/frontends/zl10353.h with 100% similarity]
drivers/media/dvb-frontends/zl10353_priv.h [moved from drivers/media/dvb/frontends/zl10353_priv.h with 100% similarity]
drivers/media/dvb/Kconfig [deleted file]
drivers/media/dvb/Makefile [deleted file]
drivers/media/dvb/b2c2/Kconfig [deleted file]
drivers/media/dvb/b2c2/Makefile [deleted file]
drivers/media/dvb/bt8xx/Kconfig [deleted file]
drivers/media/dvb/bt8xx/Makefile [deleted file]
drivers/media/dvb/dm1105/Makefile [deleted file]
drivers/media/dvb/dvb-usb/Kconfig [deleted file]
drivers/media/dvb/dvb-usb/Makefile [deleted file]
drivers/media/dvb/dvb-usb/af9015.c [deleted file]
drivers/media/dvb/dvb-usb/it913x.c [deleted file]
drivers/media/dvb/dvb-usb/mxl111sf.c [deleted file]
drivers/media/dvb/frontends/ec100_priv.h [deleted file]
drivers/media/dvb/ngene/Kconfig [deleted file]
drivers/media/dvb/pluto2/Makefile [deleted file]
drivers/media/dvb/siano/Kconfig [deleted file]
drivers/media/dvb/ttusb-budget/Makefile [deleted file]
drivers/media/firewire/Kconfig [moved from drivers/media/dvb/firewire/Kconfig with 100% similarity]
drivers/media/firewire/Makefile [moved from drivers/media/dvb/firewire/Makefile with 51% similarity]
drivers/media/firewire/firedtv-avc.c [moved from drivers/media/dvb/firewire/firedtv-avc.c with 100% similarity]
drivers/media/firewire/firedtv-ci.c [moved from drivers/media/dvb/firewire/firedtv-ci.c with 100% similarity]
drivers/media/firewire/firedtv-dvb.c [moved from drivers/media/dvb/firewire/firedtv-dvb.c with 100% similarity]
drivers/media/firewire/firedtv-fe.c [moved from drivers/media/dvb/firewire/firedtv-fe.c with 100% similarity]
drivers/media/firewire/firedtv-fw.c [moved from drivers/media/dvb/firewire/firedtv-fw.c with 100% similarity]
drivers/media/firewire/firedtv-rc.c [moved from drivers/media/dvb/firewire/firedtv-rc.c with 100% similarity]
drivers/media/firewire/firedtv.h [moved from drivers/media/dvb/firewire/firedtv.h with 100% similarity]
drivers/media/i2c/Kconfig [new file with mode: 0644]
drivers/media/i2c/Makefile [new file with mode: 0644]
drivers/media/i2c/ad9389b.c [new file with mode: 0644]
drivers/media/i2c/adp1653.c [moved from drivers/media/video/adp1653.c with 99% similarity]
drivers/media/i2c/adv7170.c [moved from drivers/media/video/adv7170.c with 100% similarity]
drivers/media/i2c/adv7175.c [moved from drivers/media/video/adv7175.c with 100% similarity]
drivers/media/i2c/adv7180.c [moved from drivers/media/video/adv7180.c with 100% similarity]
drivers/media/i2c/adv7183.c [moved from drivers/media/video/adv7183.c with 100% similarity]
drivers/media/i2c/adv7183_regs.h [moved from drivers/media/video/adv7183_regs.h with 100% similarity]
drivers/media/i2c/adv7343.c [moved from drivers/media/video/adv7343.c with 100% similarity]
drivers/media/i2c/adv7343_regs.h [moved from drivers/media/video/adv7343_regs.h with 100% similarity]
drivers/media/i2c/adv7393.c [moved from drivers/media/video/adv7393.c with 100% similarity]
drivers/media/i2c/adv7393_regs.h [moved from drivers/media/video/adv7393_regs.h with 100% similarity]
drivers/media/i2c/adv7604.c [new file with mode: 0644]
drivers/media/i2c/ak881x.c [moved from drivers/media/video/ak881x.c with 100% similarity]
drivers/media/i2c/aptina-pll.c [moved from drivers/media/video/aptina-pll.c with 100% similarity]
drivers/media/i2c/aptina-pll.h [moved from drivers/media/video/aptina-pll.h with 100% similarity]
drivers/media/i2c/as3645a.c [moved from drivers/media/video/as3645a.c with 99% similarity]
drivers/media/i2c/bt819.c [moved from drivers/media/video/bt819.c with 100% similarity]
drivers/media/i2c/bt856.c [moved from drivers/media/video/bt856.c with 100% similarity]
drivers/media/i2c/bt866.c [moved from drivers/media/video/bt866.c with 100% similarity]
drivers/media/i2c/btcx-risc.c [moved from drivers/media/video/btcx-risc.c with 100% similarity]
drivers/media/i2c/btcx-risc.h [moved from drivers/media/video/btcx-risc.h with 100% similarity]
drivers/media/i2c/cs5345.c [moved from drivers/media/video/cs5345.c with 100% similarity]
drivers/media/i2c/cs53l32a.c [moved from drivers/media/video/cs53l32a.c with 100% similarity]
drivers/media/i2c/cx2341x.c [moved from drivers/media/video/cx2341x.c with 100% similarity]
drivers/media/i2c/cx25840/Kconfig [moved from drivers/media/video/cx25840/Kconfig with 100% similarity]
drivers/media/i2c/cx25840/Makefile [moved from drivers/media/video/cx25840/Makefile with 80% similarity]
drivers/media/i2c/cx25840/cx25840-audio.c [moved from drivers/media/video/cx25840/cx25840-audio.c with 100% similarity]
drivers/media/i2c/cx25840/cx25840-core.c [moved from drivers/media/video/cx25840/cx25840-core.c with 100% similarity]
drivers/media/i2c/cx25840/cx25840-core.h [moved from drivers/media/video/cx25840/cx25840-core.h with 100% similarity]
drivers/media/i2c/cx25840/cx25840-firmware.c [moved from drivers/media/video/cx25840/cx25840-firmware.c with 92% similarity]
drivers/media/i2c/cx25840/cx25840-ir.c [moved from drivers/media/video/cx25840/cx25840-ir.c with 100% similarity]
drivers/media/i2c/cx25840/cx25840-vbi.c [moved from drivers/media/video/cx25840/cx25840-vbi.c with 98% similarity]
drivers/media/i2c/ir-kbd-i2c.c [moved from drivers/media/video/ir-kbd-i2c.c with 100% similarity]
drivers/media/i2c/ks0127.c [moved from drivers/media/video/ks0127.c with 99% similarity]
drivers/media/i2c/ks0127.h [moved from drivers/media/video/ks0127.h with 100% similarity]
drivers/media/i2c/m52790.c [moved from drivers/media/video/m52790.c with 100% similarity]
drivers/media/i2c/m5mols/Kconfig [moved from drivers/media/video/m5mols/Kconfig with 100% similarity]
drivers/media/i2c/m5mols/Makefile [moved from drivers/media/video/m5mols/Makefile with 100% similarity]
drivers/media/i2c/m5mols/m5mols.h [moved from drivers/media/video/m5mols/m5mols.h with 96% similarity]
drivers/media/i2c/m5mols/m5mols_capture.c [moved from drivers/media/video/m5mols/m5mols_capture.c with 96% similarity]
drivers/media/i2c/m5mols/m5mols_controls.c [moved from drivers/media/video/m5mols/m5mols_controls.c with 99% similarity]
drivers/media/i2c/m5mols/m5mols_core.c [moved from drivers/media/video/m5mols/m5mols_core.c with 91% similarity]
drivers/media/i2c/m5mols/m5mols_reg.h [moved from drivers/media/video/m5mols/m5mols_reg.h with 99% similarity]
drivers/media/i2c/msp3400-driver.c [moved from drivers/media/video/msp3400-driver.c with 98% similarity]
drivers/media/i2c/msp3400-driver.h [moved from drivers/media/video/msp3400-driver.h with 100% similarity]
drivers/media/i2c/msp3400-kthreads.c [moved from drivers/media/video/msp3400-kthreads.c with 100% similarity]
drivers/media/i2c/mt9m032.c [moved from drivers/media/video/mt9m032.c with 99% similarity]
drivers/media/i2c/mt9p031.c [moved from drivers/media/video/mt9p031.c with 97% similarity]
drivers/media/i2c/mt9t001.c [moved from drivers/media/video/mt9t001.c with 97% similarity]
drivers/media/i2c/mt9v011.c [moved from drivers/media/video/mt9v011.c with 100% similarity]
drivers/media/i2c/mt9v032.c [moved from drivers/media/video/mt9v032.c with 84% similarity]
drivers/media/i2c/noon010pc30.c [moved from drivers/media/video/noon010pc30.c with 100% similarity]
drivers/media/i2c/ov7670.c [moved from drivers/media/video/ov7670.c with 100% similarity]
drivers/media/i2c/s5k4ecgx.c [new file with mode: 0644]
drivers/media/i2c/s5k6aa.c [moved from drivers/media/video/s5k6aa.c with 99% similarity]
drivers/media/i2c/saa6588.c [moved from drivers/media/video/saa6588.c with 100% similarity]
drivers/media/i2c/saa7110.c [moved from drivers/media/video/saa7110.c with 100% similarity]
drivers/media/i2c/saa7115.c [moved from drivers/media/video/saa7115.c with 99% similarity]
drivers/media/i2c/saa711x_regs.h [moved from drivers/media/video/saa711x_regs.h with 100% similarity]
drivers/media/i2c/saa7127.c [moved from drivers/media/video/saa7127.c with 99% similarity]
drivers/media/i2c/saa717x.c [moved from drivers/media/video/saa717x.c with 100% similarity]
drivers/media/i2c/saa7185.c [moved from drivers/media/video/saa7185.c with 100% similarity]
drivers/media/i2c/saa7191.c [moved from drivers/media/video/saa7191.c with 100% similarity]
drivers/media/i2c/saa7191.h [moved from drivers/media/video/saa7191.h with 100% similarity]
drivers/media/i2c/smiapp-pll.c [moved from drivers/media/video/smiapp-pll.c with 99% similarity]
drivers/media/i2c/smiapp-pll.h [moved from drivers/media/video/smiapp-pll.h with 98% similarity]
drivers/media/i2c/smiapp/Kconfig [moved from drivers/media/video/smiapp/Kconfig with 100% similarity]
drivers/media/i2c/smiapp/Makefile [moved from drivers/media/video/smiapp/Makefile with 78% similarity]
drivers/media/i2c/smiapp/smiapp-core.c [moved from drivers/media/video/smiapp/smiapp-core.c with 98% similarity]
drivers/media/i2c/smiapp/smiapp-limits.c [moved from drivers/media/video/smiapp/smiapp-limits.c with 99% similarity]
drivers/media/i2c/smiapp/smiapp-limits.h [moved from drivers/media/video/smiapp/smiapp-limits.h with 99% similarity]
drivers/media/i2c/smiapp/smiapp-quirk.c [moved from drivers/media/video/smiapp/smiapp-quirk.c with 94% similarity]
drivers/media/i2c/smiapp/smiapp-quirk.h [moved from drivers/media/video/smiapp/smiapp-quirk.h with 98% similarity]
drivers/media/i2c/smiapp/smiapp-reg-defs.h [moved from drivers/media/video/smiapp/smiapp-reg-defs.h with 99% similarity]
drivers/media/i2c/smiapp/smiapp-reg.h [moved from drivers/media/video/smiapp/smiapp-reg.h with 98% similarity]
drivers/media/i2c/smiapp/smiapp-regs.c [moved from drivers/media/video/smiapp/smiapp-regs.c with 99% similarity]
drivers/media/i2c/smiapp/smiapp-regs.h [moved from drivers/media/video/smiapp/smiapp-regs.h with 100% similarity]
drivers/media/i2c/smiapp/smiapp.h [moved from drivers/media/video/smiapp/smiapp.h with 99% similarity]
drivers/media/i2c/soc_camera/Kconfig [new file with mode: 0644]
drivers/media/i2c/soc_camera/Makefile [new file with mode: 0644]
drivers/media/i2c/soc_camera/imx074.c [moved from drivers/media/video/imx074.c with 95% similarity]
drivers/media/i2c/soc_camera/mt9m001.c [moved from drivers/media/video/mt9m001.c with 97% similarity]
drivers/media/i2c/soc_camera/mt9m111.c [moved from drivers/media/video/mt9m111.c with 95% similarity]
drivers/media/i2c/soc_camera/mt9t031.c [moved from drivers/media/video/mt9t031.c with 97% similarity]
drivers/media/i2c/soc_camera/mt9t112.c [moved from drivers/media/video/mt9t112.c with 98% similarity]
drivers/media/i2c/soc_camera/mt9v022.c [moved from drivers/media/video/mt9v022.c with 93% similarity]
drivers/media/i2c/soc_camera/ov2640.c [moved from drivers/media/video/ov2640.c with 98% similarity]
drivers/media/i2c/soc_camera/ov5642.c [moved from drivers/media/video/ov5642.c with 96% similarity]
drivers/media/i2c/soc_camera/ov6650.c [moved from drivers/media/video/ov6650.c with 95% similarity]
drivers/media/i2c/soc_camera/ov772x.c [moved from drivers/media/video/ov772x.c with 81% similarity]
drivers/media/i2c/soc_camera/ov9640.c [moved from drivers/media/video/ov9640.c with 97% similarity]
drivers/media/i2c/soc_camera/ov9640.h [moved from drivers/media/video/ov9640.h with 100% similarity]
drivers/media/i2c/soc_camera/ov9740.c [moved from drivers/media/video/ov9740.c with 97% similarity]
drivers/media/i2c/soc_camera/rj54n1cb0c.c [moved from drivers/media/video/rj54n1cb0c.c with 98% similarity]
drivers/media/i2c/soc_camera/tw9910.c [moved from drivers/media/video/tw9910.c with 98% similarity]
drivers/media/i2c/sr030pc30.c [moved from drivers/media/video/sr030pc30.c with 100% similarity]
drivers/media/i2c/tcm825x.c [moved from drivers/media/video/tcm825x.c with 99% similarity]
drivers/media/i2c/tcm825x.h [moved from drivers/media/video/tcm825x.h with 99% similarity]
drivers/media/i2c/tda7432.c [moved from drivers/media/video/tda7432.c with 100% similarity]
drivers/media/i2c/tda9840.c [moved from drivers/media/video/tda9840.c with 100% similarity]
drivers/media/i2c/tea6415c.c [moved from drivers/media/video/tea6415c.c with 99% similarity]
drivers/media/i2c/tea6415c.h [moved from drivers/media/video/tea6415c.h with 100% similarity]
drivers/media/i2c/tea6420.c [moved from drivers/media/video/tea6420.c with 100% similarity]
drivers/media/i2c/tea6420.h [moved from drivers/media/video/tea6420.h with 100% similarity]
drivers/media/i2c/ths7303.c [moved from drivers/media/video/ths7303.c with 54% similarity]
drivers/media/i2c/tlv320aic23b.c [moved from drivers/media/video/tlv320aic23b.c with 100% similarity]
drivers/media/i2c/tvaudio.c [moved from drivers/media/video/tvaudio.c with 99% similarity]
drivers/media/i2c/tveeprom.c [moved from drivers/media/video/tveeprom.c with 100% similarity]
drivers/media/i2c/tvp514x.c [moved from drivers/media/video/tvp514x.c with 94% similarity]
drivers/media/i2c/tvp514x_regs.h [moved from drivers/media/video/tvp514x_regs.h with 99% similarity]
drivers/media/i2c/tvp5150.c [moved from drivers/media/video/tvp5150.c with 99% similarity]
drivers/media/i2c/tvp5150_reg.h [moved from drivers/media/video/tvp5150_reg.h with 100% similarity]
drivers/media/i2c/tvp7002.c [moved from drivers/media/video/tvp7002.c with 100% similarity]
drivers/media/i2c/tvp7002_reg.h [moved from drivers/media/video/tvp7002_reg.h with 100% similarity]
drivers/media/i2c/upd64031a.c [moved from drivers/media/video/upd64031a.c with 100% similarity]
drivers/media/i2c/upd64083.c [moved from drivers/media/video/upd64083.c with 100% similarity]
drivers/media/i2c/vp27smpx.c [moved from drivers/media/video/vp27smpx.c with 100% similarity]
drivers/media/i2c/vpx3220.c [moved from drivers/media/video/vpx3220.c with 100% similarity]
drivers/media/i2c/vs6624.c [moved from drivers/media/video/vs6624.c with 100% similarity]
drivers/media/i2c/vs6624_regs.h [moved from drivers/media/video/vs6624_regs.h with 100% similarity]
drivers/media/i2c/wm8739.c [moved from drivers/media/video/wm8739.c with 100% similarity]
drivers/media/i2c/wm8775.c [moved from drivers/media/video/wm8775.c with 100% similarity]
drivers/media/media-device.c
drivers/media/media-devnode.c
drivers/media/mmc/Kconfig [new file with mode: 0644]
drivers/media/mmc/Makefile [new file with mode: 0644]
drivers/media/mmc/siano/Kconfig [new file with mode: 0644]
drivers/media/mmc/siano/Makefile [new file with mode: 0644]
drivers/media/mmc/siano/smssdio.c [moved from drivers/media/dvb/siano/smssdio.c with 100% similarity]
drivers/media/parport/Kconfig [new file with mode: 0644]
drivers/media/parport/Makefile [new file with mode: 0644]
drivers/media/parport/bw-qcam.c [moved from drivers/media/video/bw-qcam.c with 100% similarity]
drivers/media/parport/c-qcam.c [moved from drivers/media/video/c-qcam.c with 100% similarity]
drivers/media/parport/pms.c [moved from drivers/media/video/pms.c with 100% similarity]
drivers/media/parport/w9966.c [moved from drivers/media/video/w9966.c with 100% similarity]
drivers/media/pci/Kconfig [new file with mode: 0644]
drivers/media/pci/Makefile [new file with mode: 0644]
drivers/media/pci/b2c2/Kconfig [new file with mode: 0644]
drivers/media/pci/b2c2/Makefile [new file with mode: 0644]
drivers/media/pci/b2c2/flexcop-dma.c [moved from drivers/media/dvb/b2c2/flexcop-dma.c with 100% similarity]
drivers/media/pci/b2c2/flexcop-pci.c [moved from drivers/media/dvb/b2c2/flexcop-pci.c with 100% similarity]
drivers/media/pci/bt8xx/Kconfig [new file with mode: 0644]
drivers/media/pci/bt8xx/Makefile [new file with mode: 0644]
drivers/media/pci/bt8xx/bt848.h [moved from drivers/media/video/bt8xx/bt848.h with 100% similarity]
drivers/media/pci/bt8xx/bt878.c [moved from drivers/media/dvb/bt8xx/bt878.c with 100% similarity]
drivers/media/pci/bt8xx/bt878.h [moved from drivers/media/dvb/bt8xx/bt878.h with 100% similarity]
drivers/media/pci/bt8xx/bttv-audio-hook.c [moved from drivers/media/video/bt8xx/bttv-audio-hook.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-audio-hook.h [moved from drivers/media/video/bt8xx/bttv-audio-hook.h with 100% similarity]
drivers/media/pci/bt8xx/bttv-cards.c [moved from drivers/media/video/bt8xx/bttv-cards.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-driver.c [moved from drivers/media/video/bt8xx/bttv-driver.c with 99% similarity]
drivers/media/pci/bt8xx/bttv-gpio.c [moved from drivers/media/video/bt8xx/bttv-gpio.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-i2c.c [moved from drivers/media/video/bt8xx/bttv-i2c.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-if.c [moved from drivers/media/video/bt8xx/bttv-if.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-input.c [moved from drivers/media/video/bt8xx/bttv-input.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-risc.c [moved from drivers/media/video/bt8xx/bttv-risc.c with 100% similarity]
drivers/media/pci/bt8xx/bttv-vbi.c [moved from drivers/media/video/bt8xx/bttv-vbi.c with 100% similarity]
drivers/media/pci/bt8xx/bttv.h [moved from drivers/media/video/bt8xx/bttv.h with 100% similarity]
drivers/media/pci/bt8xx/bttvp.h [moved from drivers/media/video/bt8xx/bttvp.h with 100% similarity]
drivers/media/pci/bt8xx/dst.c [moved from drivers/media/dvb/bt8xx/dst.c with 100% similarity]
drivers/media/pci/bt8xx/dst_ca.c [moved from drivers/media/dvb/bt8xx/dst_ca.c with 99% similarity]
drivers/media/pci/bt8xx/dst_ca.h [moved from drivers/media/dvb/bt8xx/dst_ca.h with 100% similarity]
drivers/media/pci/bt8xx/dst_common.h [moved from drivers/media/dvb/bt8xx/dst_common.h with 100% similarity]
drivers/media/pci/bt8xx/dst_priv.h [moved from drivers/media/dvb/bt8xx/dst_priv.h with 100% similarity]
drivers/media/pci/bt8xx/dvb-bt8xx.c [moved from drivers/media/dvb/bt8xx/dvb-bt8xx.c with 100% similarity]
drivers/media/pci/bt8xx/dvb-bt8xx.h [moved from drivers/media/dvb/bt8xx/dvb-bt8xx.h with 100% similarity]
drivers/media/pci/cx18/Kconfig [moved from drivers/media/video/cx18/Kconfig with 68% similarity]
drivers/media/pci/cx18/Makefile [moved from drivers/media/video/cx18/Makefile with 78% similarity]
drivers/media/pci/cx18/cx18-alsa-main.c [moved from drivers/media/video/cx18/cx18-alsa-main.c with 100% similarity]
drivers/media/pci/cx18/cx18-alsa-mixer.c [moved from drivers/media/video/cx18/cx18-alsa-mixer.c with 100% similarity]
drivers/media/pci/cx18/cx18-alsa-mixer.h [moved from drivers/media/video/cx18/cx18-alsa-mixer.h with 100% similarity]
drivers/media/pci/cx18/cx18-alsa-pcm.c [moved from drivers/media/video/cx18/cx18-alsa-pcm.c with 100% similarity]
drivers/media/pci/cx18/cx18-alsa-pcm.h [moved from drivers/media/video/cx18/cx18-alsa-pcm.h with 100% similarity]
drivers/media/pci/cx18/cx18-alsa.h [moved from drivers/media/video/cx18/cx18-alsa.h with 100% similarity]
drivers/media/pci/cx18/cx18-audio.c [moved from drivers/media/video/cx18/cx18-audio.c with 100% similarity]
drivers/media/pci/cx18/cx18-audio.h [moved from drivers/media/video/cx18/cx18-audio.h with 100% similarity]
drivers/media/pci/cx18/cx18-av-audio.c [moved from drivers/media/video/cx18/cx18-av-audio.c with 100% similarity]
drivers/media/pci/cx18/cx18-av-core.c [moved from drivers/media/video/cx18/cx18-av-core.c with 100% similarity]
drivers/media/pci/cx18/cx18-av-core.h [moved from drivers/media/video/cx18/cx18-av-core.h with 100% similarity]
drivers/media/pci/cx18/cx18-av-firmware.c [moved from drivers/media/video/cx18/cx18-av-firmware.c with 99% similarity]
drivers/media/pci/cx18/cx18-av-vbi.c [moved from drivers/media/video/cx18/cx18-av-vbi.c with 99% similarity]
drivers/media/pci/cx18/cx18-cards.c [moved from drivers/media/video/cx18/cx18-cards.c with 100% similarity]
drivers/media/pci/cx18/cx18-cards.h [moved from drivers/media/video/cx18/cx18-cards.h with 100% similarity]
drivers/media/pci/cx18/cx18-controls.c [moved from drivers/media/video/cx18/cx18-controls.c with 100% similarity]
drivers/media/pci/cx18/cx18-controls.h [moved from drivers/media/video/cx18/cx18-controls.h with 100% similarity]
drivers/media/pci/cx18/cx18-driver.c [moved from drivers/media/video/cx18/cx18-driver.c with 99% similarity]
drivers/media/pci/cx18/cx18-driver.h [moved from drivers/media/video/cx18/cx18-driver.h with 100% similarity]
drivers/media/pci/cx18/cx18-dvb.c [moved from drivers/media/video/cx18/cx18-dvb.c with 99% similarity]
drivers/media/pci/cx18/cx18-dvb.h [moved from drivers/media/video/cx18/cx18-dvb.h with 100% similarity]
drivers/media/pci/cx18/cx18-fileops.c [moved from drivers/media/video/cx18/cx18-fileops.c with 100% similarity]
drivers/media/pci/cx18/cx18-fileops.h [moved from drivers/media/video/cx18/cx18-fileops.h with 100% similarity]
drivers/media/pci/cx18/cx18-firmware.c [moved from drivers/media/video/cx18/cx18-firmware.c with 98% similarity]
drivers/media/pci/cx18/cx18-firmware.h [moved from drivers/media/video/cx18/cx18-firmware.h with 100% similarity]
drivers/media/pci/cx18/cx18-gpio.c [moved from drivers/media/video/cx18/cx18-gpio.c with 100% similarity]
drivers/media/pci/cx18/cx18-gpio.h [moved from drivers/media/video/cx18/cx18-gpio.h with 100% similarity]
drivers/media/pci/cx18/cx18-i2c.c [moved from drivers/media/video/cx18/cx18-i2c.c with 100% similarity]
drivers/media/pci/cx18/cx18-i2c.h [moved from drivers/media/video/cx18/cx18-i2c.h with 100% similarity]
drivers/media/pci/cx18/cx18-io.c [moved from drivers/media/video/cx18/cx18-io.c with 100% similarity]
drivers/media/pci/cx18/cx18-io.h [moved from drivers/media/video/cx18/cx18-io.h with 100% similarity]
drivers/media/pci/cx18/cx18-ioctl.c [moved from drivers/media/video/cx18/cx18-ioctl.c with 99% similarity]
drivers/media/pci/cx18/cx18-ioctl.h [moved from drivers/media/video/cx18/cx18-ioctl.h with 100% similarity]
drivers/media/pci/cx18/cx18-irq.c [moved from drivers/media/video/cx18/cx18-irq.c with 100% similarity]
drivers/media/pci/cx18/cx18-irq.h [moved from drivers/media/video/cx18/cx18-irq.h with 100% similarity]
drivers/media/pci/cx18/cx18-mailbox.c [moved from drivers/media/video/cx18/cx18-mailbox.c with 100% similarity]
drivers/media/pci/cx18/cx18-mailbox.h [moved from drivers/media/video/cx18/cx18-mailbox.h with 100% similarity]
drivers/media/pci/cx18/cx18-queue.c [moved from drivers/media/video/cx18/cx18-queue.c with 100% similarity]
drivers/media/pci/cx18/cx18-queue.h [moved from drivers/media/video/cx18/cx18-queue.h with 100% similarity]
drivers/media/pci/cx18/cx18-scb.c [moved from drivers/media/video/cx18/cx18-scb.c with 100% similarity]
drivers/media/pci/cx18/cx18-scb.h [moved from drivers/media/video/cx18/cx18-scb.h with 100% similarity]
drivers/media/pci/cx18/cx18-streams.c [moved from drivers/media/video/cx18/cx18-streams.c with 98% similarity]
drivers/media/pci/cx18/cx18-streams.h [moved from drivers/media/video/cx18/cx18-streams.h with 100% similarity]
drivers/media/pci/cx18/cx18-vbi.c [moved from drivers/media/video/cx18/cx18-vbi.c with 100% similarity]
drivers/media/pci/cx18/cx18-vbi.h [moved from drivers/media/video/cx18/cx18-vbi.h with 100% similarity]
drivers/media/pci/cx18/cx18-version.h [moved from drivers/media/video/cx18/cx18-version.h with 100% similarity]
drivers/media/pci/cx18/cx18-video.c [moved from drivers/media/video/cx18/cx18-video.c with 100% similarity]
drivers/media/pci/cx18/cx18-video.h [moved from drivers/media/video/cx18/cx18-video.h with 100% similarity]
drivers/media/pci/cx18/cx23418.h [moved from drivers/media/video/cx18/cx23418.h with 100% similarity]
drivers/media/pci/cx23885/Kconfig [new file with mode: 0644]
drivers/media/pci/cx23885/Makefile [moved from drivers/media/video/cx23885/Makefile with 72% similarity]
drivers/media/pci/cx23885/altera-ci.c [moved from drivers/media/video/cx23885/altera-ci.c with 99% similarity]
drivers/media/pci/cx23885/altera-ci.h [moved from drivers/media/video/cx23885/altera-ci.h with 100% similarity]
drivers/media/pci/cx23885/cimax2.c [moved from drivers/media/video/cx23885/cimax2.c with 100% similarity]
drivers/media/pci/cx23885/cimax2.h [moved from drivers/media/video/cx23885/cimax2.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-417.c [moved from drivers/media/video/cx23885/cx23885-417.c with 99% similarity]
drivers/media/pci/cx23885/cx23885-alsa.c [moved from drivers/media/video/cx23885/cx23885-alsa.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-av.c [moved from drivers/media/video/cx23885/cx23885-av.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-av.h [moved from drivers/media/video/cx23885/cx23885-av.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-cards.c [moved from drivers/media/video/cx23885/cx23885-cards.c with 98% similarity]
drivers/media/pci/cx23885/cx23885-core.c [moved from drivers/media/video/cx23885/cx23885-core.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-dvb.c [moved from drivers/media/video/cx23885/cx23885-dvb.c with 95% similarity]
drivers/media/pci/cx23885/cx23885-f300.c [moved from drivers/media/video/cx23885/cx23885-f300.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-f300.h [moved from drivers/media/video/cx23885/cx23885-f300.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-i2c.c [moved from drivers/media/video/cx23885/cx23885-i2c.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-input.c [moved from drivers/media/video/cx23885/cx23885-input.c with 96% similarity]
drivers/media/pci/cx23885/cx23885-input.h [moved from drivers/media/video/cx23885/cx23885-input.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-ioctl.c [moved from drivers/media/video/cx23885/cx23885-ioctl.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-ioctl.h [moved from drivers/media/video/cx23885/cx23885-ioctl.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-ir.c [moved from drivers/media/video/cx23885/cx23885-ir.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-ir.h [moved from drivers/media/video/cx23885/cx23885-ir.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-reg.h [moved from drivers/media/video/cx23885/cx23885-reg.h with 100% similarity]
drivers/media/pci/cx23885/cx23885-vbi.c [moved from drivers/media/video/cx23885/cx23885-vbi.c with 100% similarity]
drivers/media/pci/cx23885/cx23885-video.c [moved from drivers/media/video/cx23885/cx23885-video.c with 99% similarity]
drivers/media/pci/cx23885/cx23885.h [moved from drivers/media/video/cx23885/cx23885.h with 99% similarity]
drivers/media/pci/cx23885/cx23888-ir.c [moved from drivers/media/video/cx23885/cx23888-ir.c with 100% similarity]
drivers/media/pci/cx23885/cx23888-ir.h [moved from drivers/media/video/cx23885/cx23888-ir.h with 100% similarity]
drivers/media/pci/cx23885/netup-eeprom.c [moved from drivers/media/video/cx23885/netup-eeprom.c with 100% similarity]
drivers/media/pci/cx23885/netup-eeprom.h [moved from drivers/media/video/cx23885/netup-eeprom.h with 100% similarity]
drivers/media/pci/cx23885/netup-init.c [moved from drivers/media/video/cx23885/netup-init.c with 100% similarity]
drivers/media/pci/cx23885/netup-init.h [moved from drivers/media/video/cx23885/netup-init.h with 100% similarity]
drivers/media/pci/cx25821/Kconfig [moved from drivers/media/video/cx25821/Kconfig with 100% similarity]
drivers/media/pci/cx25821/Makefile [moved from drivers/media/video/cx25821/Makefile with 67% similarity]
drivers/media/pci/cx25821/cx25821-alsa.c [moved from drivers/media/video/cx25821/cx25821-alsa.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-audio-upstream.c [moved from drivers/media/video/cx25821/cx25821-audio-upstream.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-audio-upstream.h [moved from drivers/media/video/cx25821/cx25821-audio-upstream.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-audio.h [moved from drivers/media/video/cx25821/cx25821-audio.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-biffuncs.h [moved from drivers/media/video/cx25821/cx25821-biffuncs.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-cards.c [moved from drivers/media/video/cx25821/cx25821-cards.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-core.c [moved from drivers/media/video/cx25821/cx25821-core.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-gpio.c [moved from drivers/media/video/cx25821/cx25821-gpio.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-i2c.c [moved from drivers/media/video/cx25821/cx25821-i2c.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-medusa-defines.h [moved from drivers/media/video/cx25821/cx25821-medusa-defines.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-medusa-reg.h [moved from drivers/media/video/cx25821/cx25821-medusa-reg.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-medusa-video.c [moved from drivers/media/video/cx25821/cx25821-medusa-video.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-medusa-video.h [moved from drivers/media/video/cx25821/cx25821-medusa-video.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-reg.h [moved from drivers/media/video/cx25821/cx25821-reg.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-sram.h [moved from drivers/media/video/cx25821/cx25821-sram.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.c [moved from drivers/media/video/cx25821/cx25821-video-upstream-ch2.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-video-upstream-ch2.h [moved from drivers/media/video/cx25821/cx25821-video-upstream-ch2.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-video-upstream.c [moved from drivers/media/video/cx25821/cx25821-video-upstream.c with 100% similarity]
drivers/media/pci/cx25821/cx25821-video-upstream.h [moved from drivers/media/video/cx25821/cx25821-video-upstream.h with 100% similarity]
drivers/media/pci/cx25821/cx25821-video.c [moved from drivers/media/video/cx25821/cx25821-video.c with 99% similarity]
drivers/media/pci/cx25821/cx25821-video.h [moved from drivers/media/video/cx25821/cx25821-video.h with 99% similarity]
drivers/media/pci/cx25821/cx25821.h [moved from drivers/media/video/cx25821/cx25821.h with 100% similarity]
drivers/media/pci/cx88/Kconfig [moved from drivers/media/video/cx88/Kconfig with 70% similarity]
drivers/media/pci/cx88/Makefile [moved from drivers/media/video/cx88/Makefile with 73% similarity]
drivers/media/pci/cx88/cx88-alsa.c [moved from drivers/media/video/cx88/cx88-alsa.c with 99% similarity]
drivers/media/pci/cx88/cx88-blackbird.c [moved from drivers/media/video/cx88/cx88-blackbird.c with 99% similarity]
drivers/media/pci/cx88/cx88-cards.c [moved from drivers/media/video/cx88/cx88-cards.c with 99% similarity]
drivers/media/pci/cx88/cx88-core.c [moved from drivers/media/video/cx88/cx88-core.c with 99% similarity]
drivers/media/pci/cx88/cx88-dsp.c [moved from drivers/media/video/cx88/cx88-dsp.c with 100% similarity]
drivers/media/pci/cx88/cx88-dvb.c [moved from drivers/media/video/cx88/cx88-dvb.c with 99% similarity]
drivers/media/pci/cx88/cx88-i2c.c [moved from drivers/media/video/cx88/cx88-i2c.c with 100% similarity]
drivers/media/pci/cx88/cx88-input.c [moved from drivers/media/video/cx88/cx88-input.c with 100% similarity]
drivers/media/pci/cx88/cx88-mpeg.c [moved from drivers/media/video/cx88/cx88-mpeg.c with 100% similarity]
drivers/media/pci/cx88/cx88-reg.h [moved from drivers/media/video/cx88/cx88-reg.h with 100% similarity]
drivers/media/pci/cx88/cx88-tvaudio.c [moved from drivers/media/video/cx88/cx88-tvaudio.c with 100% similarity]
drivers/media/pci/cx88/cx88-vbi.c [moved from drivers/media/video/cx88/cx88-vbi.c with 100% similarity]
drivers/media/pci/cx88/cx88-video.c [moved from drivers/media/video/cx88/cx88-video.c with 99% similarity]
drivers/media/pci/cx88/cx88-vp3054-i2c.c [moved from drivers/media/video/cx88/cx88-vp3054-i2c.c with 100% similarity]
drivers/media/pci/cx88/cx88-vp3054-i2c.h [moved from drivers/media/video/cx88/cx88-vp3054-i2c.h with 100% similarity]
drivers/media/pci/cx88/cx88.h [moved from drivers/media/video/cx88/cx88.h with 99% similarity]
drivers/media/pci/ddbridge/Kconfig [moved from drivers/media/dvb/ddbridge/Kconfig with 60% similarity]
drivers/media/pci/ddbridge/Makefile [moved from drivers/media/dvb/ddbridge/Makefile with 61% similarity]
drivers/media/pci/ddbridge/ddbridge-core.c [moved from drivers/media/dvb/ddbridge/ddbridge-core.c with 99% similarity]
drivers/media/pci/ddbridge/ddbridge-regs.h [moved from drivers/media/dvb/ddbridge/ddbridge-regs.h with 100% similarity]
drivers/media/pci/ddbridge/ddbridge.h [moved from drivers/media/dvb/ddbridge/ddbridge.h with 100% similarity]
drivers/media/pci/dm1105/Kconfig [moved from drivers/media/dvb/dm1105/Kconfig with 57% similarity]
drivers/media/pci/dm1105/Makefile [new file with mode: 0644]
drivers/media/pci/dm1105/dm1105.c [moved from drivers/media/dvb/dm1105/dm1105.c with 100% similarity]
drivers/media/pci/ivtv/Kconfig [moved from drivers/media/video/ivtv/Kconfig with 67% similarity]
drivers/media/pci/ivtv/Makefile [moved from drivers/media/video/ivtv/Makefile with 53% similarity]
drivers/media/pci/ivtv/ivtv-alsa-main.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-alsa-mixer.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-alsa-mixer.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-alsa-pcm.c [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-alsa-pcm.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-alsa.h [new file with mode: 0644]
drivers/media/pci/ivtv/ivtv-cards.c [moved from drivers/media/video/ivtv/ivtv-cards.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-cards.h [moved from drivers/media/video/ivtv/ivtv-cards.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-controls.c [moved from drivers/media/video/ivtv/ivtv-controls.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-controls.h [moved from drivers/media/video/ivtv/ivtv-controls.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-driver.c [moved from drivers/media/video/ivtv/ivtv-driver.c with 97% similarity]
drivers/media/pci/ivtv/ivtv-driver.h [moved from drivers/media/video/ivtv/ivtv-driver.h with 98% similarity]
drivers/media/pci/ivtv/ivtv-fileops.c [moved from drivers/media/video/ivtv/ivtv-fileops.c with 96% similarity]
drivers/media/pci/ivtv/ivtv-fileops.h [moved from drivers/media/video/ivtv/ivtv-fileops.h with 94% similarity]
drivers/media/pci/ivtv/ivtv-firmware.c [moved from drivers/media/video/ivtv/ivtv-firmware.c with 98% similarity]
drivers/media/pci/ivtv/ivtv-firmware.h [moved from drivers/media/video/ivtv/ivtv-firmware.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-gpio.c [moved from drivers/media/video/ivtv/ivtv-gpio.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-gpio.h [moved from drivers/media/video/ivtv/ivtv-gpio.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-i2c.c [moved from drivers/media/video/ivtv/ivtv-i2c.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-i2c.h [moved from drivers/media/video/ivtv/ivtv-i2c.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-ioctl.c [moved from drivers/media/video/ivtv/ivtv-ioctl.c with 95% similarity]
drivers/media/pci/ivtv/ivtv-ioctl.h [moved from drivers/media/video/ivtv/ivtv-ioctl.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-irq.c [moved from drivers/media/video/ivtv/ivtv-irq.c with 95% similarity]
drivers/media/pci/ivtv/ivtv-irq.h [moved from drivers/media/video/ivtv/ivtv-irq.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-mailbox.c [moved from drivers/media/video/ivtv/ivtv-mailbox.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-mailbox.h [moved from drivers/media/video/ivtv/ivtv-mailbox.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-queue.c [moved from drivers/media/video/ivtv/ivtv-queue.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-queue.h [moved from drivers/media/video/ivtv/ivtv-queue.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-routing.c [moved from drivers/media/video/ivtv/ivtv-routing.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-routing.h [moved from drivers/media/video/ivtv/ivtv-routing.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-streams.c [moved from drivers/media/video/ivtv/ivtv-streams.c with 95% similarity]
drivers/media/pci/ivtv/ivtv-streams.h [moved from drivers/media/video/ivtv/ivtv-streams.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-udma.c [moved from drivers/media/video/ivtv/ivtv-udma.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-udma.h [moved from drivers/media/video/ivtv/ivtv-udma.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-vbi.c [moved from drivers/media/video/ivtv/ivtv-vbi.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-vbi.h [moved from drivers/media/video/ivtv/ivtv-vbi.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-version.h [moved from drivers/media/video/ivtv/ivtv-version.h with 100% similarity]
drivers/media/pci/ivtv/ivtv-yuv.c [moved from drivers/media/video/ivtv/ivtv-yuv.c with 100% similarity]
drivers/media/pci/ivtv/ivtv-yuv.h [moved from drivers/media/video/ivtv/ivtv-yuv.h with 100% similarity]
drivers/media/pci/ivtv/ivtvfb.c [moved from drivers/media/video/ivtv/ivtvfb.c with 100% similarity]
drivers/media/pci/mantis/Kconfig [moved from drivers/media/dvb/mantis/Kconfig with 62% similarity]
drivers/media/pci/mantis/Makefile [moved from drivers/media/dvb/mantis/Makefile with 88% similarity]
drivers/media/pci/mantis/hopper_cards.c [moved from drivers/media/dvb/mantis/hopper_cards.c with 100% similarity]
drivers/media/pci/mantis/hopper_vp3028.c [moved from drivers/media/dvb/mantis/hopper_vp3028.c with 100% similarity]
drivers/media/pci/mantis/hopper_vp3028.h [moved from drivers/media/dvb/mantis/hopper_vp3028.h with 100% similarity]
drivers/media/pci/mantis/mantis_ca.c [moved from drivers/media/dvb/mantis/mantis_ca.c with 100% similarity]
drivers/media/pci/mantis/mantis_ca.h [moved from drivers/media/dvb/mantis/mantis_ca.h with 100% similarity]
drivers/media/pci/mantis/mantis_cards.c [moved from drivers/media/dvb/mantis/mantis_cards.c with 99% similarity]
drivers/media/pci/mantis/mantis_common.h [moved from drivers/media/dvb/mantis/mantis_common.h with 100% similarity]
drivers/media/pci/mantis/mantis_core.c [moved from drivers/media/dvb/mantis/mantis_core.c with 99% similarity]
drivers/media/pci/mantis/mantis_core.h [moved from drivers/media/dvb/mantis/mantis_core.h with 100% similarity]
drivers/media/pci/mantis/mantis_dma.c [moved from drivers/media/dvb/mantis/mantis_dma.c with 100% similarity]
drivers/media/pci/mantis/mantis_dma.h [moved from drivers/media/dvb/mantis/mantis_dma.h with 100% similarity]
drivers/media/pci/mantis/mantis_dvb.c [moved from drivers/media/dvb/mantis/mantis_dvb.c with 98% similarity]
drivers/media/pci/mantis/mantis_dvb.h [moved from drivers/media/dvb/mantis/mantis_dvb.h with 100% similarity]
drivers/media/pci/mantis/mantis_evm.c [moved from drivers/media/dvb/mantis/mantis_evm.c with 100% similarity]
drivers/media/pci/mantis/mantis_hif.c [moved from drivers/media/dvb/mantis/mantis_hif.c with 100% similarity]
drivers/media/pci/mantis/mantis_hif.h [moved from drivers/media/dvb/mantis/mantis_hif.h with 100% similarity]
drivers/media/pci/mantis/mantis_i2c.c [moved from drivers/media/dvb/mantis/mantis_i2c.c with 100% similarity]
drivers/media/pci/mantis/mantis_i2c.h [moved from drivers/media/dvb/mantis/mantis_i2c.h with 100% similarity]
drivers/media/pci/mantis/mantis_input.c [moved from drivers/media/dvb/mantis/mantis_input.c with 100% similarity]
drivers/media/pci/mantis/mantis_ioc.c [moved from drivers/media/dvb/mantis/mantis_ioc.c with 100% similarity]
drivers/media/pci/mantis/mantis_ioc.h [moved from drivers/media/dvb/mantis/mantis_ioc.h with 100% similarity]
drivers/media/pci/mantis/mantis_link.h [moved from drivers/media/dvb/mantis/mantis_link.h with 100% similarity]
drivers/media/pci/mantis/mantis_pci.c [moved from drivers/media/dvb/mantis/mantis_pci.c with 100% similarity]
drivers/media/pci/mantis/mantis_pci.h [moved from drivers/media/dvb/mantis/mantis_pci.h with 100% similarity]
drivers/media/pci/mantis/mantis_pcmcia.c [moved from drivers/media/dvb/mantis/mantis_pcmcia.c with 100% similarity]
drivers/media/pci/mantis/mantis_reg.h [moved from drivers/media/dvb/mantis/mantis_reg.h with 100% similarity]
drivers/media/pci/mantis/mantis_uart.c [moved from drivers/media/dvb/mantis/mantis_uart.c with 100% similarity]
drivers/media/pci/mantis/mantis_uart.h [moved from drivers/media/dvb/mantis/mantis_uart.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp1033.c [moved from drivers/media/dvb/mantis/mantis_vp1033.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp1033.h [moved from drivers/media/dvb/mantis/mantis_vp1033.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp1034.c [moved from drivers/media/dvb/mantis/mantis_vp1034.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp1034.h [moved from drivers/media/dvb/mantis/mantis_vp1034.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp1041.c [moved from drivers/media/dvb/mantis/mantis_vp1041.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp1041.h [moved from drivers/media/dvb/mantis/mantis_vp1041.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp2033.c [moved from drivers/media/dvb/mantis/mantis_vp2033.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp2033.h [moved from drivers/media/dvb/mantis/mantis_vp2033.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp2040.c [moved from drivers/media/dvb/mantis/mantis_vp2040.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp2040.h [moved from drivers/media/dvb/mantis/mantis_vp2040.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp3028.c [moved from drivers/media/dvb/mantis/mantis_vp3028.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp3028.h [moved from drivers/media/dvb/mantis/mantis_vp3028.h with 100% similarity]
drivers/media/pci/mantis/mantis_vp3030.c [moved from drivers/media/dvb/mantis/mantis_vp3030.c with 100% similarity]
drivers/media/pci/mantis/mantis_vp3030.h [moved from drivers/media/dvb/mantis/mantis_vp3030.h with 100% similarity]
drivers/media/pci/meye/Kconfig [new file with mode: 0644]
drivers/media/pci/meye/Makefile [new file with mode: 0644]
drivers/media/pci/meye/meye.c [moved from drivers/media/video/meye.c with 100% similarity]
drivers/media/pci/meye/meye.h [moved from drivers/media/video/meye.h with 100% similarity]
drivers/media/pci/ngene/Kconfig [new file with mode: 0644]
drivers/media/pci/ngene/Makefile [moved from drivers/media/dvb/ngene/Makefile with 63% similarity]
drivers/media/pci/ngene/ngene-cards.c [moved from drivers/media/dvb/ngene/ngene-cards.c with 71% similarity]
drivers/media/pci/ngene/ngene-core.c [moved from drivers/media/dvb/ngene/ngene-core.c with 98% similarity]
drivers/media/pci/ngene/ngene-dvb.c [moved from drivers/media/dvb/ngene/ngene-dvb.c with 100% similarity]
drivers/media/pci/ngene/ngene-i2c.c [moved from drivers/media/dvb/ngene/ngene-i2c.c with 100% similarity]
drivers/media/pci/ngene/ngene.h [moved from drivers/media/dvb/ngene/ngene.h with 100% similarity]
drivers/media/pci/pluto2/Kconfig [moved from drivers/media/dvb/pluto2/Kconfig with 100% similarity]
drivers/media/pci/pluto2/Makefile [new file with mode: 0644]
drivers/media/pci/pluto2/pluto2.c [moved from drivers/media/dvb/pluto2/pluto2.c with 100% similarity]
drivers/media/pci/pt1/Kconfig [moved from drivers/media/dvb/pt1/Kconfig with 100% similarity]
drivers/media/pci/pt1/Makefile [moved from drivers/media/dvb/pt1/Makefile with 56% similarity]
drivers/media/pci/pt1/pt1.c [moved from drivers/media/dvb/pt1/pt1.c with 100% similarity]
drivers/media/pci/pt1/va1j5jf8007s.c [moved from drivers/media/dvb/pt1/va1j5jf8007s.c with 98% similarity]
drivers/media/pci/pt1/va1j5jf8007s.h [moved from drivers/media/dvb/pt1/va1j5jf8007s.h with 100% similarity]
drivers/media/pci/pt1/va1j5jf8007t.c [moved from drivers/media/dvb/pt1/va1j5jf8007t.c with 100% similarity]
drivers/media/pci/pt1/va1j5jf8007t.h [moved from drivers/media/dvb/pt1/va1j5jf8007t.h with 100% similarity]
drivers/media/pci/saa7134/Kconfig [moved from drivers/media/video/saa7134/Kconfig with 56% similarity]
drivers/media/pci/saa7134/Makefile [moved from drivers/media/video/saa7134/Makefile with 54% similarity]
drivers/media/pci/saa7134/saa6752hs.c [moved from drivers/media/video/saa7134/saa6752hs.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-alsa.c [moved from drivers/media/video/saa7134/saa7134-alsa.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-cards.c [moved from drivers/media/video/saa7134/saa7134-cards.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-core.c [moved from drivers/media/video/saa7134/saa7134-core.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-dvb.c [moved from drivers/media/video/saa7134/saa7134-dvb.c with 99% similarity]
drivers/media/pci/saa7134/saa7134-empress.c [moved from drivers/media/video/saa7134/saa7134-empress.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-i2c.c [moved from drivers/media/video/saa7134/saa7134-i2c.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-input.c [moved from drivers/media/video/saa7134/saa7134-input.c with 99% similarity]
drivers/media/pci/saa7134/saa7134-reg.h [moved from drivers/media/video/saa7134/saa7134-reg.h with 100% similarity]
drivers/media/pci/saa7134/saa7134-ts.c [moved from drivers/media/video/saa7134/saa7134-ts.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-tvaudio.c [moved from drivers/media/video/saa7134/saa7134-tvaudio.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-vbi.c [moved from drivers/media/video/saa7134/saa7134-vbi.c with 100% similarity]
drivers/media/pci/saa7134/saa7134-video.c [moved from drivers/media/video/saa7134/saa7134-video.c with 98% similarity]
drivers/media/pci/saa7134/saa7134.h [moved from drivers/media/video/saa7134/saa7134.h with 99% similarity]
drivers/media/pci/saa7146/Kconfig [new file with mode: 0644]
drivers/media/pci/saa7146/Makefile [new file with mode: 0644]
drivers/media/pci/saa7146/hexium_gemini.c [moved from drivers/media/video/hexium_gemini.c with 100% similarity]
drivers/media/pci/saa7146/hexium_orion.c [moved from drivers/media/video/hexium_orion.c with 100% similarity]
drivers/media/pci/saa7146/mxb.c [moved from drivers/media/video/mxb.c with 99% similarity]
drivers/media/pci/saa7164/Kconfig [moved from drivers/media/video/saa7164/Kconfig with 62% similarity]
drivers/media/pci/saa7164/Makefile [moved from drivers/media/video/saa7164/Makefile with 57% similarity]
drivers/media/pci/saa7164/saa7164-api.c [moved from drivers/media/video/saa7164/saa7164-api.c with 98% similarity]
drivers/media/pci/saa7164/saa7164-buffer.c [moved from drivers/media/video/saa7164/saa7164-buffer.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-bus.c [moved from drivers/media/video/saa7164/saa7164-bus.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-cards.c [moved from drivers/media/video/saa7164/saa7164-cards.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-cmd.c [moved from drivers/media/video/saa7164/saa7164-cmd.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-core.c [moved from drivers/media/video/saa7164/saa7164-core.c with 96% similarity]
drivers/media/pci/saa7164/saa7164-dvb.c [moved from drivers/media/video/saa7164/saa7164-dvb.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-encoder.c [moved from drivers/media/video/saa7164/saa7164-encoder.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-fw.c [moved from drivers/media/video/saa7164/saa7164-fw.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-i2c.c [moved from drivers/media/video/saa7164/saa7164-i2c.c with 100% similarity]
drivers/media/pci/saa7164/saa7164-reg.h [moved from drivers/media/video/saa7164/saa7164-reg.h with 100% similarity]
drivers/media/pci/saa7164/saa7164-types.h [moved from drivers/media/video/saa7164/saa7164-types.h with 100% similarity]
drivers/media/pci/saa7164/saa7164-vbi.c [moved from drivers/media/video/saa7164/saa7164-vbi.c with 100% similarity]
drivers/media/pci/saa7164/saa7164.h [moved from drivers/media/video/saa7164/saa7164.h with 99% similarity]
drivers/media/pci/sta2x11/Kconfig [new file with mode: 0644]
drivers/media/pci/sta2x11/Makefile [new file with mode: 0644]
drivers/media/pci/sta2x11/sta2x11_vip.c [moved from drivers/media/video/sta2x11_vip.c with 100% similarity]
drivers/media/pci/sta2x11/sta2x11_vip.h [moved from drivers/media/video/sta2x11_vip.h with 100% similarity]
drivers/media/pci/ttpci/Kconfig [moved from drivers/media/dvb/ttpci/Kconfig with 66% similarity]
drivers/media/pci/ttpci/Makefile [moved from drivers/media/dvb/ttpci/Makefile with 82% similarity]
drivers/media/pci/ttpci/av7110.c [moved from drivers/media/dvb/ttpci/av7110.c with 100% similarity]
drivers/media/pci/ttpci/av7110.h [moved from drivers/media/dvb/ttpci/av7110.h with 100% similarity]
drivers/media/pci/ttpci/av7110_av.c [moved from drivers/media/dvb/ttpci/av7110_av.c with 100% similarity]
drivers/media/pci/ttpci/av7110_av.h [moved from drivers/media/dvb/ttpci/av7110_av.h with 100% similarity]
drivers/media/pci/ttpci/av7110_ca.c [moved from drivers/media/dvb/ttpci/av7110_ca.c with 100% similarity]
drivers/media/pci/ttpci/av7110_ca.h [moved from drivers/media/dvb/ttpci/av7110_ca.h with 100% similarity]
drivers/media/pci/ttpci/av7110_hw.c [moved from drivers/media/dvb/ttpci/av7110_hw.c with 100% similarity]
drivers/media/pci/ttpci/av7110_hw.h [moved from drivers/media/dvb/ttpci/av7110_hw.h with 100% similarity]
drivers/media/pci/ttpci/av7110_ipack.c [moved from drivers/media/dvb/ttpci/av7110_ipack.c with 100% similarity]
drivers/media/pci/ttpci/av7110_ipack.h [moved from drivers/media/dvb/ttpci/av7110_ipack.h with 100% similarity]
drivers/media/pci/ttpci/av7110_ir.c [moved from drivers/media/dvb/ttpci/av7110_ir.c with 100% similarity]
drivers/media/pci/ttpci/av7110_v4l.c [moved from drivers/media/dvb/ttpci/av7110_v4l.c with 99% similarity]
drivers/media/pci/ttpci/budget-av.c [moved from drivers/media/dvb/ttpci/budget-av.c with 100% similarity]
drivers/media/pci/ttpci/budget-ci.c [moved from drivers/media/dvb/ttpci/budget-ci.c with 100% similarity]
drivers/media/pci/ttpci/budget-core.c [moved from drivers/media/dvb/ttpci/budget-core.c with 100% similarity]
drivers/media/pci/ttpci/budget-patch.c [moved from drivers/media/dvb/ttpci/budget-patch.c with 100% similarity]
drivers/media/pci/ttpci/budget.c [moved from drivers/media/dvb/ttpci/budget.c with 91% similarity]
drivers/media/pci/ttpci/budget.h [moved from drivers/media/dvb/ttpci/budget.h with 100% similarity]
drivers/media/pci/ttpci/ttpci-eeprom.c [moved from drivers/media/dvb/ttpci/ttpci-eeprom.c with 100% similarity]
drivers/media/pci/ttpci/ttpci-eeprom.h [moved from drivers/media/dvb/ttpci/ttpci-eeprom.h with 100% similarity]
drivers/media/pci/zoran/Kconfig [moved from drivers/media/video/zoran/Kconfig with 71% similarity]
drivers/media/pci/zoran/Makefile [moved from drivers/media/video/zoran/Makefile with 100% similarity]
drivers/media/pci/zoran/videocodec.c [moved from drivers/media/video/zoran/videocodec.c with 100% similarity]
drivers/media/pci/zoran/videocodec.h [moved from drivers/media/video/zoran/videocodec.h with 100% similarity]
drivers/media/pci/zoran/zoran.h [moved from drivers/media/video/zoran/zoran.h with 100% similarity]
drivers/media/pci/zoran/zoran_card.c [moved from drivers/media/video/zoran/zoran_card.c with 99% similarity]
drivers/media/pci/zoran/zoran_card.h [moved from drivers/media/video/zoran/zoran_card.h with 100% similarity]
drivers/media/pci/zoran/zoran_device.c [moved from drivers/media/video/zoran/zoran_device.c with 100% similarity]
drivers/media/pci/zoran/zoran_device.h [moved from drivers/media/video/zoran/zoran_device.h with 100% similarity]
drivers/media/pci/zoran/zoran_driver.c [moved from drivers/media/video/zoran/zoran_driver.c with 99% similarity]
drivers/media/pci/zoran/zoran_procfs.c [moved from drivers/media/video/zoran/zoran_procfs.c with 100% similarity]
drivers/media/pci/zoran/zoran_procfs.h [moved from drivers/media/video/zoran/zoran_procfs.h with 100% similarity]
drivers/media/pci/zoran/zr36016.c [moved from drivers/media/video/zoran/zr36016.c with 100% similarity]
drivers/media/pci/zoran/zr36016.h [moved from drivers/media/video/zoran/zr36016.h with 100% similarity]
drivers/media/pci/zoran/zr36050.c [moved from drivers/media/video/zoran/zr36050.c with 100% similarity]
drivers/media/pci/zoran/zr36050.h [moved from drivers/media/video/zoran/zr36050.h with 100% similarity]
drivers/media/pci/zoran/zr36057.h [moved from drivers/media/video/zoran/zr36057.h with 100% similarity]
drivers/media/pci/zoran/zr36060.c [moved from drivers/media/video/zoran/zr36060.c with 100% similarity]
drivers/media/pci/zoran/zr36060.h [moved from drivers/media/video/zoran/zr36060.h with 100% similarity]
drivers/media/platform/Kconfig [new file with mode: 0644]
drivers/media/platform/Makefile [new file with mode: 0644]
drivers/media/platform/arv.c [moved from drivers/media/video/arv.c with 100% similarity]
drivers/media/platform/blackfin/Kconfig [moved from drivers/media/video/blackfin/Kconfig with 100% similarity]
drivers/media/platform/blackfin/Makefile [moved from drivers/media/video/blackfin/Makefile with 100% similarity]
drivers/media/platform/blackfin/bfin_capture.c [moved from drivers/media/video/blackfin/bfin_capture.c with 98% similarity]
drivers/media/platform/blackfin/ppi.c [moved from drivers/media/video/blackfin/ppi.c with 100% similarity]
drivers/media/platform/coda.c [new file with mode: 0644]
drivers/media/platform/coda.h [new file with mode: 0644]
drivers/media/platform/davinci/Kconfig [moved from drivers/media/video/davinci/Kconfig with 97% similarity]
drivers/media/platform/davinci/Makefile [moved from drivers/media/video/davinci/Makefile with 100% similarity]
drivers/media/platform/davinci/ccdc_hw_device.h [moved from drivers/media/video/davinci/ccdc_hw_device.h with 100% similarity]
drivers/media/platform/davinci/dm355_ccdc.c [moved from drivers/media/video/davinci/dm355_ccdc.c with 99% similarity]
drivers/media/platform/davinci/dm355_ccdc_regs.h [moved from drivers/media/video/davinci/dm355_ccdc_regs.h with 100% similarity]
drivers/media/platform/davinci/dm644x_ccdc.c [moved from drivers/media/video/davinci/dm644x_ccdc.c with 99% similarity]
drivers/media/platform/davinci/dm644x_ccdc_regs.h [moved from drivers/media/video/davinci/dm644x_ccdc_regs.h with 100% similarity]
drivers/media/platform/davinci/isif.c [moved from drivers/media/video/davinci/isif.c with 99% similarity]
drivers/media/platform/davinci/isif_regs.h [moved from drivers/media/video/davinci/isif_regs.h with 100% similarity]
drivers/media/platform/davinci/vpbe.c [moved from drivers/media/video/davinci/vpbe.c with 90% similarity]
drivers/media/platform/davinci/vpbe_display.c [moved from drivers/media/video/davinci/vpbe_display.c with 95% similarity]
drivers/media/platform/davinci/vpbe_osd.c [moved from drivers/media/video/davinci/vpbe_osd.c with 100% similarity]
drivers/media/platform/davinci/vpbe_osd_regs.h [moved from drivers/media/video/davinci/vpbe_osd_regs.h with 100% similarity]
drivers/media/platform/davinci/vpbe_venc.c [moved from drivers/media/video/davinci/vpbe_venc.c with 96% similarity]
drivers/media/platform/davinci/vpbe_venc_regs.h [moved from drivers/media/video/davinci/vpbe_venc_regs.h with 100% similarity]
drivers/media/platform/davinci/vpfe_capture.c [moved from drivers/media/video/davinci/vpfe_capture.c with 98% similarity]
drivers/media/platform/davinci/vpif.c [moved from drivers/media/video/davinci/vpif.c with 96% similarity]
drivers/media/platform/davinci/vpif.h [moved from drivers/media/video/davinci/vpif.h with 99% similarity]
drivers/media/platform/davinci/vpif_capture.c [moved from drivers/media/video/davinci/vpif_capture.c with 88% similarity]
drivers/media/platform/davinci/vpif_capture.h [moved from drivers/media/video/davinci/vpif_capture.h with 91% similarity]
drivers/media/platform/davinci/vpif_display.c [moved from drivers/media/video/davinci/vpif_display.c with 89% similarity]
drivers/media/platform/davinci/vpif_display.h [moved from drivers/media/video/davinci/vpif_display.h with 91% similarity]
drivers/media/platform/davinci/vpss.c [moved from drivers/media/video/davinci/vpss.c with 99% similarity]
drivers/media/platform/exynos-gsc/Makefile [new file with mode: 0644]
drivers/media/platform/exynos-gsc/gsc-core.c [new file with mode: 0644]
drivers/media/platform/exynos-gsc/gsc-core.h [new file with mode: 0644]
drivers/media/platform/exynos-gsc/gsc-m2m.c [new file with mode: 0644]
drivers/media/platform/exynos-gsc/gsc-regs.c [new file with mode: 0644]
drivers/media/platform/exynos-gsc/gsc-regs.h [new file with mode: 0644]
drivers/media/platform/fsl-viu.c [moved from drivers/media/video/fsl-viu.c with 98% similarity]
drivers/media/platform/indycam.c [moved from drivers/media/video/indycam.c with 100% similarity]
drivers/media/platform/indycam.h [moved from drivers/media/video/indycam.h with 100% similarity]
drivers/media/platform/m2m-deinterlace.c [new file with mode: 0644]
drivers/media/platform/marvell-ccic/Kconfig [moved from drivers/media/video/marvell-ccic/Kconfig with 100% similarity]
drivers/media/platform/marvell-ccic/Makefile [moved from drivers/media/video/marvell-ccic/Makefile with 100% similarity]
drivers/media/platform/marvell-ccic/cafe-driver.c [moved from drivers/media/video/marvell-ccic/cafe-driver.c with 100% similarity]
drivers/media/platform/marvell-ccic/mcam-core.c [moved from drivers/media/video/marvell-ccic/mcam-core.c with 100% similarity]
drivers/media/platform/marvell-ccic/mcam-core.h [moved from drivers/media/video/marvell-ccic/mcam-core.h with 100% similarity]
drivers/media/platform/marvell-ccic/mmp-driver.c [moved from drivers/media/video/marvell-ccic/mmp-driver.c with 100% similarity]
drivers/media/platform/mem2mem_testdev.c [moved from drivers/media/video/mem2mem_testdev.c with 97% similarity]
drivers/media/platform/mx2_emmaprp.c [moved from drivers/media/video/mx2_emmaprp.c with 94% similarity]
drivers/media/platform/omap/Kconfig [moved from drivers/media/video/omap/Kconfig with 100% similarity]
drivers/media/platform/omap/Makefile [moved from drivers/media/video/omap/Makefile with 81% similarity]
drivers/media/platform/omap/omap_vout.c [moved from drivers/media/video/omap/omap_vout.c with 99% similarity]
drivers/media/platform/omap/omap_vout_vrfb.c [moved from drivers/media/video/omap/omap_vout_vrfb.c with 100% similarity]
drivers/media/platform/omap/omap_vout_vrfb.h [moved from drivers/media/video/omap/omap_vout_vrfb.h with 100% similarity]
drivers/media/platform/omap/omap_voutdef.h [moved from drivers/media/video/omap/omap_voutdef.h with 100% similarity]
drivers/media/platform/omap/omap_voutlib.c [moved from drivers/media/video/omap/omap_voutlib.c with 100% similarity]
drivers/media/platform/omap/omap_voutlib.h [moved from drivers/media/video/omap/omap_voutlib.h with 100% similarity]
drivers/media/platform/omap24xxcam-dma.c [moved from drivers/media/video/omap24xxcam-dma.c with 99% similarity]
drivers/media/platform/omap24xxcam.c [moved from drivers/media/video/omap24xxcam.c with 99% similarity]
drivers/media/platform/omap24xxcam.h [moved from drivers/media/video/omap24xxcam.h with 99% similarity]
drivers/media/platform/omap3isp/Makefile [moved from drivers/media/video/omap3isp/Makefile with 100% similarity]
drivers/media/platform/omap3isp/cfa_coef_table.h [moved from drivers/media/video/omap3isp/cfa_coef_table.h with 91% similarity]
drivers/media/platform/omap3isp/gamma_table.h [moved from drivers/media/video/omap3isp/gamma_table.h with 100% similarity]
drivers/media/platform/omap3isp/isp.c [moved from drivers/media/video/omap3isp/isp.c with 98% similarity]
drivers/media/platform/omap3isp/isp.h [moved from drivers/media/video/omap3isp/isp.h with 97% similarity]
drivers/media/platform/omap3isp/ispccdc.c [moved from drivers/media/video/omap3isp/ispccdc.c with 93% similarity]
drivers/media/platform/omap3isp/ispccdc.h [moved from drivers/media/video/omap3isp/ispccdc.h with 83% similarity]
drivers/media/platform/omap3isp/ispccp2.c [moved from drivers/media/video/omap3isp/ispccp2.c with 100% similarity]
drivers/media/platform/omap3isp/ispccp2.h [moved from drivers/media/video/omap3isp/ispccp2.h with 100% similarity]
drivers/media/platform/omap3isp/ispcsi2.c [moved from drivers/media/video/omap3isp/ispcsi2.c with 98% similarity]
drivers/media/platform/omap3isp/ispcsi2.h [moved from drivers/media/video/omap3isp/ispcsi2.h with 100% similarity]
drivers/media/platform/omap3isp/ispcsiphy.c [moved from drivers/media/video/omap3isp/ispcsiphy.c with 100% similarity]
drivers/media/platform/omap3isp/ispcsiphy.h [moved from drivers/media/video/omap3isp/ispcsiphy.h with 100% similarity]
drivers/media/platform/omap3isp/isph3a.h [moved from drivers/media/video/omap3isp/isph3a.h with 100% similarity]
drivers/media/platform/omap3isp/isph3a_aewb.c [moved from drivers/media/video/omap3isp/isph3a_aewb.c with 96% similarity]
drivers/media/platform/omap3isp/isph3a_af.c [moved from drivers/media/video/omap3isp/isph3a_af.c with 96% similarity]
drivers/media/platform/omap3isp/isphist.c [moved from drivers/media/video/omap3isp/isphist.c with 98% similarity]
drivers/media/platform/omap3isp/isphist.h [moved from drivers/media/video/omap3isp/isphist.h with 100% similarity]
drivers/media/platform/omap3isp/isppreview.c [moved from drivers/media/video/omap3isp/isppreview.c with 89% similarity]
drivers/media/platform/omap3isp/isppreview.h [moved from drivers/media/video/omap3isp/isppreview.h with 99% similarity]
drivers/media/platform/omap3isp/ispqueue.c [moved from drivers/media/video/omap3isp/ispqueue.c with 98% similarity]
drivers/media/platform/omap3isp/ispqueue.h [moved from drivers/media/video/omap3isp/ispqueue.h with 100% similarity]
drivers/media/platform/omap3isp/ispreg.h [moved from drivers/media/video/omap3isp/ispreg.h with 100% similarity]
drivers/media/platform/omap3isp/ispresizer.c [moved from drivers/media/video/omap3isp/ispresizer.c with 99% similarity]
drivers/media/platform/omap3isp/ispresizer.h [moved from drivers/media/video/omap3isp/ispresizer.h with 100% similarity]
drivers/media/platform/omap3isp/ispstat.c [moved from drivers/media/video/omap3isp/ispstat.c with 99% similarity]
drivers/media/platform/omap3isp/ispstat.h [moved from drivers/media/video/omap3isp/ispstat.h with 97% similarity]
drivers/media/platform/omap3isp/ispvideo.c [moved from drivers/media/video/omap3isp/ispvideo.c with 96% similarity]
drivers/media/platform/omap3isp/ispvideo.h [moved from drivers/media/video/omap3isp/ispvideo.h with 97% similarity]
drivers/media/platform/omap3isp/luma_enhance_table.h [moved from drivers/media/video/omap3isp/luma_enhance_table.h with 100% similarity]
drivers/media/platform/omap3isp/noise_filter_table.h [moved from drivers/media/video/omap3isp/noise_filter_table.h with 100% similarity]
drivers/media/platform/s5p-fimc/Kconfig [moved from drivers/media/video/s5p-fimc/Kconfig with 96% similarity]
drivers/media/platform/s5p-fimc/Makefile [moved from drivers/media/video/s5p-fimc/Makefile with 100% similarity]
drivers/media/platform/s5p-fimc/fimc-capture.c [moved from drivers/media/video/s5p-fimc/fimc-capture.c with 90% similarity]
drivers/media/platform/s5p-fimc/fimc-core.c [moved from drivers/media/video/s5p-fimc/fimc-core.c with 98% similarity]
drivers/media/platform/s5p-fimc/fimc-core.h [moved from drivers/media/video/s5p-fimc/fimc-core.h with 96% similarity]
drivers/media/platform/s5p-fimc/fimc-lite-reg.c [moved from drivers/media/video/s5p-fimc/fimc-lite-reg.c with 97% similarity]
drivers/media/platform/s5p-fimc/fimc-lite-reg.h [moved from drivers/media/video/s5p-fimc/fimc-lite-reg.h with 100% similarity]
drivers/media/platform/s5p-fimc/fimc-lite.c [moved from drivers/media/video/s5p-fimc/fimc-lite.c with 97% similarity]
drivers/media/platform/s5p-fimc/fimc-lite.h [moved from drivers/media/video/s5p-fimc/fimc-lite.h with 97% similarity]
drivers/media/platform/s5p-fimc/fimc-m2m.c [moved from drivers/media/video/s5p-fimc/fimc-m2m.c with 93% similarity]
drivers/media/platform/s5p-fimc/fimc-mdevice.c [moved from drivers/media/video/s5p-fimc/fimc-mdevice.c with 92% similarity]
drivers/media/platform/s5p-fimc/fimc-mdevice.h [moved from drivers/media/video/s5p-fimc/fimc-mdevice.h with 83% similarity]
drivers/media/platform/s5p-fimc/fimc-reg.c [moved from drivers/media/video/s5p-fimc/fimc-reg.c with 97% similarity]
drivers/media/platform/s5p-fimc/fimc-reg.h [moved from drivers/media/video/s5p-fimc/fimc-reg.h with 99% similarity]
drivers/media/platform/s5p-fimc/mipi-csis.c [moved from drivers/media/video/s5p-fimc/mipi-csis.c with 77% similarity]
drivers/media/platform/s5p-fimc/mipi-csis.h [moved from drivers/media/video/s5p-fimc/mipi-csis.h with 100% similarity]
drivers/media/platform/s5p-g2d/Makefile [moved from drivers/media/video/s5p-g2d/Makefile with 100% similarity]
drivers/media/platform/s5p-g2d/g2d-hw.c [moved from drivers/media/video/s5p-g2d/g2d-hw.c with 100% similarity]
drivers/media/platform/s5p-g2d/g2d-regs.h [moved from drivers/media/video/s5p-g2d/g2d-regs.h with 100% similarity]
drivers/media/platform/s5p-g2d/g2d.c [moved from drivers/media/video/s5p-g2d/g2d.c with 96% similarity]
drivers/media/platform/s5p-g2d/g2d.h [moved from drivers/media/video/s5p-g2d/g2d.h with 100% similarity]
drivers/media/platform/s5p-jpeg/Makefile [moved from drivers/media/video/s5p-jpeg/Makefile with 100% similarity]
drivers/media/platform/s5p-jpeg/jpeg-core.c [moved from drivers/media/video/s5p-jpeg/jpeg-core.c with 97% similarity]
drivers/media/platform/s5p-jpeg/jpeg-core.h [moved from drivers/media/video/s5p-jpeg/jpeg-core.h with 98% similarity]
drivers/media/platform/s5p-jpeg/jpeg-hw.h [moved from drivers/media/video/s5p-jpeg/jpeg-hw.h with 99% similarity]
drivers/media/platform/s5p-jpeg/jpeg-regs.h [moved from drivers/media/video/s5p-jpeg/jpeg-regs.h with 98% similarity]
drivers/media/platform/s5p-mfc/Makefile [moved from drivers/media/video/s5p-mfc/Makefile with 100% similarity]
drivers/media/platform/s5p-mfc/regs-mfc.h [moved from drivers/media/video/s5p-mfc/regs-mfc.h with 100% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc.c [moved from drivers/media/video/s5p-mfc/s5p_mfc.c with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_cmd.c with 98% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_cmd.h with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_common.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_common.h with 98% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c with 95% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_debug.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_debug.h with 95% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_dec.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_dec.c with 97% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_dec.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_dec.h with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_enc.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_enc.c with 95% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_enc.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_enc.h with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_intr.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_intr.c with 97% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_intr.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_intr.h with 93% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_opr.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_opr.c with 97% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_opr.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_opr.h with 98% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_pm.c with 98% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_pm.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_pm.h with 92% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_shm.c [moved from drivers/media/video/s5p-mfc/s5p_mfc_shm.c with 96% similarity]
drivers/media/platform/s5p-mfc/s5p_mfc_shm.h [moved from drivers/media/video/s5p-mfc/s5p_mfc_shm.h with 98% similarity]
drivers/media/platform/s5p-tv/Kconfig [moved from drivers/media/video/s5p-tv/Kconfig with 98% similarity]
drivers/media/platform/s5p-tv/Makefile [moved from drivers/media/video/s5p-tv/Makefile with 92% similarity]
drivers/media/platform/s5p-tv/hdmi_drv.c [moved from drivers/media/video/s5p-tv/hdmi_drv.c with 99% similarity]
drivers/media/platform/s5p-tv/hdmiphy_drv.c [moved from drivers/media/video/s5p-tv/hdmiphy_drv.c with 100% similarity]
drivers/media/platform/s5p-tv/mixer.h [moved from drivers/media/video/s5p-tv/mixer.h with 100% similarity]
drivers/media/platform/s5p-tv/mixer_drv.c [moved from drivers/media/video/s5p-tv/mixer_drv.c with 98% similarity]
drivers/media/platform/s5p-tv/mixer_grp_layer.c [moved from drivers/media/video/s5p-tv/mixer_grp_layer.c with 100% similarity]
drivers/media/platform/s5p-tv/mixer_reg.c [moved from drivers/media/video/s5p-tv/mixer_reg.c with 100% similarity]
drivers/media/platform/s5p-tv/mixer_video.c [moved from drivers/media/video/s5p-tv/mixer_video.c with 97% similarity]
drivers/media/platform/s5p-tv/mixer_vp_layer.c [moved from drivers/media/video/s5p-tv/mixer_vp_layer.c with 100% similarity]
drivers/media/platform/s5p-tv/regs-hdmi.h [moved from drivers/media/video/s5p-tv/regs-hdmi.h with 100% similarity]
drivers/media/platform/s5p-tv/regs-mixer.h [moved from drivers/media/video/s5p-tv/regs-mixer.h with 100% similarity]
drivers/media/platform/s5p-tv/regs-sdo.h [moved from drivers/media/video/s5p-tv/regs-sdo.h with 97% similarity]
drivers/media/platform/s5p-tv/regs-vp.h [moved from drivers/media/video/s5p-tv/regs-vp.h with 100% similarity]
drivers/media/platform/s5p-tv/sdo_drv.c [moved from drivers/media/video/s5p-tv/sdo_drv.c with 98% similarity]
drivers/media/platform/s5p-tv/sii9234_drv.c [moved from drivers/media/video/s5p-tv/sii9234_drv.c with 97% similarity]
drivers/media/platform/sh_vou.c [moved from drivers/media/video/sh_vou.c with 97% similarity]
drivers/media/platform/soc_camera/Kconfig [new file with mode: 0644]
drivers/media/platform/soc_camera/Makefile [new file with mode: 0644]
drivers/media/platform/soc_camera/atmel-isi.c [moved from drivers/media/video/atmel-isi.c with 100% similarity]
drivers/media/platform/soc_camera/mx1_camera.c [moved from drivers/media/video/mx1_camera.c with 100% similarity]
drivers/media/platform/soc_camera/mx2_camera.c [moved from drivers/media/video/mx2_camera.c with 93% similarity]
drivers/media/platform/soc_camera/mx3_camera.c [moved from drivers/media/video/mx3_camera.c with 99% similarity]
drivers/media/platform/soc_camera/omap1_camera.c [moved from drivers/media/video/omap1_camera.c with 99% similarity]
drivers/media/platform/soc_camera/pxa_camera.c [moved from drivers/media/video/pxa_camera.c with 100% similarity]
drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c [moved from drivers/media/video/sh_mobile_ceu_camera.c with 99% similarity]
drivers/media/platform/soc_camera/sh_mobile_csi2.c [moved from drivers/media/video/sh_mobile_csi2.c with 100% similarity]
drivers/media/platform/soc_camera/soc_camera.c [moved from drivers/media/video/soc_camera.c with 91% similarity]
drivers/media/platform/soc_camera/soc_camera_platform.c [moved from drivers/media/video/soc_camera_platform.c with 94% similarity]
drivers/media/platform/soc_camera/soc_mediabus.c [moved from drivers/media/video/soc_mediabus.c with 100% similarity]
drivers/media/platform/timblogiw.c [moved from drivers/media/video/timblogiw.c with 100% similarity]
drivers/media/platform/via-camera.c [moved from drivers/media/video/via-camera.c with 100% similarity]
drivers/media/platform/via-camera.h [moved from drivers/media/video/via-camera.h with 100% similarity]
drivers/media/platform/vino.c [moved from drivers/media/video/vino.c with 99% similarity]
drivers/media/platform/vino.h [moved from drivers/media/video/vino.h with 100% similarity]
drivers/media/platform/vivi.c [moved from drivers/media/video/vivi.c with 97% similarity]
drivers/media/radio/radio-keene.c
drivers/media/radio/radio-miropcm20.c
drivers/media/radio/radio-mr800.c
drivers/media/radio/radio-sf16fmi.c
drivers/media/radio/radio-shark.c
drivers/media/radio/radio-shark2.c
drivers/media/radio/radio-si4713.c
drivers/media/radio/radio-tea5764.c
drivers/media/radio/radio-tea5777.c
drivers/media/radio/radio-tea5777.h
drivers/media/radio/radio-timb.c
drivers/media/radio/radio-wl1273.c
drivers/media/radio/saa7706h.c
drivers/media/radio/si470x/radio-si470x-common.c
drivers/media/radio/si470x/radio-si470x-i2c.c
drivers/media/radio/si4713-i2c.c
drivers/media/radio/wl128x/fmdrv_v4l2.c
drivers/media/rc/Kconfig
drivers/media/rc/Makefile
drivers/media/rc/ati_remote.c
drivers/media/rc/fintek-cir.c
drivers/media/rc/iguanair.c
drivers/media/rc/ir-lirc-codec.c
drivers/media/rc/ir-nec-decoder.c
drivers/media/rc/ir-raw.c
drivers/media/rc/ir-rx51.c [new file with mode: 0644]
drivers/media/rc/ite-cir.c
drivers/media/rc/keymaps/rc-tt-1500.c
drivers/media/rc/mceusb.c
drivers/media/rc/rc-loopback.c
drivers/media/rc/redrat3.c
drivers/media/rc/ttusbir.c [new file with mode: 0644]
drivers/media/rc/winbond-cir.c
drivers/media/tuners/Kconfig [moved from drivers/media/common/tuners/Kconfig with 72% similarity]
drivers/media/tuners/Makefile [moved from drivers/media/common/tuners/Makefile with 88% similarity]
drivers/media/tuners/e4000.c [new file with mode: 0644]
drivers/media/tuners/e4000.h [new file with mode: 0644]
drivers/media/tuners/e4000_priv.h [new file with mode: 0644]
drivers/media/tuners/fc0011.c [moved from drivers/media/common/tuners/fc0011.c with 100% similarity]
drivers/media/tuners/fc0011.h [moved from drivers/media/common/tuners/fc0011.h with 100% similarity]
drivers/media/tuners/fc0012-priv.h [moved from drivers/media/common/tuners/fc0012-priv.h with 100% similarity]
drivers/media/tuners/fc0012.c [moved from drivers/media/common/tuners/fc0012.c with 100% similarity]
drivers/media/tuners/fc0012.h [moved from drivers/media/common/tuners/fc0012.h with 100% similarity]
drivers/media/tuners/fc0013-priv.h [moved from drivers/media/common/tuners/fc0013-priv.h with 100% similarity]
drivers/media/tuners/fc0013.c [moved from drivers/media/common/tuners/fc0013.c with 100% similarity]
drivers/media/tuners/fc0013.h [moved from drivers/media/common/tuners/fc0013.h with 100% similarity]
drivers/media/tuners/fc001x-common.h [moved from drivers/media/common/tuners/fc001x-common.h with 100% similarity]
drivers/media/tuners/fc2580.c [new file with mode: 0644]
drivers/media/tuners/fc2580.h [new file with mode: 0644]
drivers/media/tuners/fc2580_priv.h [new file with mode: 0644]
drivers/media/tuners/max2165.c [moved from drivers/media/common/tuners/max2165.c with 100% similarity]
drivers/media/tuners/max2165.h [moved from drivers/media/common/tuners/max2165.h with 100% similarity]
drivers/media/tuners/max2165_priv.h [moved from drivers/media/common/tuners/max2165_priv.h with 100% similarity]
drivers/media/tuners/mc44s803.c [moved from drivers/media/common/tuners/mc44s803.c with 97% similarity]
drivers/media/tuners/mc44s803.h [moved from drivers/media/common/tuners/mc44s803.h with 100% similarity]
drivers/media/tuners/mc44s803_priv.h [moved from drivers/media/common/tuners/mc44s803_priv.h with 100% similarity]
drivers/media/tuners/mt2060.c [moved from drivers/media/common/tuners/mt2060.c with 100% similarity]
drivers/media/tuners/mt2060.h [moved from drivers/media/common/tuners/mt2060.h with 100% similarity]
drivers/media/tuners/mt2060_priv.h [moved from drivers/media/common/tuners/mt2060_priv.h with 100% similarity]
drivers/media/tuners/mt2063.c [moved from drivers/media/common/tuners/mt2063.c with 100% similarity]
drivers/media/tuners/mt2063.h [moved from drivers/media/common/tuners/mt2063.h with 100% similarity]
drivers/media/tuners/mt20xx.c [moved from drivers/media/common/tuners/mt20xx.c with 100% similarity]
drivers/media/tuners/mt20xx.h [moved from drivers/media/common/tuners/mt20xx.h with 100% similarity]
drivers/media/tuners/mt2131.c [moved from drivers/media/common/tuners/mt2131.c with 100% similarity]
drivers/media/tuners/mt2131.h [moved from drivers/media/common/tuners/mt2131.h with 100% similarity]
drivers/media/tuners/mt2131_priv.h [moved from drivers/media/common/tuners/mt2131_priv.h with 100% similarity]
drivers/media/tuners/mt2266.c [moved from drivers/media/common/tuners/mt2266.c with 100% similarity]
drivers/media/tuners/mt2266.h [moved from drivers/media/common/tuners/mt2266.h with 100% similarity]
drivers/media/tuners/mxl5005s.c [moved from drivers/media/common/tuners/mxl5005s.c with 99% similarity]
drivers/media/tuners/mxl5005s.h [moved from drivers/media/common/tuners/mxl5005s.h with 100% similarity]
drivers/media/tuners/mxl5007t.c [moved from drivers/media/common/tuners/mxl5007t.c with 100% similarity]
drivers/media/tuners/mxl5007t.h [moved from drivers/media/common/tuners/mxl5007t.h with 100% similarity]
drivers/media/tuners/qt1010.c [moved from drivers/media/common/tuners/qt1010.c with 90% similarity]
drivers/media/tuners/qt1010.h [moved from drivers/media/common/tuners/qt1010.h with 100% similarity]
drivers/media/tuners/qt1010_priv.h [moved from drivers/media/common/tuners/qt1010_priv.h with 100% similarity]
drivers/media/tuners/tda18212.c [moved from drivers/media/common/tuners/tda18212.c with 91% similarity]
drivers/media/tuners/tda18212.h [moved from drivers/media/common/tuners/tda18212.h with 100% similarity]
drivers/media/tuners/tda18218.c [moved from drivers/media/common/tuners/tda18218.c with 87% similarity]
drivers/media/tuners/tda18218.h [moved from drivers/media/common/tuners/tda18218.h with 100% similarity]
drivers/media/tuners/tda18218_priv.h [moved from drivers/media/common/tuners/tda18218_priv.h with 90% similarity]
drivers/media/tuners/tda18271-common.c [moved from drivers/media/common/tuners/tda18271-common.c with 99% similarity]
drivers/media/tuners/tda18271-fe.c [moved from drivers/media/common/tuners/tda18271-fe.c with 98% similarity]
drivers/media/tuners/tda18271-maps.c [moved from drivers/media/common/tuners/tda18271-maps.c with 100% similarity]
drivers/media/tuners/tda18271-priv.h [moved from drivers/media/common/tuners/tda18271-priv.h with 100% similarity]
drivers/media/tuners/tda18271.h [moved from drivers/media/common/tuners/tda18271.h with 95% similarity]
drivers/media/tuners/tda827x.c [moved from drivers/media/common/tuners/tda827x.c with 100% similarity]
drivers/media/tuners/tda827x.h [moved from drivers/media/common/tuners/tda827x.h with 100% similarity]
drivers/media/tuners/tda8290.c [moved from drivers/media/common/tuners/tda8290.c with 100% similarity]
drivers/media/tuners/tda8290.h [moved from drivers/media/common/tuners/tda8290.h with 100% similarity]
drivers/media/tuners/tda9887.c [moved from drivers/media/common/tuners/tda9887.c with 100% similarity]
drivers/media/tuners/tda9887.h [moved from drivers/media/common/tuners/tda9887.h with 100% similarity]
drivers/media/tuners/tea5761.c [moved from drivers/media/common/tuners/tea5761.c with 100% similarity]
drivers/media/tuners/tea5761.h [moved from drivers/media/common/tuners/tea5761.h with 100% similarity]
drivers/media/tuners/tea5767.c [moved from drivers/media/common/tuners/tea5767.c with 100% similarity]
drivers/media/tuners/tea5767.h [moved from drivers/media/common/tuners/tea5767.h with 100% similarity]
drivers/media/tuners/tua9001.c [moved from drivers/media/common/tuners/tua9001.c with 65% similarity]
drivers/media/tuners/tua9001.h [moved from drivers/media/common/tuners/tua9001.h with 78% similarity]
drivers/media/tuners/tua9001_priv.h [moved from drivers/media/common/tuners/tua9001_priv.h with 100% similarity]
drivers/media/tuners/tuner-i2c.h [moved from drivers/media/common/tuners/tuner-i2c.h with 100% similarity]
drivers/media/tuners/tuner-simple.c [moved from drivers/media/common/tuners/tuner-simple.c with 100% similarity]
drivers/media/tuners/tuner-simple.h [moved from drivers/media/common/tuners/tuner-simple.h with 100% similarity]
drivers/media/tuners/tuner-types.c [moved from drivers/media/common/tuners/tuner-types.c with 100% similarity]
drivers/media/tuners/tuner-xc2028-types.h [moved from drivers/media/common/tuners/tuner-xc2028-types.h with 100% similarity]
drivers/media/tuners/tuner-xc2028.c [moved from drivers/media/common/tuners/tuner-xc2028.c with 99% similarity]
drivers/media/tuners/tuner-xc2028.h [moved from drivers/media/common/tuners/tuner-xc2028.h with 100% similarity]
drivers/media/tuners/xc4000.c [moved from drivers/media/common/tuners/xc4000.c with 99% similarity]
drivers/media/tuners/xc4000.h [moved from drivers/media/common/tuners/xc4000.h with 100% similarity]
drivers/media/tuners/xc5000.c [moved from drivers/media/common/tuners/xc5000.c with 88% similarity]
drivers/media/tuners/xc5000.h [moved from drivers/media/common/tuners/xc5000.h with 100% similarity]
drivers/media/usb/Kconfig [new file with mode: 0644]
drivers/media/usb/Makefile [new file with mode: 0644]
drivers/media/usb/au0828/Kconfig [moved from drivers/media/video/au0828/Kconfig with 54% similarity]
drivers/media/usb/au0828/Makefile [moved from drivers/media/video/au0828/Makefile with 59% similarity]
drivers/media/usb/au0828/au0828-cards.c [moved from drivers/media/video/au0828/au0828-cards.c with 99% similarity]
drivers/media/usb/au0828/au0828-cards.h [moved from drivers/media/video/au0828/au0828-cards.h with 100% similarity]
drivers/media/usb/au0828/au0828-core.c [moved from drivers/media/video/au0828/au0828-core.c with 85% similarity]
drivers/media/usb/au0828/au0828-dvb.c [moved from drivers/media/video/au0828/au0828-dvb.c with 90% similarity]
drivers/media/usb/au0828/au0828-i2c.c [moved from drivers/media/video/au0828/au0828-i2c.c with 93% similarity]
drivers/media/usb/au0828/au0828-reg.h [moved from drivers/media/video/au0828/au0828-reg.h with 98% similarity]
drivers/media/usb/au0828/au0828-vbi.c [moved from drivers/media/video/au0828/au0828-vbi.c with 100% similarity]
drivers/media/usb/au0828/au0828-video.c [moved from drivers/media/video/au0828/au0828-video.c with 96% similarity]
drivers/media/usb/au0828/au0828.h [moved from drivers/media/video/au0828/au0828.h with 98% similarity]
drivers/media/usb/b2c2/Kconfig [new file with mode: 0644]
drivers/media/usb/b2c2/Makefile [new file with mode: 0644]
drivers/media/usb/b2c2/flexcop-usb.c [moved from drivers/media/dvb/b2c2/flexcop-usb.c with 99% similarity]
drivers/media/usb/b2c2/flexcop-usb.h [moved from drivers/media/dvb/b2c2/flexcop-usb.h with 100% similarity]
drivers/media/usb/cpia2/Kconfig [moved from drivers/media/video/cpia2/Kconfig with 100% similarity]
drivers/media/usb/cpia2/Makefile [moved from drivers/media/video/cpia2/Makefile with 100% similarity]
drivers/media/usb/cpia2/cpia2.h [moved from drivers/media/video/cpia2/cpia2.h with 100% similarity]
drivers/media/usb/cpia2/cpia2_core.c [moved from drivers/media/video/cpia2/cpia2_core.c with 99% similarity]
drivers/media/usb/cpia2/cpia2_registers.h [moved from drivers/media/video/cpia2/cpia2_registers.h with 100% similarity]
drivers/media/usb/cpia2/cpia2_usb.c [moved from drivers/media/video/cpia2/cpia2_usb.c with 100% similarity]
drivers/media/usb/cpia2/cpia2_v4l.c [moved from drivers/media/video/cpia2/cpia2_v4l.c with 97% similarity]
drivers/media/usb/cx231xx/Kconfig [moved from drivers/media/video/cx231xx/Kconfig with 86% similarity]
drivers/media/usb/cx231xx/Makefile [moved from drivers/media/video/cx231xx/Makefile with 65% similarity]
drivers/media/usb/cx231xx/cx231xx-417.c [moved from drivers/media/video/cx231xx/cx231xx-417.c with 99% similarity]
drivers/media/usb/cx231xx/cx231xx-audio.c [moved from drivers/media/video/cx231xx/cx231xx-audio.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-avcore.c [moved from drivers/media/video/cx231xx/cx231xx-avcore.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-cards.c [moved from drivers/media/video/cx231xx/cx231xx-cards.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-conf-reg.h [moved from drivers/media/video/cx231xx/cx231xx-conf-reg.h with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-core.c [moved from drivers/media/video/cx231xx/cx231xx-core.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-dif.h [moved from drivers/media/video/cx231xx/cx231xx-dif.h with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-dvb.c [moved from drivers/media/video/cx231xx/cx231xx-dvb.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-i2c.c [moved from drivers/media/video/cx231xx/cx231xx-i2c.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-input.c [moved from drivers/media/video/cx231xx/cx231xx-input.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-pcb-cfg.c [moved from drivers/media/video/cx231xx/cx231xx-pcb-cfg.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-pcb-cfg.h [moved from drivers/media/video/cx231xx/cx231xx-pcb-cfg.h with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-reg.h [moved from drivers/media/video/cx231xx/cx231xx-reg.h with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-vbi.c [moved from drivers/media/video/cx231xx/cx231xx-vbi.c with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-vbi.h [moved from drivers/media/video/cx231xx/cx231xx-vbi.h with 100% similarity]
drivers/media/usb/cx231xx/cx231xx-video.c [moved from drivers/media/video/cx231xx/cx231xx-video.c with 98% similarity]
drivers/media/usb/cx231xx/cx231xx.h [moved from drivers/media/video/cx231xx/cx231xx.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/Kconfig [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/Makefile [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/af9015.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/af9015.h [moved from drivers/media/dvb/dvb-usb/af9015.h with 78% similarity]
drivers/media/usb/dvb-usb-v2/af9035.c [moved from drivers/media/dvb/dvb-usb/af9035.c with 57% similarity]
drivers/media/usb/dvb-usb-v2/af9035.h [moved from drivers/media/dvb/dvb-usb/af9035.h with 93% similarity]
drivers/media/usb/dvb-usb-v2/anysee.c [moved from drivers/media/dvb/dvb-usb/anysee.c with 67% similarity]
drivers/media/usb/dvb-usb-v2/anysee.h [moved from drivers/media/dvb/dvb-usb/anysee.h with 97% similarity]
drivers/media/usb/dvb-usb-v2/au6610.c [moved from drivers/media/dvb/dvb-usb/au6610.c with 64% similarity]
drivers/media/usb/dvb-usb-v2/au6610.h [moved from drivers/media/dvb/dvb-usb/au6610.h with 80% similarity]
drivers/media/usb/dvb-usb-v2/az6007.c [moved from drivers/media/dvb/dvb-usb/az6007.c with 63% similarity]
drivers/media/usb/dvb-usb-v2/ce6230.c [moved from drivers/media/dvb/dvb-usb/ce6230.c with 58% similarity]
drivers/media/usb/dvb-usb-v2/ce6230.h [moved from drivers/media/dvb/dvb-usb/ce6230.h with 58% similarity]
drivers/media/usb/dvb-usb-v2/cypress_firmware.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/cypress_firmware.h [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/dvb_usb.h [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/dvb_usb_common.h [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/dvb_usb_core.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/ec168.c [moved from drivers/media/dvb/dvb-usb/ec168.c with 57% similarity]
drivers/media/usb/dvb-usb-v2/ec168.h [moved from drivers/media/dvb/dvb-usb/ec168.h with 62% similarity]
drivers/media/usb/dvb-usb-v2/gl861.c [moved from drivers/media/dvb/dvb-usb/gl861.c with 54% similarity]
drivers/media/usb/dvb-usb-v2/gl861.h [moved from drivers/media/dvb/dvb-usb/gl861.h with 59% similarity]
drivers/media/usb/dvb-usb-v2/it913x.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/lmedm04.c [moved from drivers/media/dvb/dvb-usb/lmedm04.c with 69% similarity]
drivers/media/usb/dvb-usb-v2/lmedm04.h [moved from drivers/media/dvb/dvb-usb/lmedm04.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-demod.c [moved from drivers/media/dvb/dvb-usb/mxl111sf-demod.c with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-demod.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-demod.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.c [moved from drivers/media/dvb/dvb-usb/mxl111sf-gpio.c with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-gpio.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-gpio.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.c [moved from drivers/media/dvb/dvb-usb/mxl111sf-i2c.c with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-i2c.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-i2c.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-phy.c [moved from drivers/media/dvb/dvb-usb/mxl111sf-phy.c with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-phy.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-phy.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-reg.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-reg.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c [moved from drivers/media/dvb/dvb-usb/mxl111sf-tuner.c with 99% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.h [moved from drivers/media/dvb/dvb-usb/mxl111sf-tuner.h with 100% similarity]
drivers/media/usb/dvb-usb-v2/mxl111sf.c [new file with mode: 0644]
drivers/media/usb/dvb-usb-v2/mxl111sf.h [moved from drivers/media/dvb/dvb-usb/mxl111sf.h with 98% similarity]
drivers/media/usb/dvb-usb-v2/rtl28xxu.c [moved from drivers/media/dvb/dvb-usb/rtl28xxu.c with 62% similarity]
drivers/media/usb/dvb-usb-v2/rtl28xxu.h [moved from drivers/media/dvb/dvb-usb/rtl28xxu.h with 91% similarity]
drivers/media/usb/dvb-usb-v2/usb_urb.c [new file with mode: 0644]
drivers/media/usb/dvb-usb/Kconfig [new file with mode: 0644]
drivers/media/usb/dvb-usb/Makefile [new file with mode: 0644]
drivers/media/usb/dvb-usb/a800.c [moved from drivers/media/dvb/dvb-usb/a800.c with 100% similarity]
drivers/media/usb/dvb-usb/af9005-fe.c [moved from drivers/media/dvb/dvb-usb/af9005-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/af9005-remote.c [moved from drivers/media/dvb/dvb-usb/af9005-remote.c with 100% similarity]
drivers/media/usb/dvb-usb/af9005-script.h [moved from drivers/media/dvb/dvb-usb/af9005-script.h with 100% similarity]
drivers/media/usb/dvb-usb/af9005.c [moved from drivers/media/dvb/dvb-usb/af9005.c with 100% similarity]
drivers/media/usb/dvb-usb/af9005.h [moved from drivers/media/dvb/dvb-usb/af9005.h with 100% similarity]
drivers/media/usb/dvb-usb/az6027.c [moved from drivers/media/dvb/dvb-usb/az6027.c with 100% similarity]
drivers/media/usb/dvb-usb/az6027.h [moved from drivers/media/dvb/dvb-usb/az6027.h with 100% similarity]
drivers/media/usb/dvb-usb/cinergyT2-core.c [moved from drivers/media/dvb/dvb-usb/cinergyT2-core.c with 100% similarity]
drivers/media/usb/dvb-usb/cinergyT2-fe.c [moved from drivers/media/dvb/dvb-usb/cinergyT2-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/cinergyT2.h [moved from drivers/media/dvb/dvb-usb/cinergyT2.h with 100% similarity]
drivers/media/usb/dvb-usb/cxusb.c [moved from drivers/media/dvb/dvb-usb/cxusb.c with 100% similarity]
drivers/media/usb/dvb-usb/cxusb.h [moved from drivers/media/dvb/dvb-usb/cxusb.h with 100% similarity]
drivers/media/usb/dvb-usb/dib0700.h [moved from drivers/media/dvb/dvb-usb/dib0700.h with 100% similarity]
drivers/media/usb/dvb-usb/dib0700_core.c [moved from drivers/media/dvb/dvb-usb/dib0700_core.c with 99% similarity]
drivers/media/usb/dvb-usb/dib0700_devices.c [moved from drivers/media/dvb/dvb-usb/dib0700_devices.c with 100% similarity]
drivers/media/usb/dvb-usb/dib07x0.h [moved from drivers/media/dvb/dvb-usb/dib07x0.h with 100% similarity]
drivers/media/usb/dvb-usb/dibusb-common.c [moved from drivers/media/dvb/dvb-usb/dibusb-common.c with 100% similarity]
drivers/media/usb/dvb-usb/dibusb-mb.c [moved from drivers/media/dvb/dvb-usb/dibusb-mb.c with 100% similarity]
drivers/media/usb/dvb-usb/dibusb-mc.c [moved from drivers/media/dvb/dvb-usb/dibusb-mc.c with 100% similarity]
drivers/media/usb/dvb-usb/dibusb.h [moved from drivers/media/dvb/dvb-usb/dibusb.h with 100% similarity]
drivers/media/usb/dvb-usb/digitv.c [moved from drivers/media/dvb/dvb-usb/digitv.c with 100% similarity]
drivers/media/usb/dvb-usb/digitv.h [moved from drivers/media/dvb/dvb-usb/digitv.h with 100% similarity]
drivers/media/usb/dvb-usb/dtt200u-fe.c [moved from drivers/media/dvb/dvb-usb/dtt200u-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/dtt200u.c [moved from drivers/media/dvb/dvb-usb/dtt200u.c with 100% similarity]
drivers/media/usb/dvb-usb/dtt200u.h [moved from drivers/media/dvb/dvb-usb/dtt200u.h with 100% similarity]
drivers/media/usb/dvb-usb/dtv5100.c [moved from drivers/media/dvb/dvb-usb/dtv5100.c with 100% similarity]
drivers/media/usb/dvb-usb/dtv5100.h [moved from drivers/media/dvb/dvb-usb/dtv5100.h with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-common.h [moved from drivers/media/dvb/dvb-usb/dvb-usb-common.h with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-dvb.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-dvb.c with 99% similarity]
drivers/media/usb/dvb-usb/dvb-usb-firmware.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-firmware.c with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-i2c.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-i2c.c with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-init.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-init.c with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-remote.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-remote.c with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb-urb.c [moved from drivers/media/dvb/dvb-usb/dvb-usb-urb.c with 100% similarity]
drivers/media/usb/dvb-usb/dvb-usb.h [moved from drivers/media/dvb/dvb-usb/dvb-usb.h with 99% similarity]
drivers/media/usb/dvb-usb/dw2102.c [moved from drivers/media/dvb/dvb-usb/dw2102.c with 100% similarity]
drivers/media/usb/dvb-usb/dw2102.h [moved from drivers/media/dvb/dvb-usb/dw2102.h with 100% similarity]
drivers/media/usb/dvb-usb/friio-fe.c [moved from drivers/media/dvb/dvb-usb/friio-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/friio.c [moved from drivers/media/dvb/dvb-usb/friio.c with 100% similarity]
drivers/media/usb/dvb-usb/friio.h [moved from drivers/media/dvb/dvb-usb/friio.h with 100% similarity]
drivers/media/usb/dvb-usb/gp8psk-fe.c [moved from drivers/media/dvb/dvb-usb/gp8psk-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/gp8psk.c [moved from drivers/media/dvb/dvb-usb/gp8psk.c with 100% similarity]
drivers/media/usb/dvb-usb/gp8psk.h [moved from drivers/media/dvb/dvb-usb/gp8psk.h with 100% similarity]
drivers/media/usb/dvb-usb/m920x.c [moved from drivers/media/dvb/dvb-usb/m920x.c with 100% similarity]
drivers/media/usb/dvb-usb/m920x.h [moved from drivers/media/dvb/dvb-usb/m920x.h with 100% similarity]
drivers/media/usb/dvb-usb/nova-t-usb2.c [moved from drivers/media/dvb/dvb-usb/nova-t-usb2.c with 100% similarity]
drivers/media/usb/dvb-usb/opera1.c [moved from drivers/media/dvb/dvb-usb/opera1.c with 100% similarity]
drivers/media/usb/dvb-usb/pctv452e.c [moved from drivers/media/dvb/dvb-usb/pctv452e.c with 99% similarity]
drivers/media/usb/dvb-usb/technisat-usb2.c [moved from drivers/media/dvb/dvb-usb/technisat-usb2.c with 99% similarity]
drivers/media/usb/dvb-usb/ttusb2.c [moved from drivers/media/dvb/dvb-usb/ttusb2.c with 99% similarity]
drivers/media/usb/dvb-usb/ttusb2.h [moved from drivers/media/dvb/dvb-usb/ttusb2.h with 100% similarity]
drivers/media/usb/dvb-usb/umt-010.c [moved from drivers/media/dvb/dvb-usb/umt-010.c with 100% similarity]
drivers/media/usb/dvb-usb/usb-urb.c [moved from drivers/media/dvb/dvb-usb/usb-urb.c with 100% similarity]
drivers/media/usb/dvb-usb/vp702x-fe.c [moved from drivers/media/dvb/dvb-usb/vp702x-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/vp702x.c [moved from drivers/media/dvb/dvb-usb/vp702x.c with 100% similarity]
drivers/media/usb/dvb-usb/vp702x.h [moved from drivers/media/dvb/dvb-usb/vp702x.h with 100% similarity]
drivers/media/usb/dvb-usb/vp7045-fe.c [moved from drivers/media/dvb/dvb-usb/vp7045-fe.c with 100% similarity]
drivers/media/usb/dvb-usb/vp7045.c [moved from drivers/media/dvb/dvb-usb/vp7045.c with 100% similarity]
drivers/media/usb/dvb-usb/vp7045.h [moved from drivers/media/dvb/dvb-usb/vp7045.h with 100% similarity]
drivers/media/usb/em28xx/Kconfig [moved from drivers/media/video/em28xx/Kconfig with 67% similarity]
drivers/media/usb/em28xx/Makefile [moved from drivers/media/video/em28xx/Makefile with 57% similarity]
drivers/media/usb/em28xx/em28xx-audio.c [moved from drivers/media/video/em28xx/em28xx-audio.c with 99% similarity]
drivers/media/usb/em28xx/em28xx-cards.c [moved from drivers/media/video/em28xx/em28xx-cards.c with 99% similarity]
drivers/media/usb/em28xx/em28xx-core.c [moved from drivers/media/video/em28xx/em28xx-core.c with 99% similarity]
drivers/media/usb/em28xx/em28xx-dvb.c [moved from drivers/media/video/em28xx/em28xx-dvb.c with 95% similarity]
drivers/media/usb/em28xx/em28xx-i2c.c [moved from drivers/media/video/em28xx/em28xx-i2c.c with 100% similarity]
drivers/media/usb/em28xx/em28xx-input.c [moved from drivers/media/video/em28xx/em28xx-input.c with 100% similarity]
drivers/media/usb/em28xx/em28xx-reg.h [moved from drivers/media/video/em28xx/em28xx-reg.h with 100% similarity]
drivers/media/usb/em28xx/em28xx-vbi.c [moved from drivers/media/video/em28xx/em28xx-vbi.c with 100% similarity]
drivers/media/usb/em28xx/em28xx-video.c [moved from drivers/media/video/em28xx/em28xx-video.c with 98% similarity]
drivers/media/usb/em28xx/em28xx.h [moved from drivers/media/video/em28xx/em28xx.h with 100% similarity]
drivers/media/usb/gspca/Kconfig [moved from drivers/media/video/gspca/Kconfig with 98% similarity]
drivers/media/usb/gspca/Makefile [moved from drivers/media/video/gspca/Makefile with 100% similarity]
drivers/media/usb/gspca/autogain_functions.c [moved from drivers/media/video/gspca/autogain_functions.c with 100% similarity]
drivers/media/usb/gspca/autogain_functions.h [moved from drivers/media/video/gspca/autogain_functions.h with 100% similarity]
drivers/media/usb/gspca/benq.c [moved from drivers/media/video/gspca/benq.c with 100% similarity]
drivers/media/usb/gspca/conex.c [moved from drivers/media/video/gspca/conex.c with 100% similarity]
drivers/media/usb/gspca/cpia1.c [moved from drivers/media/video/gspca/cpia1.c with 99% similarity]
drivers/media/usb/gspca/etoms.c [moved from drivers/media/video/gspca/etoms.c with 100% similarity]
drivers/media/usb/gspca/finepix.c [moved from drivers/media/video/gspca/finepix.c with 92% similarity]
drivers/media/usb/gspca/gl860/Kconfig [moved from drivers/media/video/gspca/gl860/Kconfig with 100% similarity]
drivers/media/usb/gspca/gl860/Makefile [moved from drivers/media/video/gspca/gl860/Makefile with 75% similarity]
drivers/media/usb/gspca/gl860/gl860-mi1320.c [moved from drivers/media/video/gspca/gl860/gl860-mi1320.c with 100% similarity]
drivers/media/usb/gspca/gl860/gl860-mi2020.c [moved from drivers/media/video/gspca/gl860/gl860-mi2020.c with 100% similarity]
drivers/media/usb/gspca/gl860/gl860-ov2640.c [moved from drivers/media/video/gspca/gl860/gl860-ov2640.c with 100% similarity]
drivers/media/usb/gspca/gl860/gl860-ov9655.c [moved from drivers/media/video/gspca/gl860/gl860-ov9655.c with 100% similarity]
drivers/media/usb/gspca/gl860/gl860.c [moved from drivers/media/video/gspca/gl860/gl860.c with 100% similarity]
drivers/media/usb/gspca/gl860/gl860.h [moved from drivers/media/video/gspca/gl860/gl860.h with 100% similarity]
drivers/media/usb/gspca/gspca.c [moved from drivers/media/video/gspca/gspca.c with 99% similarity]
drivers/media/usb/gspca/gspca.h [moved from drivers/media/video/gspca/gspca.h with 97% similarity]
drivers/media/usb/gspca/jeilinj.c [moved from drivers/media/video/gspca/jeilinj.c with 99% similarity]
drivers/media/usb/gspca/jl2005bcd.c [moved from drivers/media/video/gspca/jl2005bcd.c with 95% similarity]
drivers/media/usb/gspca/jpeg.h [moved from drivers/media/video/gspca/jpeg.h with 100% similarity]
drivers/media/usb/gspca/kinect.c [moved from drivers/media/video/gspca/kinect.c with 100% similarity]
drivers/media/usb/gspca/konica.c [moved from drivers/media/video/gspca/konica.c with 100% similarity]
drivers/media/usb/gspca/m5602/Kconfig [moved from drivers/media/video/gspca/m5602/Kconfig with 100% similarity]
drivers/media/usb/gspca/m5602/Makefile [moved from drivers/media/video/gspca/m5602/Makefile with 80% similarity]
drivers/media/usb/gspca/m5602/m5602_bridge.h [moved from drivers/media/video/gspca/m5602/m5602_bridge.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_core.c [moved from drivers/media/video/gspca/m5602/m5602_core.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_mt9m111.c [moved from drivers/media/video/gspca/m5602/m5602_mt9m111.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_mt9m111.h [moved from drivers/media/video/gspca/m5602/m5602_mt9m111.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_ov7660.c [moved from drivers/media/video/gspca/m5602/m5602_ov7660.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_ov7660.h [moved from drivers/media/video/gspca/m5602/m5602_ov7660.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_ov9650.c [moved from drivers/media/video/gspca/m5602/m5602_ov9650.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_ov9650.h [moved from drivers/media/video/gspca/m5602/m5602_ov9650.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_po1030.c [moved from drivers/media/video/gspca/m5602/m5602_po1030.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_po1030.h [moved from drivers/media/video/gspca/m5602/m5602_po1030.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_s5k4aa.c [moved from drivers/media/video/gspca/m5602/m5602_s5k4aa.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_s5k4aa.h [moved from drivers/media/video/gspca/m5602/m5602_s5k4aa.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_s5k83a.c [moved from drivers/media/video/gspca/m5602/m5602_s5k83a.c with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_s5k83a.h [moved from drivers/media/video/gspca/m5602/m5602_s5k83a.h with 100% similarity]
drivers/media/usb/gspca/m5602/m5602_sensor.h [moved from drivers/media/video/gspca/m5602/m5602_sensor.h with 100% similarity]
drivers/media/usb/gspca/mars.c [moved from drivers/media/video/gspca/mars.c with 100% similarity]
drivers/media/usb/gspca/mr97310a.c [moved from drivers/media/video/gspca/mr97310a.c with 100% similarity]
drivers/media/usb/gspca/nw80x.c [moved from drivers/media/video/gspca/nw80x.c with 100% similarity]
drivers/media/usb/gspca/ov519.c [moved from drivers/media/video/gspca/ov519.c with 99% similarity]
drivers/media/usb/gspca/ov534.c [moved from drivers/media/video/gspca/ov534.c with 100% similarity]
drivers/media/usb/gspca/ov534_9.c [moved from drivers/media/video/gspca/ov534_9.c with 100% similarity]
drivers/media/usb/gspca/pac207.c [moved from drivers/media/video/gspca/pac207.c with 100% similarity]
drivers/media/usb/gspca/pac7302.c [moved from drivers/media/video/gspca/pac7302.c with 95% similarity]
drivers/media/usb/gspca/pac7311.c [moved from drivers/media/video/gspca/pac7311.c with 100% similarity]
drivers/media/usb/gspca/pac_common.h [moved from drivers/media/video/gspca/pac_common.h with 100% similarity]
drivers/media/usb/gspca/se401.c [moved from drivers/media/video/gspca/se401.c with 100% similarity]
drivers/media/usb/gspca/se401.h [moved from drivers/media/video/gspca/se401.h with 100% similarity]
drivers/media/usb/gspca/sn9c2028.c [moved from drivers/media/video/gspca/sn9c2028.c with 100% similarity]
drivers/media/usb/gspca/sn9c2028.h [moved from drivers/media/video/gspca/sn9c2028.h with 100% similarity]
drivers/media/usb/gspca/sn9c20x.c [moved from drivers/media/video/gspca/sn9c20x.c with 99% similarity]
drivers/media/usb/gspca/sonixb.c [moved from drivers/media/video/gspca/sonixb.c with 100% similarity]
drivers/media/usb/gspca/sonixj.c [moved from drivers/media/video/gspca/sonixj.c with 99% similarity]
drivers/media/usb/gspca/spca1528.c [moved from drivers/media/video/gspca/spca1528.c with 100% similarity]
drivers/media/usb/gspca/spca500.c [moved from drivers/media/video/gspca/spca500.c with 100% similarity]
drivers/media/usb/gspca/spca501.c [moved from drivers/media/video/gspca/spca501.c with 100% similarity]
drivers/media/usb/gspca/spca505.c [moved from drivers/media/video/gspca/spca505.c with 100% similarity]
drivers/media/usb/gspca/spca506.c [moved from drivers/media/video/gspca/spca506.c with 100% similarity]
drivers/media/usb/gspca/spca508.c [moved from drivers/media/video/gspca/spca508.c with 100% similarity]
drivers/media/usb/gspca/spca561.c [moved from drivers/media/video/gspca/spca561.c with 100% similarity]
drivers/media/usb/gspca/sq905.c [moved from drivers/media/video/gspca/sq905.c with 95% similarity]
drivers/media/usb/gspca/sq905c.c [moved from drivers/media/video/gspca/sq905c.c with 91% similarity]
drivers/media/usb/gspca/sq930x.c [moved from drivers/media/video/gspca/sq930x.c with 99% similarity]
drivers/media/usb/gspca/stk014.c [moved from drivers/media/video/gspca/stk014.c with 100% similarity]
drivers/media/usb/gspca/stv0680.c [moved from drivers/media/video/gspca/stv0680.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/Kconfig [moved from drivers/media/video/gspca/stv06xx/Kconfig with 100% similarity]
drivers/media/usb/gspca/stv06xx/Makefile [moved from drivers/media/video/gspca/stv06xx/Makefile with 78% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx.c [moved from drivers/media/video/gspca/stv06xx/stv06xx.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx.h [moved from drivers/media/video/gspca/stv06xx/stv06xx.h with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.c [moved from drivers/media/video/gspca/stv06xx/stv06xx_hdcs.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_hdcs.h [moved from drivers/media/video/gspca/stv06xx/stv06xx_hdcs.h with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.c [moved from drivers/media/video/gspca/stv06xx/stv06xx_pb0100.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_pb0100.h [moved from drivers/media/video/gspca/stv06xx/stv06xx_pb0100.h with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_sensor.h [moved from drivers/media/video/gspca/stv06xx/stv06xx_sensor.h with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_st6422.c [moved from drivers/media/video/gspca/stv06xx/stv06xx_st6422.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_st6422.h [moved from drivers/media/video/gspca/stv06xx/stv06xx_st6422.h with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.c [moved from drivers/media/video/gspca/stv06xx/stv06xx_vv6410.c with 100% similarity]
drivers/media/usb/gspca/stv06xx/stv06xx_vv6410.h [moved from drivers/media/video/gspca/stv06xx/stv06xx_vv6410.h with 100% similarity]
drivers/media/usb/gspca/sunplus.c [moved from drivers/media/video/gspca/sunplus.c with 100% similarity]
drivers/media/usb/gspca/t613.c [moved from drivers/media/video/gspca/t613.c with 100% similarity]
drivers/media/usb/gspca/topro.c [moved from drivers/media/video/gspca/topro.c with 99% similarity]
drivers/media/usb/gspca/tv8532.c [moved from drivers/media/video/gspca/tv8532.c with 100% similarity]
drivers/media/usb/gspca/vc032x.c [moved from drivers/media/video/gspca/vc032x.c with 99% similarity]
drivers/media/usb/gspca/vicam.c [moved from drivers/media/video/gspca/vicam.c with 94% similarity]
drivers/media/usb/gspca/w996Xcf.c [moved from drivers/media/video/gspca/w996Xcf.c with 100% similarity]
drivers/media/usb/gspca/xirlink_cit.c [moved from drivers/media/video/gspca/xirlink_cit.c with 99% similarity]
drivers/media/usb/gspca/zc3xx-reg.h [moved from drivers/media/video/gspca/zc3xx-reg.h with 100% similarity]
drivers/media/usb/gspca/zc3xx.c [moved from drivers/media/video/gspca/zc3xx.c with 99% similarity]
drivers/media/usb/hdpvr/Kconfig [moved from drivers/media/video/hdpvr/Kconfig with 100% similarity]
drivers/media/usb/hdpvr/Makefile [moved from drivers/media/video/hdpvr/Makefile with 81% similarity]
drivers/media/usb/hdpvr/hdpvr-control.c [moved from drivers/media/video/hdpvr/hdpvr-control.c with 100% similarity]
drivers/media/usb/hdpvr/hdpvr-core.c [moved from drivers/media/video/hdpvr/hdpvr-core.c with 100% similarity]
drivers/media/usb/hdpvr/hdpvr-i2c.c [moved from drivers/media/video/hdpvr/hdpvr-i2c.c with 100% similarity]
drivers/media/usb/hdpvr/hdpvr-video.c [moved from drivers/media/video/hdpvr/hdpvr-video.c with 99% similarity]
drivers/media/usb/hdpvr/hdpvr.h [moved from drivers/media/video/hdpvr/hdpvr.h with 100% similarity]
drivers/media/usb/pvrusb2/Kconfig [moved from drivers/media/video/pvrusb2/Kconfig with 82% similarity]
drivers/media/usb/pvrusb2/Makefile [moved from drivers/media/video/pvrusb2/Makefile with 80% similarity]
drivers/media/usb/pvrusb2/pvrusb2-audio.c [moved from drivers/media/video/pvrusb2/pvrusb2-audio.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-audio.h [moved from drivers/media/video/pvrusb2/pvrusb2-audio.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-context.c [moved from drivers/media/video/pvrusb2/pvrusb2-context.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-context.h [moved from drivers/media/video/pvrusb2/pvrusb2-context.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.c [moved from drivers/media/video/pvrusb2/pvrusb2-cs53l32a.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-cs53l32a.h [moved from drivers/media/video/pvrusb2/pvrusb2-cs53l32a.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-ctrl.c [moved from drivers/media/video/pvrusb2/pvrusb2-ctrl.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-ctrl.h [moved from drivers/media/video/pvrusb2/pvrusb2-ctrl.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.c [moved from drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-cx2584x-v4l.h [moved from drivers/media/video/pvrusb2/pvrusb2-cx2584x-v4l.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-debug.h [moved from drivers/media/video/pvrusb2/pvrusb2-debug.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-debugifc.c [moved from drivers/media/video/pvrusb2/pvrusb2-debugifc.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-debugifc.h [moved from drivers/media/video/pvrusb2/pvrusb2-debugifc.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-devattr.c [moved from drivers/media/video/pvrusb2/pvrusb2-devattr.c with 97% similarity]
drivers/media/usb/pvrusb2/pvrusb2-devattr.h [moved from drivers/media/video/pvrusb2/pvrusb2-devattr.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-dvb.c [moved from drivers/media/video/pvrusb2/pvrusb2-dvb.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-dvb.h [moved from drivers/media/video/pvrusb2/pvrusb2-dvb.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-eeprom.c [moved from drivers/media/video/pvrusb2/pvrusb2-eeprom.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-eeprom.h [moved from drivers/media/video/pvrusb2/pvrusb2-eeprom.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-encoder.c [moved from drivers/media/video/pvrusb2/pvrusb2-encoder.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-encoder.h [moved from drivers/media/video/pvrusb2/pvrusb2-encoder.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-fx2-cmd.h [moved from drivers/media/video/pvrusb2/pvrusb2-fx2-cmd.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-hdw-internal.h [moved from drivers/media/video/pvrusb2/pvrusb2-hdw-internal.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-hdw.c [moved from drivers/media/video/pvrusb2/pvrusb2-hdw.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-hdw.h [moved from drivers/media/video/pvrusb2/pvrusb2-hdw.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.c [moved from drivers/media/video/pvrusb2/pvrusb2-i2c-core.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-i2c-core.h [moved from drivers/media/video/pvrusb2/pvrusb2-i2c-core.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-io.c [moved from drivers/media/video/pvrusb2/pvrusb2-io.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-io.h [moved from drivers/media/video/pvrusb2/pvrusb2-io.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-ioread.c [moved from drivers/media/video/pvrusb2/pvrusb2-ioread.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-ioread.h [moved from drivers/media/video/pvrusb2/pvrusb2-ioread.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-main.c [moved from drivers/media/video/pvrusb2/pvrusb2-main.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-std.c [moved from drivers/media/video/pvrusb2/pvrusb2-std.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-std.h [moved from drivers/media/video/pvrusb2/pvrusb2-std.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-sysfs.c [moved from drivers/media/video/pvrusb2/pvrusb2-sysfs.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-sysfs.h [moved from drivers/media/video/pvrusb2/pvrusb2-sysfs.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-util.h [moved from drivers/media/video/pvrusb2/pvrusb2-util.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-v4l2.c [moved from drivers/media/video/pvrusb2/pvrusb2-v4l2.c with 99% similarity]
drivers/media/usb/pvrusb2/pvrusb2-v4l2.h [moved from drivers/media/video/pvrusb2/pvrusb2-v4l2.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-video-v4l.c [moved from drivers/media/video/pvrusb2/pvrusb2-video-v4l.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-video-v4l.h [moved from drivers/media/video/pvrusb2/pvrusb2-video-v4l.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-wm8775.c [moved from drivers/media/video/pvrusb2/pvrusb2-wm8775.c with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2-wm8775.h [moved from drivers/media/video/pvrusb2/pvrusb2-wm8775.h with 100% similarity]
drivers/media/usb/pvrusb2/pvrusb2.h [moved from drivers/media/video/pvrusb2/pvrusb2.h with 100% similarity]
drivers/media/usb/pwc/Kconfig [moved from drivers/media/video/pwc/Kconfig with 100% similarity]
drivers/media/usb/pwc/Makefile [moved from drivers/media/video/pwc/Makefile with 60% similarity]
drivers/media/usb/pwc/philips.txt [moved from drivers/media/video/pwc/philips.txt with 100% similarity]
drivers/media/usb/pwc/pwc-ctrl.c [moved from drivers/media/video/pwc/pwc-ctrl.c with 100% similarity]
drivers/media/usb/pwc/pwc-dec1.c [moved from drivers/media/video/pwc/pwc-dec1.c with 100% similarity]
drivers/media/usb/pwc/pwc-dec1.h [moved from drivers/media/video/pwc/pwc-dec1.h with 100% similarity]
drivers/media/usb/pwc/pwc-dec23.c [moved from drivers/media/video/pwc/pwc-dec23.c with 100% similarity]
drivers/media/usb/pwc/pwc-dec23.h [moved from drivers/media/video/pwc/pwc-dec23.h with 100% similarity]
drivers/media/usb/pwc/pwc-if.c [moved from drivers/media/video/pwc/pwc-if.c with 99% similarity]
drivers/media/usb/pwc/pwc-kiara.c [moved from drivers/media/video/pwc/pwc-kiara.c with 100% similarity]
drivers/media/usb/pwc/pwc-kiara.h [moved from drivers/media/video/pwc/pwc-kiara.h with 100% similarity]
drivers/media/usb/pwc/pwc-misc.c [moved from drivers/media/video/pwc/pwc-misc.c with 100% similarity]
drivers/media/usb/pwc/pwc-nala.h [moved from drivers/media/video/pwc/pwc-nala.h with 100% similarity]
drivers/media/usb/pwc/pwc-timon.c [moved from drivers/media/video/pwc/pwc-timon.c with 100% similarity]
drivers/media/usb/pwc/pwc-timon.h [moved from drivers/media/video/pwc/pwc-timon.h with 100% similarity]
drivers/media/usb/pwc/pwc-uncompress.c [moved from drivers/media/video/pwc/pwc-uncompress.c with 100% similarity]
drivers/media/usb/pwc/pwc-v4l.c [moved from drivers/media/video/pwc/pwc-v4l.c with 100% similarity]
drivers/media/usb/pwc/pwc.h [moved from drivers/media/video/pwc/pwc.h with 100% similarity]
drivers/media/usb/s2255/Kconfig [new file with mode: 0644]
drivers/media/usb/s2255/Makefile [new file with mode: 0644]
drivers/media/usb/s2255/s2255drv.c [moved from drivers/media/video/s2255drv.c with 99% similarity]
drivers/media/usb/siano/Kconfig [new file with mode: 0644]
drivers/media/usb/siano/Makefile [new file with mode: 0644]
drivers/media/usb/siano/smsusb.c [moved from drivers/media/dvb/siano/smsusb.c with 100% similarity]
drivers/media/usb/sn9c102/Kconfig [moved from drivers/media/video/sn9c102/Kconfig with 100% similarity]
drivers/media/usb/sn9c102/Makefile [moved from drivers/media/video/sn9c102/Makefile with 100% similarity]
drivers/media/usb/sn9c102/sn9c102.h [moved from drivers/media/video/sn9c102/sn9c102.h with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_config.h [moved from drivers/media/video/sn9c102/sn9c102_config.h with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_core.c [moved from drivers/media/video/sn9c102/sn9c102_core.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_devtable.h [moved from drivers/media/video/sn9c102/sn9c102_devtable.h with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_hv7131d.c [moved from drivers/media/video/sn9c102/sn9c102_hv7131d.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_hv7131r.c [moved from drivers/media/video/sn9c102/sn9c102_hv7131r.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_mi0343.c [moved from drivers/media/video/sn9c102/sn9c102_mi0343.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_mi0360.c [moved from drivers/media/video/sn9c102/sn9c102_mi0360.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_mt9v111.c [moved from drivers/media/video/sn9c102/sn9c102_mt9v111.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_ov7630.c [moved from drivers/media/video/sn9c102/sn9c102_ov7630.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_ov7660.c [moved from drivers/media/video/sn9c102/sn9c102_ov7660.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_pas106b.c [moved from drivers/media/video/sn9c102/sn9c102_pas106b.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_pas202bcb.c [moved from drivers/media/video/sn9c102/sn9c102_pas202bcb.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_sensor.h [moved from drivers/media/video/sn9c102/sn9c102_sensor.h with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_tas5110c1b.c [moved from drivers/media/video/sn9c102/sn9c102_tas5110c1b.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_tas5110d.c [moved from drivers/media/video/sn9c102/sn9c102_tas5110d.c with 100% similarity]
drivers/media/usb/sn9c102/sn9c102_tas5130d1b.c [moved from drivers/media/video/sn9c102/sn9c102_tas5130d1b.c with 100% similarity]
drivers/media/usb/stk1160/Kconfig [new file with mode: 0644]
drivers/media/usb/stk1160/Makefile [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-ac97.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-core.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-i2c.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-reg.h [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-v4l.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160-video.c [new file with mode: 0644]
drivers/media/usb/stk1160/stk1160.h [new file with mode: 0644]
drivers/media/usb/stkwebcam/Kconfig [new file with mode: 0644]
drivers/media/usb/stkwebcam/Makefile [new file with mode: 0644]
drivers/media/usb/stkwebcam/stk-sensor.c [moved from drivers/media/video/stk-sensor.c with 100% similarity]
drivers/media/usb/stkwebcam/stk-webcam.c [moved from drivers/media/video/stk-webcam.c with 100% similarity]
drivers/media/usb/stkwebcam/stk-webcam.h [moved from drivers/media/video/stk-webcam.h with 100% similarity]
drivers/media/usb/tlg2300/Kconfig [moved from drivers/media/video/tlg2300/Kconfig with 100% similarity]
drivers/media/usb/tlg2300/Makefile [new file with mode: 0644]
drivers/media/usb/tlg2300/pd-alsa.c [moved from drivers/media/video/tlg2300/pd-alsa.c with 99% similarity]
drivers/media/usb/tlg2300/pd-common.h [moved from drivers/media/video/tlg2300/pd-common.h with 100% similarity]
drivers/media/usb/tlg2300/pd-dvb.c [moved from drivers/media/video/tlg2300/pd-dvb.c with 100% similarity]
drivers/media/usb/tlg2300/pd-main.c [moved from drivers/media/video/tlg2300/pd-main.c with 100% similarity]
drivers/media/usb/tlg2300/pd-radio.c [moved from drivers/media/video/tlg2300/pd-radio.c with 99% similarity]
drivers/media/usb/tlg2300/pd-video.c [moved from drivers/media/video/tlg2300/pd-video.c with 99% similarity]
drivers/media/usb/tlg2300/vendorcmds.h [moved from drivers/media/video/tlg2300/vendorcmds.h with 100% similarity]
drivers/media/usb/tm6000/Kconfig [moved from drivers/media/video/tm6000/Kconfig with 100% similarity]
drivers/media/usb/tm6000/Makefile [moved from drivers/media/video/tm6000/Makefile with 62% similarity]
drivers/media/usb/tm6000/tm6000-alsa.c [moved from drivers/media/video/tm6000/tm6000-alsa.c with 99% similarity]
drivers/media/usb/tm6000/tm6000-cards.c [moved from drivers/media/video/tm6000/tm6000-cards.c with 100% similarity]
drivers/media/usb/tm6000/tm6000-core.c [moved from drivers/media/video/tm6000/tm6000-core.c with 100% similarity]
drivers/media/usb/tm6000/tm6000-dvb.c [moved from drivers/media/video/tm6000/tm6000-dvb.c with 100% similarity]
drivers/media/usb/tm6000/tm6000-i2c.c [moved from drivers/media/video/tm6000/tm6000-i2c.c with 100% similarity]
drivers/media/usb/tm6000/tm6000-input.c [moved from drivers/media/video/tm6000/tm6000-input.c with 99% similarity]
drivers/media/usb/tm6000/tm6000-regs.h [moved from drivers/media/video/tm6000/tm6000-regs.h with 100% similarity]
drivers/media/usb/tm6000/tm6000-stds.c [moved from drivers/media/video/tm6000/tm6000-stds.c with 100% similarity]
drivers/media/usb/tm6000/tm6000-usb-isoc.h [moved from drivers/media/video/tm6000/tm6000-usb-isoc.h with 100% similarity]
drivers/media/usb/tm6000/tm6000-video.c [moved from drivers/media/video/tm6000/tm6000-video.c with 97% similarity]
drivers/media/usb/tm6000/tm6000.h [moved from drivers/media/video/tm6000/tm6000.h with 100% similarity]
drivers/media/usb/ttusb-budget/Kconfig [moved from drivers/media/dvb/ttusb-budget/Kconfig with 56% similarity]
drivers/media/usb/ttusb-budget/Makefile [new file with mode: 0644]
drivers/media/usb/ttusb-budget/dvb-ttusb-budget.c [moved from drivers/media/dvb/ttusb-budget/dvb-ttusb-budget.c with 100% similarity]
drivers/media/usb/ttusb-dec/Kconfig [moved from drivers/media/dvb/ttusb-dec/Kconfig with 100% similarity]
drivers/media/usb/ttusb-dec/Makefile [moved from drivers/media/dvb/ttusb-dec/Makefile with 57% similarity]
drivers/media/usb/ttusb-dec/ttusb_dec.c [moved from drivers/media/dvb/ttusb-dec/ttusb_dec.c with 100% similarity]
drivers/media/usb/ttusb-dec/ttusbdecfe.c [moved from drivers/media/dvb/ttusb-dec/ttusbdecfe.c with 100% similarity]
drivers/media/usb/ttusb-dec/ttusbdecfe.h [moved from drivers/media/dvb/ttusb-dec/ttusbdecfe.h with 100% similarity]
drivers/media/usb/usbvision/Kconfig [moved from drivers/media/video/usbvision/Kconfig with 88% similarity]
drivers/media/usb/usbvision/Makefile [moved from drivers/media/video/usbvision/Makefile with 63% similarity]
drivers/media/usb/usbvision/usbvision-cards.c [moved from drivers/media/video/usbvision/usbvision-cards.c with 100% similarity]
drivers/media/usb/usbvision/usbvision-cards.h [moved from drivers/media/video/usbvision/usbvision-cards.h with 100% similarity]
drivers/media/usb/usbvision/usbvision-core.c [moved from drivers/media/video/usbvision/usbvision-core.c with 100% similarity]
drivers/media/usb/usbvision/usbvision-i2c.c [moved from drivers/media/video/usbvision/usbvision-i2c.c with 100% similarity]
drivers/media/usb/usbvision/usbvision-video.c [moved from drivers/media/video/usbvision/usbvision-video.c with 97% similarity]
drivers/media/usb/usbvision/usbvision.h [moved from drivers/media/video/usbvision/usbvision.h with 100% similarity]
drivers/media/usb/uvc/Kconfig [moved from drivers/media/video/uvc/Kconfig with 100% similarity]
drivers/media/usb/uvc/Makefile [moved from drivers/media/video/uvc/Makefile with 100% similarity]
drivers/media/usb/uvc/uvc_ctrl.c [moved from drivers/media/video/uvc/uvc_ctrl.c with 100% similarity]
drivers/media/usb/uvc/uvc_debugfs.c [moved from drivers/media/video/uvc/uvc_debugfs.c with 100% similarity]
drivers/media/usb/uvc/uvc_driver.c [moved from drivers/media/video/uvc/uvc_driver.c with 98% similarity]
drivers/media/usb/uvc/uvc_entity.c [moved from drivers/media/video/uvc/uvc_entity.c with 100% similarity]
drivers/media/usb/uvc/uvc_isight.c [moved from drivers/media/video/uvc/uvc_isight.c with 100% similarity]
drivers/media/usb/uvc/uvc_queue.c [moved from drivers/media/video/uvc/uvc_queue.c with 100% similarity]
drivers/media/usb/uvc/uvc_status.c [moved from drivers/media/video/uvc/uvc_status.c with 100% similarity]
drivers/media/usb/uvc/uvc_v4l2.c [moved from drivers/media/video/uvc/uvc_v4l2.c with 100% similarity]
drivers/media/usb/uvc/uvc_video.c [moved from drivers/media/video/uvc/uvc_video.c with 98% similarity]
drivers/media/usb/uvc/uvcvideo.h [moved from drivers/media/video/uvc/uvcvideo.h with 98% similarity]
drivers/media/usb/zr364xx/Kconfig [new file with mode: 0644]
drivers/media/usb/zr364xx/Makefile [new file with mode: 0644]
drivers/media/usb/zr364xx/zr364xx.c [moved from drivers/media/video/zr364xx.c with 100% similarity]
drivers/media/v4l2-core/Kconfig [new file with mode: 0644]
drivers/media/v4l2-core/Makefile [new file with mode: 0644]
drivers/media/v4l2-core/tuner-core.c [moved from drivers/media/video/tuner-core.c with 100% similarity]
drivers/media/v4l2-core/v4l2-common.c [moved from drivers/media/video/v4l2-common.c with 62% similarity]
drivers/media/v4l2-core/v4l2-compat-ioctl32.c [moved from drivers/media/video/v4l2-compat-ioctl32.c with 94% similarity]
drivers/media/v4l2-core/v4l2-ctrls.c [moved from drivers/media/video/v4l2-ctrls.c with 93% similarity]
drivers/media/v4l2-core/v4l2-dev.c [moved from drivers/media/video/v4l2-dev.c with 79% similarity]
drivers/media/v4l2-core/v4l2-device.c [moved from drivers/media/video/v4l2-device.c with 99% similarity]
drivers/media/v4l2-core/v4l2-event.c [moved from drivers/media/video/v4l2-event.c with 98% similarity]
drivers/media/v4l2-core/v4l2-fh.c [moved from drivers/media/video/v4l2-fh.c with 100% similarity]
drivers/media/v4l2-core/v4l2-int-device.c [moved from drivers/media/video/v4l2-int-device.c with 100% similarity]
drivers/media/v4l2-core/v4l2-ioctl.c [moved from drivers/media/video/v4l2-ioctl.c with 92% similarity]
drivers/media/v4l2-core/v4l2-mem2mem.c [moved from drivers/media/video/v4l2-mem2mem.c with 98% similarity]
drivers/media/v4l2-core/v4l2-subdev.c [moved from drivers/media/video/v4l2-subdev.c with 98% similarity]
drivers/media/v4l2-core/videobuf-core.c [moved from drivers/media/video/videobuf-core.c with 100% similarity]
drivers/media/v4l2-core/videobuf-dma-contig.c [moved from drivers/media/video/videobuf-dma-contig.c with 100% similarity]
drivers/media/v4l2-core/videobuf-dma-sg.c [moved from drivers/media/video/videobuf-dma-sg.c with 100% similarity]
drivers/media/v4l2-core/videobuf-dvb.c [moved from drivers/media/video/videobuf-dvb.c with 96% similarity]
drivers/media/v4l2-core/videobuf-vmalloc.c [moved from drivers/media/video/videobuf-vmalloc.c with 100% similarity]
drivers/media/v4l2-core/videobuf2-core.c [moved from drivers/media/video/videobuf2-core.c with 97% similarity]
drivers/media/v4l2-core/videobuf2-dma-contig.c [moved from drivers/media/video/videobuf2-dma-contig.c with 100% similarity]
drivers/media/v4l2-core/videobuf2-dma-sg.c [moved from drivers/media/video/videobuf2-dma-sg.c with 100% similarity]
drivers/media/v4l2-core/videobuf2-memops.c [moved from drivers/media/video/videobuf2-memops.c with 100% similarity]
drivers/media/v4l2-core/videobuf2-vmalloc.c [moved from drivers/media/video/videobuf2-vmalloc.c with 99% similarity]
drivers/media/video/Kconfig [deleted file]
drivers/media/video/Makefile [deleted file]
drivers/media/video/bt8xx/Kconfig [deleted file]
drivers/media/video/bt8xx/Makefile [deleted file]
drivers/media/video/cx23885/Kconfig [deleted file]
drivers/media/video/tlg2300/Makefile [deleted file]
drivers/mfd/88pm800.c
drivers/mfd/88pm805.c
drivers/mfd/88pm860x-core.c
drivers/mfd/aat2870-core.c
drivers/mfd/ab3100-core.c
drivers/mfd/ab8500-core.c
drivers/mfd/arizona-core.c
drivers/mfd/asic3.c
drivers/mfd/cs5535-mfd.c
drivers/mfd/da9052-core.c
drivers/mfd/davinci_voicecodec.c
drivers/mfd/db8500-prcmu.c
drivers/mfd/htc-pasic3.c
drivers/mfd/intel_msic.c
drivers/mfd/janz-cmodio.c
drivers/mfd/jz4740-adc.c
drivers/mfd/lm3533-core.c
drivers/mfd/lpc_ich.c
drivers/mfd/lpc_sch.c
drivers/mfd/max77686.c
drivers/mfd/max77693-irq.c
drivers/mfd/max77693.c
drivers/mfd/max8925-core.c
drivers/mfd/max8997.c
drivers/mfd/max8998.c
drivers/mfd/mc13xxx-core.c
drivers/mfd/mfd-core.c
drivers/mfd/palmas.c
drivers/mfd/rc5t583.c
drivers/mfd/rdc321x-southbridge.c
drivers/mfd/sec-core.c
drivers/mfd/sta2x11-mfd.c
drivers/mfd/stmpe.c
drivers/mfd/t7l66xb.c
drivers/mfd/tc3589x.c
drivers/mfd/tc6387xb.c
drivers/mfd/tc6393xb.c
drivers/mfd/ti-ssp.c
drivers/mfd/timberdale.c
drivers/mfd/tps6105x.c
drivers/mfd/tps6507x.c
drivers/mfd/tps65090.c
drivers/mfd/tps65217.c
drivers/mfd/tps6586x.c
drivers/mfd/tps65910.c
drivers/mfd/tps65912-core.c
drivers/mfd/twl4030-audio.c
drivers/mfd/twl6040-core.c
drivers/mfd/vx855.c
drivers/mfd/wl1273-core.c
drivers/mfd/wm831x-core.c
drivers/mfd/wm8400-core.c
drivers/mfd/wm8994-core.c
drivers/mmc/card/block.c
drivers/mmc/host/atmel-mci.c
drivers/mmc/host/bfin_sdh.c
drivers/mmc/host/dw_mmc.c
drivers/mmc/host/mxs-mmc.c
drivers/mmc/host/omap.c
drivers/mmc/host/sdhci-esdhc.h
drivers/mtd/mtdchar.c
drivers/mtd/ubi/vtbl.c
drivers/net/can/janz-ican3.c
drivers/net/can/mcp251x.c
drivers/net/can/sja1000/sja1000_platform.c
drivers/net/can/softing/softing_fw.c
drivers/net/can/ti_hecc.c
drivers/net/ethernet/broadcom/bnx2.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_cmn.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_dump.h
drivers/net/ethernet/broadcom/bnx2x/bnx2x_ethtool.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_link.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_main.c
drivers/net/ethernet/broadcom/bnx2x/bnx2x_stats.c
drivers/net/ethernet/cadence/at91_ether.c
drivers/net/ethernet/cirrus/cs89x0.c
drivers/net/ethernet/emulex/benet/be_cmds.c
drivers/net/ethernet/emulex/benet/be_main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/gianfar_ethtool.c
drivers/net/ethernet/freescale/gianfar_ptp.c
drivers/net/ethernet/i825xx/znet.c
drivers/net/ethernet/ibm/ibmveth.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/netdev.c
drivers/net/ethernet/mellanox/mlx4/icm.c
drivers/net/ethernet/mellanox/mlx4/icm.h
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/mellanox/mlx4/mlx4.h
drivers/net/ethernet/mellanox/mlx4/resource_tracker.c
drivers/net/ethernet/octeon/octeon_mgmt.c
drivers/net/ethernet/pasemi/pasemi_mac.c
drivers/net/ethernet/qlogic/netxen/netxen_nic_main.c
drivers/net/ethernet/qlogic/qlcnic/qlcnic_ctx.c
drivers/net/ethernet/seeq/sgiseeq.c
drivers/net/ethernet/sfc/ethtool.c
drivers/net/ethernet/stmicro/stmmac/common.h
drivers/net/ethernet/stmicro/stmmac/descs.h
drivers/net/ethernet/stmicro/stmmac/descs_com.h
drivers/net/ethernet/stmicro/stmmac/dwmac100.h
drivers/net/ethernet/stmicro/stmmac/dwmac1000.h
drivers/net/ethernet/stmicro/stmmac/dwmac_dma.h
drivers/net/ethernet/stmicro/stmmac/mmc.h
drivers/net/ethernet/stmicro/stmmac/mmc_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.c
drivers/net/ethernet/stmicro/stmmac/stmmac_timer.h
drivers/net/ethernet/ti/davinci_mdio.c
drivers/net/fddi/skfp/pmf.c
drivers/net/irda/sh_sir.c
drivers/net/phy/bcm87xx.c
drivers/net/phy/micrel.c
drivers/net/phy/smsc.c
drivers/net/ppp/pppoe.c
drivers/net/team/team.c
drivers/net/usb/asix_devices.c
drivers/net/usb/qmi_wwan.c
drivers/net/usb/sierra_net.c
drivers/net/usb/smsc75xx.c
drivers/net/usb/usbnet.c
drivers/net/wan/ixp4xx_hss.c
drivers/net/wireless/ath/ath5k/eeprom.c
drivers/net/wireless/ath/ath5k/eeprom.h
drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
drivers/net/wireless/ath/ath9k/ar9003_paprd.c
drivers/net/wireless/ath/ath9k/ar9003_phy.h
drivers/net/wireless/ath/ath9k/debug.c
drivers/net/wireless/ath/ath9k/gpio.c
drivers/net/wireless/ath/ath9k/hw.c
drivers/net/wireless/ath/ath9k/hw.h
drivers/net/wireless/ath/ath9k/link.c
drivers/net/wireless/ath/ath9k/xmit.c
drivers/net/wireless/brcm80211/brcmfmac/bcmsdh_sdmmc.c
drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
drivers/net/wireless/brcm80211/brcmfmac/usb.c
drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
drivers/net/wireless/brcm80211/brcmsmac/channel.c
drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
drivers/net/wireless/ipw2x00/ipw2100.c
drivers/net/wireless/iwlwifi/dvm/debugfs.c
drivers/net/wireless/iwlwifi/pcie/internal.h
drivers/net/wireless/iwlwifi/pcie/rx.c
drivers/net/wireless/iwlwifi/pcie/trans.c
drivers/net/wireless/libertas/if_sdio.c
drivers/net/wireless/mwifiex/cmdevt.c
drivers/net/wireless/rt2x00/rt2400pci.c
drivers/net/wireless/rt2x00/rt2400pci.h
drivers/net/wireless/rt2x00/rt2500pci.c
drivers/net/wireless/rt2x00/rt2500usb.c
drivers/net/wireless/rt2x00/rt2500usb.h
drivers/net/wireless/rt2x00/rt2800lib.c
drivers/net/wireless/rt2x00/rt2800pci.c
drivers/net/wireless/rt2x00/rt2800usb.c
drivers/net/wireless/rt2x00/rt2x00dev.c
drivers/net/wireless/rt2x00/rt61pci.c
drivers/net/wireless/rt2x00/rt61pci.h
drivers/net/wireless/rt2x00/rt73usb.c
drivers/net/wireless/rt2x00/rt73usb.h
drivers/net/wireless/rtlwifi/rtl8192ce/def.h
drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
drivers/net/xen-netfront.c
drivers/pci/pci-driver.c
drivers/pci/pci-sysfs.c
drivers/pci/pci.c
drivers/pci/pcie/portdrv_pci.c
drivers/pci/probe.c
drivers/platform/x86/acer-wmi.c
drivers/platform/x86/apple-gmux.c
drivers/platform/x86/asus-laptop.c
drivers/platform/x86/asus-wmi.c
drivers/platform/x86/eeepc-laptop.c
drivers/platform/x86/samsung-laptop.c
drivers/platform/x86/thinkpad_acpi.c
drivers/pwm/pwm-tiecap.c
drivers/pwm/pwm-tiehrpwm.c
drivers/regulator/tps65217-regulator.c
drivers/rpmsg/virtio_rpmsg_bus.c
drivers/rtc/rtc-at91sam9.c
drivers/rtc/rtc-twl.c
drivers/s390/block/dasd.c
drivers/s390/block/dasd_alias.c
drivers/s390/block/dasd_eckd.c
drivers/s390/block/dasd_ioctl.c
drivers/s390/cio/device.c
drivers/scsi/bnx2i/bnx2i_hwi.c
drivers/scsi/hpsa.c
drivers/scsi/megaraid/megaraid_sas_base.c
drivers/scsi/mpt2sas/mpt2sas_base.c
drivers/scsi/scsi_error.c
drivers/scsi/scsi_lib.c
drivers/scsi/scsi_scan.c
drivers/scsi/virtio_scsi.c
drivers/sh/intc/core.c
drivers/sh/pfc/pinctrl.c
drivers/spi/spi-bcm63xx.c
drivers/staging/android/android_alarm.h
drivers/staging/comedi/drivers/amplc_dio200.c
drivers/staging/comedi/drivers/amplc_pc236.c
drivers/staging/comedi/drivers/amplc_pc263.c
drivers/staging/comedi/drivers/amplc_pci224.c
drivers/staging/comedi/drivers/amplc_pci230.c
drivers/staging/comedi/drivers/das08.c
drivers/staging/iio/accel/lis3l02dq_ring.c
drivers/staging/iio/adc/ad7192.c
drivers/staging/iio/gyro/adis16260_core.c
drivers/staging/iio/imu/adis16400_core.c
drivers/staging/iio/meter/ade7753.c
drivers/staging/iio/meter/ade7754.c
drivers/staging/iio/meter/ade7759.c
drivers/staging/media/Kconfig
drivers/staging/media/Makefile
drivers/staging/media/as102/Makefile
drivers/staging/media/cxd2099/Makefile
drivers/staging/media/cxd2099/cxd2099.c
drivers/staging/media/dt3155v4l/dt3155v4l.c
drivers/staging/media/easycap/Kconfig [deleted file]
drivers/staging/media/easycap/Makefile [deleted file]
drivers/staging/media/easycap/README [deleted file]
drivers/staging/media/easycap/easycap.h [deleted file]
drivers/staging/media/easycap/easycap_ioctl.c [deleted file]
drivers/staging/media/easycap/easycap_low.c [deleted file]
drivers/staging/media/easycap/easycap_main.c [deleted file]
drivers/staging/media/easycap/easycap_settings.c [deleted file]
drivers/staging/media/easycap/easycap_sound.c [deleted file]
drivers/staging/media/easycap/easycap_testcard.c [deleted file]
drivers/staging/media/go7007/Makefile
drivers/staging/media/go7007/go7007-v4l2.c
drivers/staging/media/lirc/Kconfig
drivers/staging/media/lirc/Makefile
drivers/staging/media/lirc/lirc_ene0100.h [deleted file]
drivers/staging/media/lirc/lirc_igorplugusb.c
drivers/staging/media/lirc/lirc_ttusbir.c [deleted file]
drivers/staging/media/lirc/lirc_zilog.c
drivers/staging/nvec/nvec.c
drivers/staging/omapdrm/omap_connector.c
drivers/staging/ozwpan/ozcdev.c
drivers/staging/rtl8712/recv_linux.c
drivers/staging/vt6656/dpc.c
drivers/staging/vt6656/rxtx.c
drivers/staging/wlan-ng/cfg80211.c
drivers/staging/zcache/zcache-main.c
drivers/target/iscsi/iscsi_target_login.c
drivers/target/target_core_alua.c
drivers/target/target_core_device.c
drivers/target/target_core_iblock.c
drivers/target/target_core_pr.c
drivers/target/target_core_pscsi.c
drivers/target/target_core_spc.c
drivers/target/target_core_transport.c
drivers/tty/serial/imx.c
drivers/usb/chipidea/udc.c
drivers/usb/class/cdc-wdm.c
drivers/usb/core/devices.c
drivers/usb/core/hcd.c
drivers/usb/core/quirks.c
drivers/usb/dwc3/core.c
drivers/usb/dwc3/ep0.c
drivers/usb/dwc3/gadget.c
drivers/usb/gadget/at91_udc.c
drivers/usb/gadget/dummy_hcd.c
drivers/usb/gadget/f_fs.c
drivers/usb/gadget/s3c-hsotg.c
drivers/usb/gadget/u_serial.c
drivers/usb/host/ehci-q.c
drivers/usb/host/ohci-at91.c
drivers/usb/host/pci-quirks.c
drivers/usb/host/pci-quirks.h
drivers/usb/host/xhci-hub.c
drivers/usb/host/xhci-plat.c
drivers/usb/host/xhci.c
drivers/usb/host/xhci.h
drivers/usb/musb/musb_host.c
drivers/usb/musb/musbhsdma.c
drivers/usb/musb/tusb6010.c
drivers/usb/renesas_usbhs/fifo.c
drivers/usb/serial/ftdi_sio.c
drivers/usb/serial/ftdi_sio_ids.h
drivers/usb/serial/option.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/video/auo_k190x.c
drivers/video/console/bitblit.c
drivers/video/console/fbcon.c
drivers/video/mb862xx/mb862xxfbdrv.c
drivers/video/omap2/dss/sdi.c
drivers/video/omap2/omapfb/omapfb-main.c
drivers/watchdog/booke_wdt.c
drivers/watchdog/da9052_wdt.c
drivers/watchdog/hpwdt.c
drivers/watchdog/watchdog_core.c
drivers/xen/gntdev.c
drivers/xen/grant-table.c
drivers/xen/platform-pci.c
drivers/xen/swiotlb-xen.c
drivers/xen/xen-pciback/pci_stub.c
fs/bio.c
fs/block_dev.c
fs/btrfs/backref.c
fs/btrfs/compression.c
fs/btrfs/ctree.c
fs/btrfs/ctree.h
fs/btrfs/delayed-inode.c
fs/btrfs/delayed-ref.c
fs/btrfs/delayed-ref.h
fs/btrfs/disk-io.c
fs/btrfs/disk-io.h
fs/btrfs/extent-tree.c
fs/btrfs/extent_io.c
fs/btrfs/file-item.c
fs/btrfs/inode.c
fs/btrfs/ioctl.c
fs/btrfs/locking.c
fs/btrfs/qgroup.c
fs/btrfs/root-tree.c
fs/btrfs/super.c
fs/btrfs/transaction.c
fs/btrfs/volumes.c
fs/btrfs/volumes.h
fs/buffer.c
fs/cifs/cifs_unicode.c
fs/cifs/cifssmb.c
fs/cifs/dir.c
fs/cifs/file.c
fs/cifs/inode.c
fs/cifs/link.c
fs/cifs/smb2misc.c
fs/cifs/smb2pdu.h
fs/cifs/transport.c
fs/dcache.c
fs/debugfs/file.c
fs/direct-io.c
fs/ecryptfs/file.c
fs/ecryptfs/inode.c
fs/ecryptfs/main.c
fs/ext3/inode.c
fs/fuse/control.c
fs/fuse/cuse.c
fs/fuse/dev.c
fs/fuse/inode.c
fs/gfs2/file.c
fs/gfs2/inode.c
fs/gfs2/rgrp.c
fs/jbd/journal.c
fs/lockd/svclock.c
fs/logfs/dev_bdev.c
fs/logfs/inode.c
fs/logfs/journal.c
fs/logfs/readwrite.c
fs/logfs/segment.c
fs/namespace.c
fs/nfs/file.c
fs/nfs/inode.c
fs/nfs/nfs3proc.c
fs/nfs/nfs4file.c
fs/nfs/nfs4proc.c
fs/nfs/nfs4xdr.c
fs/nfs/super.c
fs/nfsd/nfs4callback.c
fs/nfsd/state.h
fs/proc/proc_sysctl.c
fs/quota/dquot.c
fs/reiserfs/bitmap.c
fs/reiserfs/inode.c
fs/stat.c
fs/ubifs/debug.h
fs/ubifs/lpt.c
fs/ubifs/recovery.c
fs/ubifs/replay.c
fs/ubifs/super.c
fs/udf/file.c
fs/udf/inode.c
fs/udf/super.c
fs/xfs/xfs_buf.c
fs/xfs/xfs_buf.h
fs/xfs/xfs_discard.c
fs/xfs/xfs_ialloc.c
fs/xfs/xfs_rtalloc.c
fs/xfs/xfs_super.c
include/asm-generic/unistd.h
include/drm/drm_crtc.h
include/drm/drm_fourcc.h
include/drm/drm_mode.h
include/linux/Kbuild
include/linux/atmel-ssc.h
include/linux/blkdev.h
include/linux/compiler-gcc4.h
include/linux/compiler.h
include/linux/cpuidle.h
include/linux/dcache.h
include/linux/dvb/frontend.h
include/linux/dvb/version.h
include/linux/i2c-pnx.h
include/linux/iommu.h
include/linux/kernel.h
include/linux/kobject.h
include/linux/ktime.h
include/linux/mISDNhw.h
include/linux/memory.h
include/linux/mfd/core.h
include/linux/mfd/tps65217.h
include/linux/micrel_phy.h
include/linux/mlx4/device.h
include/linux/mmc/card.h
include/linux/mv643xx_eth.h
include/linux/nfs_fs.h
include/linux/nfs_xdr.h
include/linux/nvme.h
include/linux/omap3isp.h
include/linux/pci_ids.h
include/linux/perf_event.h
include/linux/sched.h
include/linux/security.h
include/linux/sunrpc/xprt.h
include/linux/time.h
include/linux/v4l2-common.h
include/linux/v4l2-controls.h [new file with mode: 0644]
include/linux/v4l2-mediabus.h
include/linux/v4l2-subdev.h
include/linux/videodev2.h
include/linux/xfrm.h
include/media/ad9389b.h [new file with mode: 0644]
include/media/adv7604.h [new file with mode: 0644]
include/media/davinci/vpbe.h
include/media/davinci/vpbe_types.h
include/media/davinci/vpbe_venc.h
include/media/davinci/vpif_types.h
include/media/ir-rx51.h [new file with mode: 0644]
include/media/mt9v032.h
include/media/omap3isp.h
include/media/s5k4ecgx.h [new file with mode: 0644]
include/media/s5p_fimc.h
include/media/saa7146.h
include/media/soc_camera.h
include/media/v4l2-chip-ident.h
include/media/v4l2-common.h
include/media/v4l2-ctrls.h
include/media/v4l2-dev.h
include/media/v4l2-event.h
include/media/v4l2-ioctl.h
include/media/v4l2-mem2mem.h
include/media/v4l2-subdev.h
include/media/videobuf-dvb.h
include/media/videobuf2-core.h
include/net/bluetooth/smp.h
include/net/ip6_fib.h
include/net/net_namespace.h
include/net/netfilter/nf_conntrack_ecache.h
include/net/netns/ipv4.h
include/net/route.h
include/net/sock.h
include/net/xfrm.h
include/sound/tea575x-tuner.h
include/target/target_core_backend.h
include/target/target_core_base.h
include/trace/events/kmem.h
include/xen/events.h
include/xen/grant_table.h
kernel/events/core.c
kernel/events/hw_breakpoint.c
kernel/fork.c
kernel/pid_namespace.c
kernel/sched/core.c
kernel/sched/fair.c
kernel/sched/rt.c
kernel/sched/sched.h
kernel/time/tick-sched.c
kernel/time/timekeeping.c
kernel/trace/trace_syscalls.c
kernel/workqueue.c
lib/digsig.c
lib/flex_proportions.c
mm/filemap.c
mm/huge_memory.c
mm/memblock.c
mm/memory_hotplug.c
mm/mempolicy.c
mm/mmap.c
mm/page_alloc.c
mm/slab.c
mm/slub.c
mm/vmscan.c
net/batman-adv/bat_iv_ogm.c
net/batman-adv/bitarray.h
net/batman-adv/soft-interface.c
net/bluetooth/bnep/sock.c
net/bluetooth/cmtp/sock.c
net/bluetooth/hci_conn.c
net/bluetooth/hci_core.c
net/bluetooth/hci_sock.c
net/bluetooth/hidp/sock.c
net/bluetooth/l2cap_core.c
net/bluetooth/l2cap_sock.c
net/bluetooth/mgmt.c
net/bluetooth/smp.c
net/bridge/netfilter/ebt_log.c
net/caif/cfsrvl.c
net/ceph/messenger.c
net/core/dev.c
net/core/netpoll.c
net/core/pktgen.c
net/core/skbuff.c
net/core/sock.c
net/ipv4/arp.c
net/ipv4/devinet.c
net/ipv4/fib_frontend.c
net/ipv4/fib_rules.c
net/ipv4/fib_trie.c
net/ipv4/inetpeer.c
net/ipv4/ipmr.c
net/ipv4/netfilter/nf_nat_sip.c
net/ipv4/raw.c
net/ipv4/route.c
net/ipv4/tcp.c
net/ipv4/tcp_input.c
net/ipv4/udp.c
net/ipv6/esp6.c
net/ipv6/inet6_connection_sock.c
net/ipv6/ip6_fib.c
net/ipv6/mip6.c
net/ipv6/raw.c
net/ipv6/route.c
net/ipv6/tcp_ipv6.c
net/ipv6/udp.c
net/l2tp/l2tp_core.c
net/l2tp/l2tp_core.h
net/l2tp/l2tp_eth.c
net/l2tp/l2tp_netlink.c
net/mac80211/cfg.c
net/mac80211/mlme.c
net/mac80211/tx.c
net/netfilter/ipvs/ip_vs_ctl.c
net/netfilter/nf_conntrack_core.c
net/netfilter/nf_conntrack_netlink.c
net/netfilter/nf_conntrack_proto_tcp.c
net/netfilter/nfnetlink_log.c
net/netfilter/xt_LOG.c
net/netfilter/xt_limit.c
net/netlink/af_netlink.c
net/netrom/af_netrom.c
net/openvswitch/actions.c
net/openvswitch/datapath.c
net/openvswitch/flow.h
net/packet/af_packet.c
net/sched/sch_cbq.c
net/sched/sch_fq_codel.c
net/sched/sch_gred.c
net/sched/sch_qfq.c
net/sctp/output.c
net/socket.c
net/sunrpc/svc_xprt.c
net/sunrpc/svcsock.c
net/sunrpc/xprt.c
net/sunrpc/xprtrdma/transport.c
net/sunrpc/xprtsock.c
net/wireless/nl80211.c
net/wireless/reg.c
net/xfrm/xfrm_input.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_replay.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
scripts/Makefile.fwinst
scripts/checksyscalls.sh
scripts/link-vmlinux.sh
security/selinux/include/xfrm.h
sound/core/compress_offload.c
sound/i2c/other/tea575x-tuner.c
sound/pci/Kconfig
sound/pci/hda/hda_codec.c
sound/pci/hda/hda_codec.h
sound/pci/hda/hda_intel.c
sound/pci/hda/patch_sigmatel.c
sound/pci/ice1712/prodigy_hifi.c
sound/soc/codecs/arizona.c
sound/soc/codecs/mc13783.c
sound/soc/codecs/wm2000.c
sound/soc/codecs/wm8904.c
sound/soc/fsl/imx-sgtl5000.c
sound/soc/omap/am3517evm.c
sound/soc/samsung/dma.c
sound/soc/soc-dapm.c
sound/soc/spear/spear_pcm.c
sound/soc/tegra/tegra_alc5632.c
sound/soc/tegra/tegra_pcm.c
sound/soc/ux500/ux500_msp_i2s.c
sound/usb/card.c
sound/usb/endpoint.c
sound/usb/endpoint.h
sound/usb/pcm.c
tools/perf/util/python-ext-sources
virt/kvm/kvm_main.c

index 34f51100f0299cb5a96a77984def99dbfdd9367d..dff1f48d252d8f0d36aa31cccf6514cb02b3d333 100644 (file)
@@ -210,3 +210,15 @@ Users:
                firmware assigned instance number of the PCI
                device that can help in understanding the firmware
                intended order of the PCI device.
+
+What:          /sys/bus/pci/devices/.../d3cold_allowed
+Date:          July 2012
+Contact:       Huang Ying <ying.huang@intel.com>
+Description:
+               d3cold_allowed is bit to control whether the corresponding PCI
+               device can be put into D3Cold state.  If it is cleared, the
+               device will never be put into D3Cold state.  If it is set, the
+               device may be put into D3Cold state if other requirements are
+               satisfied too.  Reading this attribute will show the current
+               value of d3cold_allowed bit.  Writing this attribute will set
+               the value of d3cold_allowed bit.
index 362520992ced54497deb8dca8b6fa4a60bd61125..9b7e4c55792803b1c053bc99026860a5ce56e88d 100644 (file)
@@ -300,7 +300,7 @@ $(MEDIA_OBJ_DIR)/media-entities.tmpl: $(MEDIA_OBJ_DIR)/v4l2.xml
        @(                                                              \
        for ident in $(IOCTLS) ; do                                     \
          entity=`echo $$ident | tr _ -` ;                              \
-         id=`grep "<refname>$$ident" $(MEDIA_OBJ_DIR)/vidioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
+         id=`grep "<refname>$$ident" $(MEDIA_OBJ_DIR)/vidioc-*.xml $(MEDIA_OBJ_DIR)/media-ioc-*.xml | sed -r s,"^.*/(.*).xml.*","\1",` ; \
          echo "<!ENTITY $$entity \"<link"                              \
            "linkend='$$id'><constant>$$ident</constant></link>\">"     \
          >>$@ ;                                                        \
index d64386237207a9f27867fd6e9bee02620ff4c8bb..a7ea56c71a27cc5cebcfd6ea91b8d17dfa9432c4 100644 (file)
@@ -1,12 +1,16 @@
 <title>DVB Audio Device</title>
 <para>The DVB audio device controls the MPEG2 audio decoder of the DVB hardware. It
 can be accessed through <emphasis role="tt">/dev/dvb/adapter0/audio0</emphasis>. Data types and and
-ioctl definitions can be accessed by including <emphasis role="tt">linux/dvb/video.h</emphasis> in your
+ioctl definitions can be accessed by including <emphasis role="tt">linux/dvb/audio.h</emphasis> in your
 application.
 </para>
 <para>Please note that some DVB cards don&#8217;t have their own MPEG decoder, which results in
 the omission of the audio and video device.
 </para>
+<para>
+These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
+of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
+have been created to replace that functionality.</para>
 
 <section id="audio_data_types">
 <title>Audio Data Types</title>
@@ -558,6 +562,8 @@ role="subsection"><title>AUDIO_SELECT_SOURCE</title>
 role="subsection"><title>AUDIO_SET_MUTE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; with the <constant>V4L2_DEC_CMD_START_MUTE_AUDIO</constant> flag instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the audio device to mute the stream that is currently being
@@ -730,6 +736,8 @@ role="subsection"><title>AUDIO_SET_BYPASS_MODE</title>
 role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+<constant>V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK</constant> control instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Audio Device to select the requested channel if possible.</para>
@@ -772,6 +780,109 @@ role="subsection"><title>AUDIO_CHANNEL_SELECT</title>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
 
+</section><section id="AUDIO_BILINGUAL_CHANNEL_SELECT"
+role="subsection"><title>AUDIO_BILINGUAL_CHANNEL_SELECT</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. It has been replaced by
+the V4L2 <constant>V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK</constant> control
+for MPEG decoders controlled through V4L2.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Audio Device to select the requested channel for bilingual streams if possible.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ AUDIO_BILINGUAL_CHANNEL_SELECT, audio_channel_select_t);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals AUDIO_BILINGUAL_CHANNEL_SELECT for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>audio_channel_select_t
+ch</para>
+</entry><entry
+ align="char">
+<para>Select the output format of the audio (mono left/right,
+ stereo).</para>
+</entry>
+ </row>
+</tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="AUDIO_GET_PTS"
+role="subsection"><title>AUDIO_GET_PTS</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. If you need this functionality,
+then please contact the linux-media mailing list (&v4l-ml;).</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Audio Device to return the current PTS timestamp.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ AUDIO_GET_PTS, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals AUDIO_GET_PTS for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+</para>
+<para>
+The PTS should belong to the currently played
+frame if possible, but may also be a value close to it
+like the PTS of the last decoded frame or the last PTS
+extracted by the PES parser.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="AUDIO_GET_STATUS"
 role="subsection"><title>AUDIO_GET_STATUS</title>
 <para>DESCRIPTION
index 5c4adb44b1c18a4207ac993132e823c83cac6624..85eaf4fe2931fc96cea50ba2d502a401d475c22c 100644 (file)
@@ -226,4 +226,357 @@ typedef struct ca_pid {
 </entry>
  </row></tbody></tgroup></informaltable>
  </section>
+
+<section id="CA_RESET"
+role="subsection"><title>CA_RESET</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_RESET);
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_RESET for this command.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_CAP"
+role="subsection"><title>CA_GET_CAP</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_CAP,
+ ca_caps_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_CAP for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_caps_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_SLOT_INFO"
+role="subsection"><title>CA_GET_SLOT_INFO</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_SLOT_INFO,
+ ca_slot_info_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_SLOT_INFO for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_slot_info_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_DESCR_INFO"
+role="subsection"><title>CA_GET_DESCR_INFO</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_DESCR_INFO,
+ ca_descr_info_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_DESCR_INFO for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_descr_info_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_GET_MSG"
+role="subsection"><title>CA_GET_MSG</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_GET_MSG,
+ ca_msg_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_GET_MSG for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_msg_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SEND_MSG"
+role="subsection"><title>CA_SEND_MSG</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SEND_MSG,
+ ca_msg_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SEND_MSG for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_msg_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SET_DESCR"
+role="subsection"><title>CA_SET_DESCR</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SET_DESCR,
+ ca_descr_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SET_DESCR for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_descr_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="CA_SET_PID"
+role="subsection"><title>CA_SET_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = CA_SET_PID,
+ ca_pid_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals CA_SET_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>ca_pid_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
 </section>
index 37c17908aa400acd225881af1acb5383e6221442..86de89cfbd676cbeda054aba040432e25c4f68d3 100644 (file)
@@ -899,4 +899,232 @@ typedef enum {
 <para>Invalid stc number.</para>
 </entry>
  </row></tbody></tgroup></informaltable>
- </section></section>
+ </section>
+
+<section id="DMX_GET_PES_PIDS"
+role="subsection"><title>DMX_GET_PES_PIDS</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_GET_PES_PIDS,
+ __u16[5]);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_GET_PES_PIDS for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16[5]
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_GET_CAPS"
+role="subsection"><title>DMX_GET_CAPS</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_GET_CAPS,
+ dmx_caps_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_GET_CAPS for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>dmx_caps_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_SET_SOURCE"
+role="subsection"><title>DMX_SET_SOURCE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_SET_SOURCE,
+ dmx_source_t *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_SET_SOURCE for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>dmx_source_t *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_ADD_PID"
+role="subsection"><title>DMX_ADD_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_ADD_PID,
+ __u16 *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_ADD_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16 *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="DMX_REMOVE_PID"
+role="subsection"><title>DMX_REMOVE_PID</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = DMX_REMOVE_PID,
+ __u16 *);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals DMX_REMOVE_PID for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u16 *
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+
+</section>
index 2ab6ddcfc4e095dada4e2e6eb8084003096c279a..757488b24f4f2518898f13f55de57e9d708fa575 100644 (file)
@@ -28,7 +28,7 @@
        <holder>Convergence GmbH</holder>
 </copyright>
 <copyright>
-       <year>2009-2011</year>
+       <year>2009-2012</year>
        <holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
@@ -84,7 +84,7 @@ Added ISDB-T test originally written by Patrick Boettcher
 
 
 <title>LINUX DVB API</title>
-<subtitle>Version 5.2</subtitle>
+<subtitle>Version 5.8</subtitle>
 <!-- ADD THE CHAPTERS HERE -->
   <chapter id="dvb_introdution">
     &sub-intro;
index e633c097a8d14b954975743e67816867f5b9fdaa..957e3acaae8e9c7e0cbc6ee377885c53d2b298d1 100644 (file)
@@ -194,6 +194,7 @@ get/set up to 64 properties. The actual meaning of each property is described on
        APSK_16,
        APSK_32,
        DQPSK,
+       QAM_4_NR,
  } fe_modulation_t;
 </programlisting>
        </section>
@@ -265,6 +266,7 @@ typedef enum fe_code_rate {
        FEC_AUTO,
        FEC_3_5,
        FEC_9_10,
+       FEC_2_5,
 } fe_code_rate_t;
        </programlisting>
        <para>which correspond to error correction rates of 1/2, 2/3, etc.,
@@ -351,7 +353,7 @@ typedef enum fe_delivery_system {
        SYS_ISDBC,
        SYS_ATSC,
        SYS_ATSCMH,
-       SYS_DMBTH,
+       SYS_DTMB,
        SYS_CMMB,
        SYS_DAB,
        SYS_DVBT2,
@@ -567,28 +569,33 @@ typedef enum fe_delivery_system {
                        <title><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></title>
                        <para>RS frame mode.</para>
                        <para>Possible values are:</para>
+                 <para id="atscmh-rs-frame-mode">
 <programlisting>
 typedef enum atscmh_rs_frame_mode {
        ATSCMH_RSFRAME_PRI_ONLY  = 0,
        ATSCMH_RSFRAME_PRI_SEC   = 1,
 } atscmh_rs_frame_mode_t;
 </programlisting>
+                 </para>
                </section>
                <section id="DTV-ATSCMH-RS-FRAME-ENSEMBLE">
                        <title><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></title>
                        <para>RS frame ensemble.</para>
                        <para>Possible values are:</para>
+                 <para id="atscmh-rs-frame-ensemble">
 <programlisting>
 typedef enum atscmh_rs_frame_ensemble {
        ATSCMH_RSFRAME_ENS_PRI   = 0,
        ATSCMH_RSFRAME_ENS_SEC   = 1,
 } atscmh_rs_frame_ensemble_t;
 </programlisting>
+                 </para>
                </section>
                <section id="DTV-ATSCMH-RS-CODE-MODE-PRI">
                        <title><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></title>
                        <para>RS code mode (primary).</para>
                        <para>Possible values are:</para>
+                 <para id="atscmh-rs-code-mode">
 <programlisting>
 typedef enum atscmh_rs_code_mode {
        ATSCMH_RSCODE_211_187    = 0,
@@ -596,6 +603,7 @@ typedef enum atscmh_rs_code_mode {
        ATSCMH_RSCODE_235_187    = 2,
 } atscmh_rs_code_mode_t;
 </programlisting>
+                 </para>
                </section>
                <section id="DTV-ATSCMH-RS-CODE-MODE-SEC">
                        <title><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></title>
@@ -613,23 +621,27 @@ typedef enum atscmh_rs_code_mode {
                        <title><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></title>
                        <para>Series Concatenated Convolutional Code Block Mode.</para>
                        <para>Possible values are:</para>
+                 <para id="atscmh-sccc-block-mode">
 <programlisting>
 typedef enum atscmh_sccc_block_mode {
        ATSCMH_SCCC_BLK_SEP      = 0,
        ATSCMH_SCCC_BLK_COMB     = 1,
 } atscmh_sccc_block_mode_t;
 </programlisting>
+                 </para>
                </section>
                <section id="DTV-ATSCMH-SCCC-CODE-MODE-A">
                        <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></title>
                        <para>Series Concatenated Convolutional Code Rate.</para>
                        <para>Possible values are:</para>
+                 <para id="atscmh-sccc-code-mode">
 <programlisting>
 typedef enum atscmh_sccc_code_mode {
        ATSCMH_SCCC_CODE_HLF     = 0,
        ATSCMH_SCCC_CODE_QTR     = 1,
 } atscmh_sccc_code_mode_t;
 </programlisting>
+                 </para>
                </section>
                <section id="DTV-ATSCMH-SCCC-CODE-MODE-B">
                        <title><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></title>
@@ -725,6 +737,9 @@ typedef enum fe_guard_interval {
        GUARD_INTERVAL_1_128,
        GUARD_INTERVAL_19_128,
        GUARD_INTERVAL_19_256,
+       GUARD_INTERVAL_PN420,
+       GUARD_INTERVAL_PN595,
+       GUARD_INTERVAL_PN945,
 } fe_guard_interval_t;
 </programlisting>
 
@@ -733,6 +748,7 @@ typedef enum fe_guard_interval {
                        try to find the correct guard interval (if capable) and will use TMCC to fill
                        in the missing parameters.</para>
                <para>2) Intervals 1/128, 19/128 and 19/256 are used only for DVB-T2 at present</para>
+               <para>3) DTMB specifies PN420, PN595 and PN945.</para>
        </section>
        <section id="DTV-TRANSMISSION-MODE">
                <title><constant>DTV_TRANSMISSION_MODE</constant></title>
@@ -749,6 +765,8 @@ typedef enum fe_transmit_mode {
        TRANSMISSION_MODE_1K,
        TRANSMISSION_MODE_16K,
        TRANSMISSION_MODE_32K,
+       TRANSMISSION_MODE_C1,
+       TRANSMISSION_MODE_C3780,
 } fe_transmit_mode_t;
 </programlisting>
                <para>Notes:</para>
@@ -760,6 +778,7 @@ typedef enum fe_transmit_mode {
                        use TMCC to fill in the missing parameters.</para>
                <para>3) DVB-T specifies 2K and 8K as valid sizes.</para>
                <para>4) DVB-T2 specifies 1K, 2K, 4K, 8K, 16K and 32K.</para>
+               <para>5) DTMB specifies C1 and C3780.</para>
        </section>
        <section id="DTV-HIERARCHY">
        <title><constant>DTV_HIERARCHY</constant></title>
@@ -774,17 +793,28 @@ typedef enum fe_hierarchy {
  } fe_hierarchy_t;
        </programlisting>
        </section>
-       <section id="DTV-ISDBS-TS-ID">
-       <title><constant>DTV_ISDBS_TS_ID</constant></title>
-       <para>Currently unused.</para>
+       <section id="DTV-STREAM-ID">
+       <title><constant>DTV_STREAM_ID</constant></title>
+       <para>DVB-S2, DVB-T2 and ISDB-S support the transmission of several
+             streams on a single transport stream.
+             This property enables the DVB driver to handle substream filtering,
+             when supported by the hardware.
+             By default, substream filtering is disabled.
+       </para><para>
+             For DVB-S2 and DVB-T2, the valid substream id range is from 0 to 255.
+       </para><para>
+             For ISDB, the valid substream id range is from 1 to 65535.
+       </para><para>
+             To disable it, you should use the special macro NO_STREAM_ID_FILTER.
+       </para><para>
+             Note: any value outside the id range also disables filtering.
+       </para>
        </section>
-       <section id="DTV-DVBT2-PLP-ID">
-               <title><constant>DTV_DVBT2_PLP_ID</constant></title>
-               <para>DVB-T2 supports Physical Layer Pipes (PLP) to allow transmission of
-                       many data types via a single multiplex. The API will soon support this
-                       at which point this section will be expanded.</para>
+       <section id="DTV-DVBT2-PLP-ID-LEGACY">
+               <title><constant>DTV_DVBT2_PLP_ID_LEGACY</constant></title>
+               <para>Obsolete, replaced with DTV_STREAM_ID.</para>
        </section>
-       <section id="DTV_ENUM_DELSYS">
+       <section id="DTV-ENUM-DELSYS">
                <title><constant>DTV_ENUM_DELSYS</constant></title>
                <para>A Multi standard frontend needs to advertise the delivery systems provided.
                        Applications need to enumerate the provided delivery systems, before using
@@ -796,6 +826,29 @@ typedef enum fe_hierarchy {
                        FE_GET_INFO. In the case of a legacy frontend, the result is just the same
                        as with FE_GET_INFO, but in a more structured format </para>
        </section>
+       <section id="DTV-INTERLEAVING">
+       <title><constant>DTV_INTERLEAVING</constant></title>
+       <para id="fe-interleaving">Interleaving mode</para>
+       <programlisting>
+enum fe_interleaving {
+       INTERLEAVING_NONE,
+       INTERLEAVING_AUTO,
+       INTERLEAVING_240,
+       INTERLEAVING_720,
+};
+       </programlisting>
+       </section>
+       <section id="DTV-LNA">
+       <title><constant>DTV_LNA</constant></title>
+       <para>Low-noise amplifier.</para>
+       <para>Hardware might offer controllable LNA which can be set manually
+               using that parameter. Usually LNA could be found only from
+               terrestrial devices if at all.</para>
+       <para>Possible values: 0, 1, LNA_AUTO</para>
+       <para>0, LNA off</para>
+       <para>1, LNA on</para>
+       <para>use the special macro LNA_AUTO to set LNA auto</para>
+       </section>
 </section>
        <section id="frontend-property-terrestrial-systems">
        <title>Properties used on terrestrial delivery systems</title>
@@ -816,6 +869,7 @@ typedef enum fe_hierarchy {
                                <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
                                <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
                                <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
                        </itemizedlist>
                </section>
                <section id="dvbt2-params">
@@ -838,7 +892,8 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-HIERARCHY"><constant>DTV_HIERARCHY</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-DVBT2-PLP-ID"><constant>DTV_DVBT2_PLP_ID</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
                </itemizedlist>
                </section>
                <section id="isdbt">
@@ -925,13 +980,32 @@ typedef enum fe_hierarchy {
                                <listitem><para><link linkend="DTV-ATSCMH-PRC"><constant>DTV_ATSCMH_PRC</constant></link></para></listitem>
                                <listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-MODE"><constant>DTV_ATSCMH_RS_FRAME_MODE</constant></link></para></listitem>
                                <listitem><para><link linkend="DTV-ATSCMH-RS-FRAME-ENSEMBLE"><constant>DTV_ATSCMH_RS_FRAME_ENSEMBLE</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-CODE-MODE-PRI"><constant>DTV_ATSCMH_CODE_MODE_PRI</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-CODE-MODE-SEC"><constant>DTV_ATSCMH_CODE_MODE_SEC</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-PRI"><constant>DTV_ATSCMH_RS_CODE_MODE_PRI</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-RS-CODE-MODE-SEC"><constant>DTV_ATSCMH_RS_CODE_MODE_SEC</constant></link></para></listitem>
                                <listitem><para><link linkend="DTV-ATSCMH-SCCC-BLOCK-MODE"><constant>DTV_ATSCMH_SCCC_BLOCK_MODE</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-A"><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-B"><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-C"><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></link></para></listitem>
-                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE_MODE-D"><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-A"><constant>DTV_ATSCMH_SCCC_CODE_MODE_A</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-B"><constant>DTV_ATSCMH_SCCC_CODE_MODE_B</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-C"><constant>DTV_ATSCMH_SCCC_CODE_MODE_C</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-ATSCMH-SCCC-CODE-MODE-D"><constant>DTV_ATSCMH_SCCC_CODE_MODE_D</constant></link></para></listitem>
+                       </itemizedlist>
+               </section>
+               <section id="dtmb-params">
+                       <title>DTMB delivery system</title>
+                       <para>The following parameters are valid for DTMB:</para>
+                       <itemizedlist mark='opencircle'>
+                               <listitem><para><link linkend="DTV-API-VERSION"><constant>DTV_API_VERSION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-DELIVERY-SYSTEM"><constant>DTV_DELIVERY_SYSTEM</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-TUNE"><constant>DTV_TUNE</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-CLEAR"><constant>DTV_CLEAR</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-BANDWIDTH-HZ"><constant>DTV_BANDWIDTH_HZ</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-GUARD-INTERVAL"><constant>DTV_GUARD_INTERVAL</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-TRANSMISSION-MODE"><constant>DTV_TRANSMISSION_MODE</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-INTERLEAVING"><constant>DTV_INTERLEAVING</constant></link></para></listitem>
+                               <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
                        </itemizedlist>
                </section>
        </section>
@@ -952,6 +1026,7 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
                </itemizedlist>
        </section>
        <section id="dvbc-annex-b-params">
@@ -966,6 +1041,7 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-FREQUENCY"><constant>DTV_FREQUENCY</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-INVERSION"><constant>DTV_INVERSION</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-LNA"><constant>DTV_LNA</constant></link></para></listitem>
                </itemizedlist>
        </section>
        </section>
@@ -999,6 +1075,7 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-MODULATION"><constant>DTV_MODULATION</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-PILOT"><constant>DTV_PILOT</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-ROLLOFF"><constant>DTV_ROLLOFF</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
                </itemizedlist>
        </section>
        <section id="turbo-params">
@@ -1021,7 +1098,7 @@ typedef enum fe_hierarchy {
                        <listitem><para><link linkend="DTV-SYMBOL-RATE"><constant>DTV_SYMBOL_RATE</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-INNER-FEC"><constant>DTV_INNER_FEC</constant></link></para></listitem>
                        <listitem><para><link linkend="DTV-VOLTAGE"><constant>DTV_VOLTAGE</constant></link></para></listitem>
-                       <listitem><para><link linkend="DTV-ISDBS-TS-ID"><constant>DTV_ISDBS_TS_ID</constant></link></para></listitem>
+                       <listitem><para><link linkend="DTV-STREAM-ID"><constant>DTV_STREAM_ID</constant></link></para></listitem>
                </itemizedlist>
        </section>
        </section>
index aeaed59d0f1f5d3d9baeff4af53eb803a7b50355..426c2526a4546a5fcf8ec27561d14482fa91593e 100644 (file)
@@ -66,7 +66,7 @@ supported via the new <link linkend="FE_GET_SET_PROPERTY">FE_GET_PROPERTY/FE_GET
 
 <para>The usage of this field is deprecated, as it doesn't report all supported standards, and
 will provide an incomplete information for frontends that support multiple delivery systems.
-Please use <link linkend="DTV_ENUM_DELSYS">DTV_ENUM_DELSYS</link> instead.</para>
+Please use <link linkend="DTV-ENUM-DELSYS">DTV_ENUM_DELSYS</link> instead.</para>
 </section>
 
 <section id="fe-caps-t">
@@ -101,6 +101,7 @@ a specific frontend type.</para>
        FE_CAN_8VSB                   = 0x200000,
        FE_CAN_16VSB                  = 0x400000,
        FE_HAS_EXTENDED_CAPS          = 0x800000,
+       FE_CAN_MULTISTREAM            = 0x4000000,
        FE_CAN_TURBO_FEC              = 0x8000000,
        FE_CAN_2G_MODULATION          = 0x10000000,
        FE_NEEDS_BENDING              = 0x20000000,
@@ -207,18 +208,44 @@ spec.</para>
 <para>Several functions of the frontend device use the fe_status data type defined
 by</para>
 <programlisting>
- typedef enum fe_status {
-        FE_HAS_SIGNAL     = 0x01,   /&#x22C6;  found something above the noise level &#x22C6;/
-        FE_HAS_CARRIER    = 0x02,   /&#x22C6;  found a DVB signal  &#x22C6;/
-        FE_HAS_VITERBI    = 0x04,   /&#x22C6;  FEC is stable  &#x22C6;/
-        FE_HAS_SYNC       = 0x08,   /&#x22C6;  found sync bytes  &#x22C6;/
-        FE_HAS_LOCK       = 0x10,   /&#x22C6;  everything's working... &#x22C6;/
-        FE_TIMEDOUT       = 0x20,   /&#x22C6;  no lock within the last ~2 seconds &#x22C6;/
-        FE_REINIT         = 0x40    /&#x22C6;  frontend was reinitialized,  &#x22C6;/
- } fe_status_t;                      /&#x22C6;  application is recommned to reset &#x22C6;/
+typedef enum fe_status {
+       FE_HAS_SIGNAL           = 0x01,
+       FE_HAS_CARRIER          = 0x02,
+       FE_HAS_VITERBI          = 0x04,
+       FE_HAS_SYNC             = 0x08,
+       FE_HAS_LOCK             = 0x10,
+       FE_TIMEDOUT             = 0x20,
+       FE_REINIT               = 0x40,
+} fe_status_t;
 </programlisting>
-<para>to indicate the current state and/or state changes of the frontend hardware.
-</para>
+<para>to indicate the current state and/or state changes of the frontend hardware:
+</para>
+
+<informaltable><tgroup cols="2"><tbody>
+<row>
+<entry align="char">FE_HAS_SIGNAL</entry>
+<entry align="char">The frontend has found something above the noise level</entry>
+</row><row>
+<entry align="char">FE_HAS_CARRIER</entry>
+<entry align="char">The frontend has found a DVB signal</entry>
+</row><row>
+<entry align="char">FE_HAS_VITERBI</entry>
+<entry align="char">The frontend FEC code is stable</entry>
+</row><row>
+<entry align="char">FE_HAS_SYNC</entry>
+<entry align="char">Syncronization bytes was found</entry>
+</row><row>
+<entry align="char">FE_HAS_LOCK</entry>
+<entry align="char">The DVB were locked and everything is working</entry>
+</row><row>
+<entry align="char">FE_TIMEDOUT</entry>
+<entry align="char">no lock within the last about 2 seconds</entry>
+</row><row>
+<entry align="char">FE_REINIT</entry>
+<entry align="char">The frontend was reinitialized, application is
+recommended to reset DiSEqC, tone and parameters</entry>
+</row>
+</tbody></tgroup></informaltable>
 
 </section>
 
@@ -238,7 +265,7 @@ and to add newer delivery systems.</para>
 <constant>FE_GET_PROPERTY/FE_SET_PROPERTY</constant></link> instead, in
 order to be able to support the newer System Delivery like  DVB-S2, DVB-T2,
 DVB-C2, ISDB, etc.</para>
-<para>All kinds of parameters are combined as an union in the FrontendParameters structure:</para>
+<para>All kinds of parameters are combined as an union in the FrontendParameters structure:
 <programlisting>
 struct dvb_frontend_parameters {
        uint32_t frequency;     /&#x22C6; (absolute) frequency in Hz for QAM/OFDM &#x22C6;/
@@ -251,12 +278,13 @@ struct dvb_frontend_parameters {
                struct dvb_vsb_parameters  vsb;
        } u;
 };
-</programlisting>
+</programlisting></para>
 <para>In the case of QPSK frontends the <constant>frequency</constant> field specifies the intermediate
 frequency, i.e. the offset which is effectively added to the local oscillator frequency (LOF) of
 the LNB. The intermediate frequency has to be specified in units of kHz. For QAM and
 OFDM frontends the <constant>frequency</constant> specifies the absolute frequency and is given in Hz.
 </para>
+
 <section id="dvb-qpsk-parameters">
 <title>QPSK parameters</title>
 <para>For satellite QPSK frontends you have to use the <constant>dvb_qpsk_parameters</constant> structure:</para>
@@ -321,8 +349,8 @@ itself.
 <section id="fe-code-rate-t">
 <title>frontend code rate</title>
 <para>The possible values for the <constant>fec_inner</constant> field used on
-<link refend="dvb-qpsk-parameters"><constant>struct dvb_qpsk_parameters</constant></link> and
-<link refend="dvb-qam-parameters"><constant>struct dvb_qam_parameters</constant></link> are:
+<link linkend="dvb-qpsk-parameters"><constant>struct dvb_qpsk_parameters</constant></link> and
+<link linkend="dvb-qam-parameters"><constant>struct dvb_qam_parameters</constant></link> are:
 </para>
 <programlisting>
 typedef enum fe_code_rate {
@@ -347,9 +375,9 @@ detection.
 <section id="fe-modulation-t">
 <title>frontend modulation type for QAM, OFDM and VSB</title>
 <para>For cable and terrestrial frontends, e. g. for
-<link refend="dvb-qam-parameters"><constant>struct dvb_qpsk_parameters</constant></link>,
-<link refend="dvb-ofdm-parameters"><constant>struct dvb_qam_parameters</constant></link> and
-<link refend="dvb-vsb-parameters"><constant>struct dvb_qam_parameters</constant></link>,
+<link linkend="dvb-qam-parameters"><constant>struct dvb_qpsk_parameters</constant></link>,
+<link linkend="dvb-ofdm-parameters"><constant>struct dvb_qam_parameters</constant></link> and
+<link linkend="dvb-vsb-parameters"><constant>struct dvb_qam_parameters</constant></link>,
 it needs to specify the quadrature modulation mode which can be one of the following:
 </para>
 <programlisting>
@@ -370,8 +398,8 @@ it needs to specify the quadrature modulation mode which can be one of the follo
  } fe_modulation_t;
 </programlisting>
 </section>
-<para>Finally, there are several more parameters for OFDM:
-</para>
+<section>
+<title>More OFDM parameters</title>
 <section id="fe-transmit-mode-t">
 <title>Number of carriers per channel</title>
 <programlisting>
@@ -427,6 +455,7 @@ typedef enum fe_hierarchy {
  } fe_hierarchy_t;
 </programlisting>
 </section>
+</section>
 
 </section>
 
index 170064a3dc8f4b3db90bb348331ec777074f84c2..2048b53d19b9e81b2a7e159dbde0ce63c1b51f98 100644 (file)
@@ -205,7 +205,7 @@ a partial path like:</para>
 additional include file <emphasis
 role="tt">linux/dvb/version.h</emphasis> exists, which defines the
 constant <emphasis role="tt">DVB_API_VERSION</emphasis>. This document
-describes <emphasis role="tt">DVB_API_VERSION 5.4</emphasis>.
+describes <emphasis role="tt">DVB_API_VERSION 5.8</emphasis>.
 </para>
 
 </section>
index 6c67481eaa4b8f20292d5ab9d2cdcdc4398d9f3f..6c11ec52cbeef013839fc3bf8a27c0029c56427a 100644 (file)
@@ -2,7 +2,7 @@
 <para>The kernel demux API defines a driver-internal interface for registering low-level,
 hardware specific driver to a hardware independent demux layer. It is only of interest for
 DVB device driver writers. The header file for this API is named <emphasis role="tt">demux.h</emphasis> and located in
-<emphasis role="tt">drivers/media/dvb/dvb-core</emphasis>.
+<emphasis role="tt">drivers/media/dvb-core</emphasis>.
 </para>
 <para>Maintainer note: This section must be reviewed. It is probably out of date.
 </para>
index 67d37e5ce5979c1a8ffb160bc0993b7f264fc8ec..a193e86941b55eb85ab45beb6850c90560d7c0a7 100644 (file)
@@ -26,4 +26,131 @@ struct dvb_net_if {
 <title>DVB net Function Calls</title>
 <para>To be written&#x2026;
 </para>
+
+<section id="NET_ADD_IF"
+role="subsection"><title>NET_ADD_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_ADD_IF,
+ struct dvb_net_if *if);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_ADD_IF for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dvb_net_if *if
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="NET_REMOVE_IF"
+role="subsection"><title>NET_REMOVE_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_REMOVE_IF);
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_REMOVE_IF for this command.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
+
+<section id="NET_GET_IF"
+role="subsection"><title>NET_GET_IF</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl is undocumented. Documentation is welcome.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(fd, int request = NET_GET_IF,
+ struct dvb_net_if *if);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals NET_GET_IF for this command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct dvb_net_if *if
+</para>
+</entry><entry
+ align="char">
+<para>Undocumented.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+</section>
 </section>
index 25fb823226b42231f7333212c8256fd8d44a888b..3ea1ca7e785ef2b271c848442a54177b86b0245d 100644 (file)
@@ -15,6 +15,10 @@ the audio and video device as well as the video4linux device.
 <para>The ioctls that deal with SPUs (sub picture units) and navigation packets are only
 supported on some MPEG decoders made for DVD playback.
 </para>
+<para>
+These ioctls were also used by V4L2 to control MPEG decoders implemented in V4L2. The use
+of these ioctls for that purpose has been made obsolete and proper V4L2 ioctls or controls
+have been created to replace that functionality.</para>
 <section id="video_types">
 <title>Video Data Types</title>
 
@@ -55,7 +59,7 @@ typedef enum {
 </section>
 
 <section id="video-stream-source-t">
-<title>video stream source</title>
+<title>video_stream_source_t</title>
 <para>The video stream source is set through the VIDEO_SELECT_SOURCE call and can take
 the following values, depending on whether we are replaying from an internal (demuxer) or
 external (user write) source.
@@ -76,7 +80,7 @@ call.
 </section>
 
 <section id="video-play-state-t">
-<title>video play state</title>
+<title>video_play_state_t</title>
 <para>The following values can be returned by the VIDEO_GET_STATUS call representing the
 state of video playback.
 </para>
@@ -90,9 +94,9 @@ typedef enum {
 </section>
 
 <section id="video-command">
+<title>struct video_command</title>
 <para>The structure must be zeroed before use by the application
 This ensures it can be extended safely in the future.</para>
-<title>struct video-command</title>
 <programlisting>
 struct video_command {
        __u32 cmd;
@@ -121,7 +125,7 @@ struct video_command {
 </section>
 
 <section id="video-size-t">
-<title>struct video_size-t</title>
+<title>video_size_t</title>
 <programlisting>
 typedef struct {
        int w;
@@ -217,7 +221,7 @@ bits set according to the hardwares capabilities.
 </section>
 
 <section id="video-system">
-<title>video system</title>
+<title>video_system_t</title>
 <para>A call to VIDEO_SET_SYSTEM sets the desired video system for TV output. The
 following system types can be set:
 </para>
@@ -263,7 +267,7 @@ call expects the following format for that information:
 
 </section>
 <section id="video-spu">
-<title>video SPU</title>
+<title>struct video_spu</title>
 <para>Calling VIDEO_SET_SPU deactivates or activates SPU decoding, according to the
 following format:
 </para>
@@ -277,12 +281,12 @@ following format:
 
 </section>
 <section id="video-spu-palette">
-<title>video SPU palette</title>
+<title>struct video_spu_palette</title>
 <para>The following structure is used to set the SPU palette by calling VIDEO_SPU_PALETTE:
 </para>
 <programlisting>
  typedef
- struct video_spu_palette{
+ struct video_spu_palette {
         int length;
         uint8_t &#x22C6;palette;
  } video_spu_palette_t;
@@ -290,13 +294,13 @@ following format:
 
 </section>
 <section id="video-navi-pack">
-<title>video NAVI pack</title>
+<title>struct video_navi_pack</title>
 <para>In order to get the navigational data the following structure has to be passed to the ioctl
 VIDEO_GET_NAVI:
 </para>
 <programlisting>
  typedef
- struct video_navi_pack{
+ struct video_navi_pack {
         int length;         /&#x22C6; 0 ... 1024 &#x22C6;/
         uint8_t data[1024];
  } video_navi_pack_t;
@@ -305,7 +309,7 @@ VIDEO_GET_NAVI:
 
 
 <section id="video-attributes-t">
-<title>video attributes</title>
+<title>video_attributes_t</title>
 <para>The following attributes can be set by a call to VIDEO_SET_ATTRIBUTES:
 </para>
 <programlisting>
@@ -541,6 +545,8 @@ VIDEO_GET_NAVI:
 role="subsection"><title>VIDEO_STOP</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Video Device to stop playing the current stream.
@@ -598,6 +604,8 @@ role="subsection"><title>VIDEO_STOP</title>
 role="subsection"><title>VIDEO_PLAY</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call asks the Video Device to start playing a video stream from the
@@ -634,6 +642,8 @@ role="subsection"><title>VIDEO_PLAY</title>
 role="subsection"><title>VIDEO_FREEZE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call suspends the live video stream being played. Decoding
@@ -674,6 +684,8 @@ role="subsection"><title>VIDEO_FREEZE</title>
 role="subsection"><title>VIDEO_CONTINUE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To control a V4L2 decoder use the V4L2
+&VIDIOC-DECODER-CMD; instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call restarts decoding and playing processes of the video stream
@@ -710,6 +722,9 @@ role="subsection"><title>VIDEO_CONTINUE</title>
 role="subsection"><title>VIDEO_SELECT_SOURCE</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. This ioctl was also supported by the
+V4L2 ivtv driver, but that has been replaced by the ivtv-specific
+<constant>IVTV_IOC_PASSTHROUGH_MODE</constant> ioctl.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call informs the video device which source shall be used for the input
@@ -845,10 +860,160 @@ role="subsection"><title>VIDEO_GET_STATUS</title>
  </row></tbody></tgroup></informaltable>
 &return-value-dvb;
 
+</section><section id="VIDEO_GET_FRAME_COUNT"
+role="subsection"><title>VIDEO_GET_FRAME_COUNT</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_FRAME</constant> control.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the number of displayed frames
+since the decoder was started.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_FRAME_COUNT, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_FRAME_COUNT for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the number of frames displayed since the decoder was started.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_PTS"
+role="subsection"><title>VIDEO_GET_PTS</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the <constant>V4L2_CID_MPEG_VIDEO_DEC_PTS</constant> control.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the current PTS timestamp.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_PTS, __u64 *pts);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_PTS for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>__u64 *pts
+</para>
+</entry><entry
+ align="char">
+<para>Returns the 33-bit timestamp as defined in ITU T-REC-H.222.0 / ISO/IEC 13818-1.
+</para>
+<para>
+The PTS should belong to the currently played
+frame if possible, but may also be a value close to it
+like the PTS of the last decoded frame or the last PTS
+extracted by the PES parser.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_FRAME_RATE"
+role="subsection"><title>VIDEO_GET_FRAME_RATE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl call asks the Video Device to return the current framerate.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_FRAME_RATE, unsigned int *rate);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_FRAME_RATE for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>unsigned int *rate
+</para>
+</entry><entry
+ align="char">
+<para>Returns the framerate in number of frames per 1000 seconds.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="VIDEO_GET_EVENT"
 role="subsection"><title>VIDEO_GET_EVENT</title>
 <para>DESCRIPTION
 </para>
+<para>This ioctl is for DVB devices only. To get events from a V4L2 decoder use the V4L2
+&VIDIOC-DQEVENT; ioctl instead.</para>
 <informaltable><tgroup cols="1"><tbody><row><entry
  align="char">
 <para>This ioctl call returns an event of type video_event if available. If an event is
@@ -914,6 +1079,152 @@ role="subsection"><title>VIDEO_GET_EVENT</title>
 </entry>
  </row></tbody></tgroup></informaltable>
 
+</section><section id="VIDEO_COMMAND"
+role="subsection"><title>VIDEO_COMMAND</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the &VIDIOC-DECODER-CMD; ioctl.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl commands the decoder. The <constant>video_command</constant> struct
+is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
+&VIDIOC-DECODER-CMD; documentation for more information.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_COMMAND, struct video_command *cmd);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_COMMAND for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct video_command *cmd
+</para>
+</entry><entry
+ align="char">
+<para>Commands the decoder.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_TRY_COMMAND"
+role="subsection"><title>VIDEO_TRY_COMMAND</title>
+<para>DESCRIPTION
+</para>
+<para>This ioctl is obsolete. Do not use in new drivers. For V4L2 decoders this
+ioctl has been replaced by the &VIDIOC-TRY-DECODER-CMD; ioctl.</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl tries a decoder command. The <constant>video_command</constant> struct
+is a subset of the <constant>v4l2_decoder_cmd</constant> struct, so refer to the
+&VIDIOC-TRY-DECODER-CMD; documentation for more information.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_TRY_COMMAND, struct video_command *cmd);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_TRY_COMMAND for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>struct video_command *cmd
+</para>
+</entry><entry
+ align="char">
+<para>Try a decoder command.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
+</section><section id="VIDEO_GET_SIZE"
+role="subsection"><title>VIDEO_GET_SIZE</title>
+<para>DESCRIPTION
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>This ioctl returns the size and aspect ratio.</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>SYNOPSIS
+</para>
+<informaltable><tgroup cols="1"><tbody><row><entry
+ align="char">
+<para>int ioctl(int fd, int request =
+ VIDEO_GET_SIZE, video_size_t *size);</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+<para>PARAMETERS
+</para>
+<informaltable><tgroup cols="2"><tbody><row><entry
+ align="char">
+<para>int fd</para>
+</entry><entry
+ align="char">
+<para>File descriptor returned by a previous call to open().</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>int request</para>
+</entry><entry
+ align="char">
+<para>Equals VIDEO_GET_SIZE for this
+ command.</para>
+</entry>
+ </row><row><entry
+ align="char">
+<para>video_size_t *size
+</para>
+</entry><entry
+ align="char">
+<para>Returns the size and aspect ratio.
+</para>
+</entry>
+ </row></tbody></tgroup></informaltable>
+&return-value-dvb;
+
 </section><section id="VIDEO_SET_DISPLAY_FORMAT"
 role="subsection"><title>VIDEO_SET_DISPLAY_FORMAT</title>
 <para>DESCRIPTION
index 1078e45f189f0630c6c6ea50f74b3764dc1cea43..d2eb79e41a011a6e904ba5f81da083cec8e3b520 100644 (file)
@@ -178,23 +178,23 @@ Signal - NTSC for Studio Applications"</title>
 1125-Line High-Definition Production"</title>
     </biblioentry>
 
-    <biblioentry id="en50067">
-      <abbrev>EN&nbsp;50067</abbrev>
+    <biblioentry id="iec62106">
+      <abbrev>IEC&nbsp;62106</abbrev>
       <authorgroup>
-       <corpauthor>European Committee for Electrotechnical Standardization
-(<ulink url="http://www.cenelec.eu">http://www.cenelec.eu</ulink>)</corpauthor>
+       <corpauthor>International Electrotechnical Commission
+(<ulink url="http://www.iec.ch">http://www.iec.ch</ulink>)</corpauthor>
       </authorgroup>
       <title>Specification of the radio data system (RDS) for VHF/FM sound broadcasting
 in the frequency range from 87,5 to 108,0 MHz</title>
     </biblioentry>
 
     <biblioentry id="nrsc4">
-      <abbrev>NRSC-4</abbrev>
+      <abbrev>NRSC-4-B</abbrev>
       <authorgroup>
        <corpauthor>National Radio Systems Committee
 (<ulink url="http://www.nrscstandards.org">http://www.nrscstandards.org</ulink>)</corpauthor>
       </authorgroup>
-      <title>NRSC-4: United States RBDS Standard</title>
+      <title>NRSC-4-B: United States RBDS Standard</title>
     </biblioentry>
 
     <biblioentry id="iso12232">
@@ -226,4 +226,44 @@ in the frequency range from 87,5 to 108,0 MHz</title>
       <title>VESA and Industry Standards and Guidelines for Computer Display Monitor Timing (DMT)</title>
     </biblioentry>
 
+    <biblioentry id="vesaedid">
+      <abbrev>EDID</abbrev>
+      <authorgroup>
+       <corpauthor>Video Electronics Standards Association
+(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>VESA Enhanced Extended Display Identification Data Standard</title>
+      <subtitle>Release A, Revision 2</subtitle>
+    </biblioentry>
+
+    <biblioentry id="hdcp">
+      <abbrev>HDCP</abbrev>
+      <authorgroup>
+       <corpauthor>Digital Content Protection LLC
+(<ulink url="http://www.digital-cp.com">http://www.digital-cp.com</ulink>)</corpauthor>
+      </authorgroup>
+      <title>High-bandwidth Digital Content Protection System</title>
+      <subtitle>Revision 1.3</subtitle>
+    </biblioentry>
+
+    <biblioentry id="hdmi">
+      <abbrev>HDMI</abbrev>
+      <authorgroup>
+       <corpauthor>HDMI Licensing LLC
+(<ulink url="http://www.hdmi.org">http://www.hdmi.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>High-Definition Multimedia Interface</title>
+      <subtitle>Specification Version 1.4a</subtitle>
+    </biblioentry>
+
+    <biblioentry id="dp">
+      <abbrev>DP</abbrev>
+      <authorgroup>
+       <corpauthor>Video Electronics Standards Association
+(<ulink url="http://www.vesa.org">http://www.vesa.org</ulink>)</corpauthor>
+      </authorgroup>
+      <title>VESA DisplayPort Standard</title>
+      <subtitle>Version 1, Revision 2</subtitle>
+    </biblioentry>
+
   </bibliography>
index b91d25313b631eb25fec06bf42877131af31c61e..73c6847436c99f7c7ca5fccc3f6b1c2780881afd 100644 (file)
@@ -564,7 +564,7 @@ automatically.</para>
     <para>To query and select the standard used by the current video
 input or output applications call the &VIDIOC-G-STD; and
 &VIDIOC-S-STD; ioctl, respectively. The <emphasis>received</emphasis>
-standard can be sensed with the &VIDIOC-QUERYSTD; ioctl. Note parameter of all these ioctls is a pointer to a &v4l2-std-id; type (a standard set), <emphasis>not</emphasis> an index into the standard enumeration.<footnote>
+standard can be sensed with the &VIDIOC-QUERYSTD; ioctl. Note that the parameter of all these ioctls is a pointer to a &v4l2-std-id; type (a standard set), <emphasis>not</emphasis> an index into the standard enumeration.<footnote>
        <para>An alternative to the current scheme is to use pointers
 to indices as arguments of <constant>VIDIOC_G_STD</constant> and
 <constant>VIDIOC_S_STD</constant>, the &v4l2-input; and
@@ -588,30 +588,28 @@ switch to a standard by &v4l2-std-id;.</para>
       </footnote> Drivers must implement all video standard ioctls
 when the device has one or more video inputs or outputs.</para>
 
-    <para>Special rules apply to USB cameras where the notion of video
-standards makes little sense. More generally any capture device,
-output devices accordingly, which is <itemizedlist>
+    <para>Special rules apply to devices such as USB cameras where the notion of video
+standards makes little sense. More generally for any capture or output device
+which is: <itemizedlist>
        <listitem>
          <para>incapable of capturing fields or frames at the nominal
 rate of the video standard, or</para>
        </listitem>
        <listitem>
-         <para>where <link linkend="buffer">timestamps</link> refer
-to the instant the field or frame was received by the driver, not the
-capture time, or</para>
-       </listitem>
-       <listitem>
-         <para>where <link linkend="buffer">sequence numbers</link>
-refer to the frames received by the driver, not the captured
-frames.</para>
+         <para>that does not support the video standard formats at all.</para>
        </listitem>
       </itemizedlist> Here the driver shall set the
 <structfield>std</structfield> field of &v4l2-input; and &v4l2-output;
-to zero, the <constant>VIDIOC_G_STD</constant>,
+to zero and the <constant>VIDIOC_G_STD</constant>,
 <constant>VIDIOC_S_STD</constant>,
 <constant>VIDIOC_QUERYSTD</constant> and
 <constant>VIDIOC_ENUMSTD</constant> ioctls shall return the
-&EINVAL;.<footnote>
+&ENOTTY;.<footnote>
+       <para>See <xref linkend="buffer" /> for a rationale.</para>
+       <para>Applications can make use of the <xref linkend="input-capabilities" /> and
+<xref linkend="output-capabilities"/> flags to determine whether the video standard ioctls
+are available for the device.</para>
+&ENOTTY;.
        <para>See <xref linkend="buffer" /> for a rationale. Probably
 even USB cameras follow some well known video standard. It might have
 been better to explicitly indicate elsewhere if a device cannot live
@@ -626,9 +624,9 @@ up to normal expectations, instead of this exception.</para>
 &v4l2-standard; standard;
 
 if (-1 == ioctl (fd, &VIDIOC-G-STD;, &amp;std_id)) {
-       /* Note when VIDIOC_ENUMSTD always returns EINVAL this
+       /* Note when VIDIOC_ENUMSTD always returns ENOTTY this
           is no video device or it falls under the USB exception,
-          and VIDIOC_G_STD returning EINVAL is no error. */
+          and VIDIOC_G_STD returning ENOTTY is no error. */
 
        perror ("VIDIOC_G_STD");
        exit (EXIT_FAILURE);
index faa0fd14666a54bc2688ca176c9dee531cc5eccf..4fdf6b562d1cedb819c258f99820edfa4fafc7b3 100644 (file)
@@ -1476,7 +1476,7 @@ follows.<informaltable>
                  </row>
                  <row>
                    <entry><constant>V4L2_BUF_TYPE_PRIVATE_BASE</constant></entry>
-                   <entry><constant>V4L2_BUF_TYPE_PRIVATE</constant></entry>
+                   <entry><constant>V4L2_BUF_TYPE_PRIVATE</constant> (but this is deprecated)</entry>
                  </row>
                </tbody>
              </tgroup>
@@ -2468,21 +2468,9 @@ that used it. It was originally scheduled for removal in 2.6.35.
          <structfield>reserved2</structfield> and removed
          <constant>V4L2_BUF_FLAG_INPUT</constant>.</para>
        </listitem>
-      </orderedlist>
-    </section>
-
-    <section>
-      <title>V4L2 in Linux 3.6</title>
-      <orderedlist>
         <listitem>
          <para>Added V4L2_CAP_VIDEO_M2M and V4L2_CAP_VIDEO_M2M_MPLANE capabilities.</para>
         </listitem>
-      </orderedlist>
-    </section>
-
-    <section>
-      <title>V4L2 in Linux 3.6</title>
-      <orderedlist>
         <listitem>
          <para>Added support for frequency band enumerations: &VIDIOC-ENUM-FREQ-BANDS;.</para>
         </listitem>
@@ -2567,29 +2555,6 @@ and may change in the future.</para>
          <para>Video Output Overlay (OSD) Interface, <xref
            linkend="osd" />.</para>
         </listitem>
-       <listitem>
-         <para><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant>,
-       &v4l2-buf-type;, <xref linkend="v4l2-buf-type" />.</para>
-        </listitem>
-        <listitem>
-         <para><constant>V4L2_CAP_VIDEO_OUTPUT_OVERLAY</constant>,
-&VIDIOC-QUERYCAP; ioctl, <xref linkend="device-capabilities" />.</para>
-        </listitem>
-        <listitem>
-         <para>&VIDIOC-ENUM-FRAMESIZES; and
-&VIDIOC-ENUM-FRAMEINTERVALS; ioctls.</para>
-        </listitem>
-        <listitem>
-         <para>&VIDIOC-G-ENC-INDEX; ioctl.</para>
-        </listitem>
-        <listitem>
-         <para>&VIDIOC-ENCODER-CMD; and &VIDIOC-TRY-ENCODER-CMD;
-ioctls.</para>
-        </listitem>
-        <listitem>
-         <para>&VIDIOC-DECODER-CMD; and &VIDIOC-TRY-DECODER-CMD;
-ioctls.</para>
-        </listitem>
         <listitem>
          <para>&VIDIOC-DBG-G-REGISTER; and &VIDIOC-DBG-S-REGISTER;
 ioctls.</para>
@@ -2615,11 +2580,11 @@ ioctls.</para>
          and &VIDIOC-SUBDEV-S-SELECTION; ioctls.</para>
         </listitem>
         <listitem>
-         <para><link linkend="v4l2-auto-focus-area"><constant>
-         V4L2_CID_AUTO_FOCUS_AREA</constant></link> control.</para>
+         <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
         </listitem>
         <listitem>
-         <para>Support for frequency band enumeration: &VIDIOC-ENUM-FREQ-BANDS; ioctl.</para>
+         <para>Vendor and device specific media bus pixel formats.
+           <xref linkend="v4l2-mbus-vendor-spec-fmts" />.</para>
         </listitem>
       </itemizedlist>
     </section>
index b0964fb4e8348853619efd3296b7821d4e6b6803..a84a08ca51dcd155dde371ae818f2e75a4bcd0e8 100644 (file)
@@ -3505,7 +3505,7 @@ This encodes up to 31 pre-defined programme types.</entry>
          </row>
          <row><entry spanname="descr">Sets the Programme Service name (PS_NAME) for transmission.
 It is intended for static display on a receiver. It is the primary aid to listeners in programme service
-identification and selection.  In Annex E of <xref linkend="en50067" />, the RDS specification,
+identification and selection.  In Annex E of <xref linkend="iec62106" />, the RDS specification,
 there is a full description of the correct character encoding for Programme Service name strings.
 Also from RDS specification, PS is usually a single eight character text. However, it is also possible
 to find receivers which can scroll strings sized as 8 x N characters. So, this control must be configured
@@ -3519,7 +3519,7 @@ with steps of 8 characters. The result is it must always contain a string with s
 what is being broadcasted. RDS Radio Text can be applied when broadcaster wishes to transmit longer PS names,
 programme-related information or any other text. In these cases, RadioText should be used in addition to
 <constant>V4L2_CID_RDS_TX_PS_NAME</constant>. The encoding for Radio Text strings is also fully described
-in Annex E of <xref linkend="en50067" />. The length of Radio Text strings depends on which RDS Block is being
+in Annex E of <xref linkend="iec62106" />. The length of Radio Text strings depends on which RDS Block is being
 used to transmit it, either 32 (2A block) or 64 (2B block).  However, it is also possible
 to find receivers which can scroll strings sized as 32 x N or 64 x N characters. So, this control must be configured
 with steps of 32 or 64 characters. The result is it must always contain a string with size multiple of 32 or 64. </entry>
@@ -3650,7 +3650,7 @@ manually or automatically if set to zero. Unit, range and step are driver-specif
       </table>
 
 <para>For more details about RDS specification, refer to
-<xref linkend="en50067" /> document, from CENELEC.</para>
+<xref linkend="iec62106" /> document, from CENELEC.</para>
     </section>
 
     <section id="flash-controls">
@@ -3717,232 +3717,231 @@ interface and may change in the future.</para>
            use case involving camera or individually.
          </para>
 
-       </section>
 
+          <table pgwide="1" frame="none" id="flash-control-id">
+          <title>Flash 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_FLASH_CLASS</constant></entry>
+           <entry>class</entry>
+         </row>
+         <row>
+           <entry spanname="descr">The FLASH class descriptor.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-flash-led-mode">
+           <entry spanname="descr">Defines the mode of the flash LED,
+           the high-power white LED attached to the flash controller.
+           Setting this control may not be possible in presence of
+           some faults. See V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
+                 <entry>Off.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
+                 <entry>Flash mode.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
+                 <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-flash-strobe-source"><entry
+         spanname="descr">Defines the source of the flash LED
+         strobe.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
+                 <entry>The flash strobe is triggered by using
+                 the V4L2_CID_FLASH_STROBE control.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
+                 <entry>The flash strobe is triggered by an
+                 external source. Typically this is a sensor,
+                 which makes it possible to synchronises the
+                 flash strobe start to exposure start.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
+           <entry>button</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Strobe flash. Valid when
+           V4L2_CID_FLASH_LED_MODE is set to
+           V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
+           is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
+           control may not be possible in presence of some faults.
+           See V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
+           <entry>button</entry>
+         </row>
+         <row><entry spanname="descr">Stop flash strobe immediately.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Strobe status: whether the flash
+           is strobing at the moment or not. This is a read-only
+           control.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Hardware timeout for flash. The
+           flash strobe is stopped after this period of time has
+           passed from the start of the strobe.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the flash strobe when
+           the flash LED is in flash mode
+           (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
+           (mA) if possible.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the flash LED in
+           torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
+           milliamps (mA) if possible. Setting this control may not
+           be possible in presence of some faults. See
+           V4L2_CID_FLASH_FAULT.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
+           <entry>integer</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Intensity of the indicator LED.
+           The indicator LED may be fully independent of the flash
+           LED. The unit should be microamps (uA) if possible.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Faults related to the flash. The
+           faults tell about specific problems in the flash chip
+           itself or the LEDs attached to it. Faults may prevent
+           further use of some of the flash controls. In particular,
+           V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
+           if the fault affects the flash LED. Exactly which faults
+           have such an effect is chip dependent. Reading the faults
+           resets the control and returns the chip to a usable state
+           if possible.</entry>
+         </row>
+         <row>
+           <entrytbl spanname="descr" cols="2">
+             <tbody valign="top">
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
+                 <entry>Flash controller voltage to the flash LED
+                 has exceeded the limit specific to the flash
+                 controller.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
+                 <entry>The flash strobe was still on when
+                 the timeout set by the user ---
+                 V4L2_CID_FLASH_TIMEOUT control --- has expired.
+                 Not all flash controllers may set this in all
+                 such conditions.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
+                 <entry>The flash controller has overheated.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
+                 <entry>The short circuit protection of the flash
+                 controller has been triggered.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
+                 <entry>Current in the LED power supply has exceeded the limit
+                 specific to the flash controller.</entry>
+               </row>
+               <row>
+                 <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
+                 <entry>The flash controller has detected a short or open
+                 circuit condition on the indicator LED.</entry>
+               </row>
+             </tbody>
+           </entrytbl>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row><entry spanname="descr">Enable or disable charging of the xenon
+         flash capacitor.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
+           <entry>boolean</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Is the flash ready to strobe?
+           Xenon flashes require their capacitors charged before
+           strobing. LED flashes often require a cooldown period
+           after strobe during which another strobe will not be
+           possible. This is a read-only control.</entry>
+         </row>
+         <row><entry></entry></row>
+       </tbody>
+          </tgroup>
+          </table>
+       </section>
       </section>
-
-      <table pgwide="1" frame="none" id="flash-control-id">
-      <title>Flash 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_FLASH_CLASS</constant></entry>
-           <entry>class</entry>
-         </row>
-         <row>
-           <entry spanname="descr">The FLASH class descriptor.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_LED_MODE</constant></entry>
-           <entry>menu</entry>
-         </row>
-         <row id="v4l2-flash-led-mode">
-           <entry spanname="descr">Defines the mode of the flash LED,
-           the high-power white LED attached to the flash controller.
-           Setting this control may not be possible in presence of
-           some faults. See V4L2_CID_FLASH_FAULT.</entry>
-         </row>
-         <row>
-           <entrytbl spanname="descr" cols="2">
-             <tbody valign="top">
-               <row>
-                 <entry><constant>V4L2_FLASH_LED_MODE_NONE</constant></entry>
-                 <entry>Off.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_LED_MODE_FLASH</constant></entry>
-                 <entry>Flash mode.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_LED_MODE_TORCH</constant></entry>
-                 <entry>Torch mode. See V4L2_CID_FLASH_TORCH_INTENSITY.</entry>
-               </row>
-             </tbody>
-           </entrytbl>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_SOURCE</constant></entry>
-           <entry>menu</entry>
-         </row>
-         <row id="v4l2-flash-strobe-source"><entry
-         spanname="descr">Defines the source of the flash LED
-         strobe.</entry>
-         </row>
-         <row>
-           <entrytbl spanname="descr" cols="2">
-             <tbody valign="top">
-               <row>
-                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_SOFTWARE</constant></entry>
-                 <entry>The flash strobe is triggered by using
-                 the V4L2_CID_FLASH_STROBE control.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_STROBE_SOURCE_EXTERNAL</constant></entry>
-                 <entry>The flash strobe is triggered by an
-                 external source. Typically this is a sensor,
-                 which makes it possible to synchronises the
-                 flash strobe start to exposure start.</entry>
-               </row>
-             </tbody>
-           </entrytbl>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE</constant></entry>
-           <entry>button</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Strobe flash. Valid when
-           V4L2_CID_FLASH_LED_MODE is set to
-           V4L2_FLASH_LED_MODE_FLASH and V4L2_CID_FLASH_STROBE_SOURCE
-           is set to V4L2_FLASH_STROBE_SOURCE_SOFTWARE. Setting this
-           control may not be possible in presence of some faults.
-           See V4L2_CID_FLASH_FAULT.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STOP</constant></entry>
-           <entry>button</entry>
-         </row>
-         <row><entry spanname="descr">Stop flash strobe immediately.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_STROBE_STATUS</constant></entry>
-           <entry>boolean</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Strobe status: whether the flash
-           is strobing at the moment or not. This is a read-only
-           control.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_TIMEOUT</constant></entry>
-           <entry>integer</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Hardware timeout for flash. The
-           flash strobe is stopped after this period of time has
-           passed from the start of the strobe.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_INTENSITY</constant></entry>
-           <entry>integer</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Intensity of the flash strobe when
-           the flash LED is in flash mode
-           (V4L2_FLASH_LED_MODE_FLASH). The unit should be milliamps
-           (mA) if possible.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_TORCH_INTENSITY</constant></entry>
-           <entry>integer</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Intensity of the flash LED in
-           torch mode (V4L2_FLASH_LED_MODE_TORCH). The unit should be
-           milliamps (mA) if possible. Setting this control may not
-           be possible in presence of some faults. See
-           V4L2_CID_FLASH_FAULT.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_INDICATOR_INTENSITY</constant></entry>
-           <entry>integer</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Intensity of the indicator LED.
-           The indicator LED may be fully independent of the flash
-           LED. The unit should be microamps (uA) if possible.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_FAULT</constant></entry>
-           <entry>bitmask</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Faults related to the flash. The
-           faults tell about specific problems in the flash chip
-           itself or the LEDs attached to it. Faults may prevent
-           further use of some of the flash controls. In particular,
-           V4L2_CID_FLASH_LED_MODE is set to V4L2_FLASH_LED_MODE_NONE
-           if the fault affects the flash LED. Exactly which faults
-           have such an effect is chip dependent. Reading the faults
-           resets the control and returns the chip to a usable state
-           if possible.</entry>
-         </row>
-         <row>
-           <entrytbl spanname="descr" cols="2">
-             <tbody valign="top">
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_OVER_VOLTAGE</constant></entry>
-                 <entry>Flash controller voltage to the flash LED
-                 has exceeded the limit specific to the flash
-                 controller.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_TIMEOUT</constant></entry>
-                 <entry>The flash strobe was still on when
-                 the timeout set by the user ---
-                 V4L2_CID_FLASH_TIMEOUT control --- has expired.
-                 Not all flash controllers may set this in all
-                 such conditions.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_OVER_TEMPERATURE</constant></entry>
-                 <entry>The flash controller has overheated.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_SHORT_CIRCUIT</constant></entry>
-                 <entry>The short circuit protection of the flash
-                 controller has been triggered.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_OVER_CURRENT</constant></entry>
-                 <entry>Current in the LED power supply has exceeded the limit
-                 specific to the flash controller.</entry>
-               </row>
-               <row>
-                 <entry><constant>V4L2_FLASH_FAULT_INDICATOR</constant></entry>
-                 <entry>The flash controller has detected a short or open
-                 circuit condition on the indicator LED.</entry>
-               </row>
-             </tbody>
-           </entrytbl>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_CHARGE</constant></entry>
-           <entry>boolean</entry>
-         </row>
-         <row><entry spanname="descr">Enable or disable charging of the xenon
-         flash capacitor.</entry>
-         </row>
-         <row>
-           <entry spanname="id"><constant>V4L2_CID_FLASH_READY</constant></entry>
-           <entry>boolean</entry>
-         </row>
-         <row>
-           <entry spanname="descr">Is the flash ready to strobe?
-           Xenon flashes require their capacitors charged before
-           strobing. LED flashes often require a cooldown period
-           after strobe during which another strobe will not be
-           possible. This is a read-only control.</entry>
-         </row>
-         <row><entry></entry></row>
-       </tbody>
-      </tgroup>
-      </table>
     </section>
 
     <section id="jpeg-controls">
@@ -4268,6 +4267,177 @@ interface and may change in the future.</para>
            pixels / second.
            </entry>
          </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_TEST_PATTERN</constant></entry>
+           <entry>menu</entry>
+         </row>
+         <row id="v4l2-test-pattern">
+           <entry spanname="descr"> Some capture/display/sensor devices have
+           the capability to generate test pattern images. These hardware
+           specific test patterns can be used to test if a device is working
+           properly.</entry>
+         </row>
+         <row><entry></entry></row>
+       </tbody>
+      </tgroup>
+      </table>
+
+    </section>
+
+    <section id="dv-controls">
+      <title>Digital Video Control Reference</title>
+
+      <note>
+       <title>Experimental</title>
+
+       <para>This is an <link
+       linkend="experimental">experimental</link> interface and may
+       change in the future.</para>
+      </note>
+
+      <para>
+       The Digital Video control class is intended to control receivers
+       and transmitters for <ulink url="http://en.wikipedia.org/wiki/Vga">VGA</ulink>,
+       <ulink url="http://en.wikipedia.org/wiki/Digital_Visual_Interface">DVI</ulink>
+       (Digital Visual Interface), HDMI (<xref linkend="hdmi" />) and DisplayPort (<xref linkend="dp" />).
+       These controls are generally expected to be private to the receiver or transmitter
+       subdevice that implements them, so they are only exposed on the
+       <filename>/dev/v4l-subdev*</filename> device node.
+      </para>
+
+      <para>Note that these devices can have multiple input or output pads which are
+      hooked up to e.g. HDMI connectors. Even though the subdevice will receive or
+      transmit video from/to only one of those pads, the other pads can still be
+      active when it comes to EDID (Extended Display Identification Data,
+      <xref linkend="vesaedid" />) and HDCP (High-bandwidth Digital Content
+      Protection System, <xref linkend="hdcp" />) processing, allowing the device
+      to do the fairly slow EDID/HDCP handling in advance. This allows for quick
+      switching between connectors.</para>
+
+      <para>These pads appear in several of the controls in this section as
+      bitmasks, one bit for each pad. Bit 0 corresponds to pad 0, bit 1 to pad 1,
+      etc. The maximum value of the control is the set of valid pads.</para>
+
+      <table pgwide="1" frame="none" id="dv-control-id">
+      <title>Digital Video 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_DV_CLASS</constant></entry>
+           <entry>class</entry>
+         </row>
+         <row>
+           <entry spanname="descr">The Digital Video class descriptor.</entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_TX_HOTPLUG</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Many connectors have a hotplug pin which is high
+           if EDID information is available from the source. This control shows the
+           state of the hotplug pin as seen by the transmitter.
+           Each bit corresponds to an output pad on the transmitter. If an output pad
+           does not have an associated hotplug pin, then the bit for that pad will be 0.
+           This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_TX_RXSENSE</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Rx Sense is the detection of pull-ups on the TMDS
+            clock lines. This normally means that the sink has left/entered standby (i.e.
+           the transmitter can sense that the receiver is ready to receive video).
+           Each bit corresponds to an output pad on the transmitter. If an output pad
+           does not have an associated Rx Sense, then the bit for that pad will be 0.
+           This read-only control is applicable to DVI-D and HDMI devices.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_TX_EDID_PRESENT</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">When the transmitter sees the hotplug signal from the
+           receiver it will attempt to read the EDID. If set, then the transmitter has read
+           at least the first block (= 128 bytes).
+           Each bit corresponds to an output pad on the transmitter. If an output pad
+           does not support EDIDs, then the bit for that pad will be 0.
+           This read-only control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_TX_MODE</constant></entry>
+           <entry id="v4l2-dv-tx-mode">enum v4l2_dv_tx_mode</entry>
+         </row>
+         <row>
+           <entry spanname="descr">HDMI transmitters can transmit in DVI-D mode (just video)
+           or in HDMI mode (video + audio + auxiliary data). This control selects which mode
+           to use: V4L2_DV_TX_MODE_DVI_D or V4L2_DV_TX_MODE_HDMI.
+           This control is applicable to HDMI connectors.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_TX_RGB_RANGE</constant></entry>
+           <entry id="v4l2-dv-rgb-range">enum v4l2_dv_rgb_range</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Select the quantization range for RGB output. V4L2_DV_RANGE_AUTO
+           follows the RGB quantization range specified in the standard for the video interface
+           (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
+           to be compatible with sinks that have not implemented the standard correctly
+           (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
+           used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
+           where N is the number of bits per component.
+           This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_RX_POWER_PRESENT</constant></entry>
+           <entry>bitmask</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Detects whether the receiver receives power from the source
+           (e.g. HDMI carries 5V on one of the pins). This is often used to power an eeprom
+           which contains EDID information, such that the source can read the EDID even if
+           the sink is in standby/power off.
+           Each bit corresponds to an input pad on the transmitter. If an input pad
+           cannot detect whether power is present, then the bit for that pad will be 0.
+           This read-only control is applicable to DVI-D, HDMI and DisplayPort connectors.
+           </entry>
+         </row>
+         <row>
+           <entry spanname="id"><constant>V4L2_CID_DV_RX_RGB_RANGE</constant></entry>
+           <entry>enum v4l2_dv_rgb_range</entry>
+         </row>
+         <row>
+           <entry spanname="descr">Select the quantization range for RGB input. V4L2_DV_RANGE_AUTO
+           follows the RGB quantization range specified in the standard for the video interface
+           (ie. <xref linkend="cea861" /> for HDMI). V4L2_DV_RANGE_LIMITED and V4L2_DV_RANGE_FULL override the standard
+           to be compatible with sources that have not implemented the standard correctly
+           (unfortunately quite common for HDMI and DVI-D). Full range allows all possible values to be
+           used whereas limited range sets the range to (16 &lt;&lt; (N-8)) - (235 &lt;&lt; (N-8))
+           where N is the number of bits per component.
+           This control is applicable to VGA, DVI-A/D, HDMI and DisplayPort connectors.
+           </entry>
+         </row>
          <row><entry></entry></row>
        </tbody>
       </tgroup>
index 479d9433869aff1e18fdc12d3c2aa1d0bbee772b..dd91d6134e8c950a0add05ab4e6cd45f2c04b1f7 100644 (file)
@@ -1,13 +1,6 @@
   <title>Video Output Overlay Interface</title>
   <subtitle>Also known as On-Screen Display (OSD)</subtitle>
 
-  <note>
-    <title>Experimental</title>
-
-    <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-  </note>
-
   <para>Some video output devices can overlay a framebuffer image onto
 the outgoing video signal. Applications can set up such an overlay
 using this interface, which borrows structures and ioctls of the <link
index 38883a419e65674092aa4265ac4f637ff80211a4..be2f337373232e934d2ab93911ba06443792c0c4 100644 (file)
@@ -6,7 +6,7 @@ information, on an inaudible audio subcarrier of a radio program. This
 interface is aimed at devices capable of receiving and/or transmitting RDS
 information.</para>
 
-      <para>For more information see the core RDS standard <xref linkend="en50067" />
+      <para>For more information see the core RDS standard <xref linkend="iec62106" />
 and the RBDS standard <xref linkend="nrsc4" />.</para>
 
       <para>Note that the RBDS standard as is used in the USA is almost identical
index a3d9dd093268747de3751dcc41001e1fba638b11..d15aaf83f56f433a6fa09711a5b0ba5625ed30a0 100644 (file)
       rectangle --- if it is supported by the hardware.</para>
 
       <orderedlist>
-       <listitem>Sink pad format. The user configures the sink pad
+       <listitem><para>Sink pad format. The user configures the sink pad
        format. This format defines the parameters of the image the
-       entity receives through the pad for further processing.</listitem>
+       entity receives through the pad for further processing.</para></listitem>
 
-       <listitem>Sink pad actual crop selection. The sink pad crop
-       defines the crop performed to the sink pad format.</listitem>
+       <listitem><para>Sink pad actual crop selection. The sink pad crop
+       defines the crop performed to the sink pad format.</para></listitem>
 
-       <listitem>Sink pad actual compose selection. The size of the
+       <listitem><para>Sink pad actual compose selection. The size of the
        sink pad compose rectangle defines the scaling ratio compared
        to the size of the sink pad crop rectangle. The location of
        the compose rectangle specifies the location of the actual
        sink compose rectangle in the sink compose bounds
-       rectangle.</listitem>
+       rectangle.</para></listitem>
 
-       <listitem>Source pad actual crop selection. Crop on the source
+       <listitem><para>Source pad actual crop selection. Crop on the source
        pad defines crop performed to the image in the sink compose
-       bounds rectangle.</listitem>
+       bounds rectangle.</para></listitem>
 
-       <listitem>Source pad format. The source pad format defines the
+       <listitem><para>Source pad format. The source pad format defines the
        output pixel format of the subdev, as well as the other
        parameters with the exception of the image width and height.
        Width and height are defined by the size of the source pad
-       actual crop selection.</listitem>
+       actual crop selection.</para></listitem>
       </orderedlist>
 
       <para>Accessing any of the above rectangles not supported by the
index 5bbf3ce1973a8df5d72619ce3df4cc62de52b036..7e29a4e1f696ec0c898fa431c4ea9163b5a12de9 100644 (file)
@@ -6,6 +6,15 @@
     &cs-str;
     <tbody valign="top">
        <!-- Keep it ordered alphabetically -->
+      <row>
+       <entry>EAGAIN (aka EWOULDBLOCK)</entry>
+       <entry>The ioctl can't be handled because the device is in state where
+              it can't perform it. This could happen for example in case where
+              device is sleeping and ioctl is performed to query statistics.
+              It is also returned when the ioctl would need to wait
+              for an event, but the device was opened in non-blocking mode.
+       </entry>
+      </row>
       <row>
        <entry>EBADF</entry>
        <entry>The file descriptor is not a valid.</entry>
               that this request would overcommit the usb bandwidth reserved
               for periodic transfers (up to 80% of the USB bandwidth).</entry>
       </row>
-      <row>
-       <entry>ENOSYS or EOPNOTSUPP</entry>
-       <entry>Function not available for this device (dvb API only. Will likely
-              be replaced anytime soon by ENOTTY).</entry>
-      </row>
       <row>
        <entry>EPERM</entry>
        <entry>Permission denied. Can be returned if the device needs write
                permission, or some special capabilities is needed
                (e. g. root)</entry>
       </row>
-      <row>
-       <entry>EWOULDBLOCK</entry>
-       <entry>Operation would block. Used when the ioctl would need to wait
-              for an event, but the device was opened in non-blocking mode.</entry>
-      </row>
     </tbody>
   </tgroup>
 </table>
index 1885cc0755cb48a438aadfe686857f46ee541172..b5d1cbdc558bdfa5cfbd6e451425dabc5456b0ce 100644 (file)
@@ -613,8 +613,8 @@ field is independent of the <structfield>timestamp</structfield> and
            <entry>__u32</entry>
            <entry><structfield>sequence</structfield></entry>
            <entry></entry>
-           <entry>Set by the driver, counting the frames in the
-sequence.</entry>
+           <entry>Set by the driver, counting the frames (not fields!) in
+sequence. This field is set for both input and output devices.</entry>
          </row>
          <row>
            <entry spanname="hspan"><para>In <link
@@ -677,26 +677,24 @@ memory, set by the application. See <xref linkend="userp" /> for details.
            <entry><structfield>length</structfield></entry>
            <entry></entry>
            <entry>Size of the buffer (not the payload) in bytes for the
-           single-planar API. For the multi-planar API should contain the
-           number of elements in the <structfield>planes</structfield> array.
+           single-planar API. For the multi-planar API the application sets
+           this to the number of elements in the <structfield>planes</structfield>
+           array. The driver will fill in the actual number of valid elements in
+           that array.
            </entry>
          </row>
          <row>
            <entry>__u32</entry>
            <entry><structfield>reserved2</structfield></entry>
            <entry></entry>
-           <entry>A place holder for future extensions and custom
-(driver defined) buffer types
-<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
+           <entry>A place holder for future extensions. Applications
 should set this to 0.</entry>
          </row>
          <row>
            <entry>__u32</entry>
            <entry><structfield>reserved</structfield></entry>
            <entry></entry>
-           <entry>A place holder for future extensions and custom
-(driver defined) buffer types
-<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher. Applications
+           <entry>A place holder for future extensions. Applications
 should set this to 0.</entry>
          </row>
        </tbody>
@@ -827,14 +825,7 @@ should set this to 0.</entry>
            <entry><constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY</constant></entry>
            <entry>8</entry>
            <entry>Buffer for video output overlay (OSD), see <xref
-               linkend="osd" />. Status: <link
-linkend="experimental">Experimental</link>.</entry>
-         </row>
-         <row>
-           <entry><constant>V4L2_BUF_TYPE_PRIVATE</constant></entry>
-           <entry>0x80</entry>
-         <entry>This and higher values are reserved for custom
-(driver defined) buffer types.</entry>
+               linkend="osd" />.</entry>
          </row>
        </tbody>
       </tgroup>
index 8eace3e2e7d4d7e0176f7539341d006fdb81bd83..2d3f0b1aefe0c878b6f133987b4abf70857c9c39 100644 (file)
@@ -22,8 +22,7 @@
        with 10 bits per colour compressed to 8 bits each, using DPCM
        compression. DPCM, differential pulse-code modulation, is lossy.
        Each colour component consumes 8 bits of memory. In other respects
-       this format is similar to <xref
-       linkend="pixfmt-srggb10">.</xref></para>
+       this format is similar to <xref linkend="pixfmt-srggb10" />.</para>
 
       </refsect1>
     </refentry>
diff --git a/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml b/Documentation/DocBook/media/v4l/pixfmt-yvu420m.xml
new file mode 100644 (file)
index 0000000..2330667
--- /dev/null
@@ -0,0 +1,154 @@
+    <refentry id="V4L2-PIX-FMT-YVU420M">
+      <refmeta>
+       <refentrytitle>V4L2_PIX_FMT_YVU420M ('YM21')</refentrytitle>
+       &manvol;
+      </refmeta>
+      <refnamediv>
+       <refname> <constant>V4L2_PIX_FMT_YVU420M</constant></refname>
+       <refpurpose>Variation of <constant>V4L2_PIX_FMT_YVU420</constant>
+         with planes non contiguous in memory. </refpurpose>
+      </refnamediv>
+
+      <refsect1>
+       <title>Description</title>
+
+       <para>This is a multi-planar format, as opposed to a packed format.
+The three components are separated into three sub-images or planes.
+
+The Y plane is first. The Y plane has one byte per pixel. The Cr data
+constitutes the second plane which is half the width and half
+the height of the Y plane (and of the image). Each Cr belongs to four
+pixels, a two-by-two square of the image. For example,
+Cr<subscript>0</subscript> belongs to Y'<subscript>00</subscript>,
+Y'<subscript>01</subscript>, Y'<subscript>10</subscript>, and
+Y'<subscript>11</subscript>. The Cb data, just like the Cr plane, constitutes
+the third plane. </para>
+
+       <para>If the Y plane has pad bytes after each row, then the Cr
+and Cb planes have half as many pad bytes after their rows. In other
+words, two Cx rows (including padding) is exactly as long as one Y row
+(including padding).</para>
+
+       <para><constant>V4L2_PIX_FMT_YVU420M</constant> is intended to be
+used only in drivers and applications that support the multi-planar API,
+described in <xref linkend="planar-apis"/>. </para>
+
+       <example>
+         <title><constant>V4L2_PIX_FMT_YVU420M</constant> 4 &times; 4
+pixel image</title>
+
+         <formalpara>
+           <title>Byte Order.</title>
+           <para>Each cell is one byte.
+               <informaltable frame="none">
+               <tgroup cols="5" align="center">
+                 <colspec align="left" colwidth="2*" />
+                 <tbody valign="top">
+                   <row>
+                     <entry>start0&nbsp;+&nbsp;0:</entry>
+                     <entry>Y'<subscript>00</subscript></entry>
+                     <entry>Y'<subscript>01</subscript></entry>
+                     <entry>Y'<subscript>02</subscript></entry>
+                     <entry>Y'<subscript>03</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start0&nbsp;+&nbsp;4:</entry>
+                     <entry>Y'<subscript>10</subscript></entry>
+                     <entry>Y'<subscript>11</subscript></entry>
+                     <entry>Y'<subscript>12</subscript></entry>
+                     <entry>Y'<subscript>13</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start0&nbsp;+&nbsp;8:</entry>
+                     <entry>Y'<subscript>20</subscript></entry>
+                     <entry>Y'<subscript>21</subscript></entry>
+                     <entry>Y'<subscript>22</subscript></entry>
+                     <entry>Y'<subscript>23</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start0&nbsp;+&nbsp;12:</entry>
+                     <entry>Y'<subscript>30</subscript></entry>
+                     <entry>Y'<subscript>31</subscript></entry>
+                     <entry>Y'<subscript>32</subscript></entry>
+                     <entry>Y'<subscript>33</subscript></entry>
+                   </row>
+                   <row><entry></entry></row>
+                   <row>
+                     <entry>start1&nbsp;+&nbsp;0:</entry>
+                     <entry>Cr<subscript>00</subscript></entry>
+                     <entry>Cr<subscript>01</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start1&nbsp;+&nbsp;2:</entry>
+                     <entry>Cr<subscript>10</subscript></entry>
+                     <entry>Cr<subscript>11</subscript></entry>
+                   </row>
+                   <row><entry></entry></row>
+                   <row>
+                     <entry>start2&nbsp;+&nbsp;0:</entry>
+                     <entry>Cb<subscript>00</subscript></entry>
+                     <entry>Cb<subscript>01</subscript></entry>
+                   </row>
+                   <row>
+                     <entry>start2&nbsp;+&nbsp;2:</entry>
+                     <entry>Cb<subscript>10</subscript></entry>
+                     <entry>Cb<subscript>11</subscript></entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+               </informaltable>
+             </para>
+         </formalpara>
+
+         <formalpara>
+           <title>Color Sample Location.</title>
+           <para>
+               <informaltable frame="none">
+               <tgroup cols="7" align="center">
+                 <tbody valign="top">
+                   <row>
+                     <entry></entry>
+                     <entry>0</entry><entry></entry><entry>1</entry><entry></entry>
+                     <entry>2</entry><entry></entry><entry>3</entry>
+                   </row>
+                   <row>
+                     <entry>0</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry><entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry>
+                   </row>
+                   <row>
+                     <entry>1</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                   </row>
+                   <row>
+                     <entry>2</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                   <row>
+                     <entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry><entry></entry>
+                     <entry></entry><entry>C</entry><entry></entry>
+                   </row>
+                   <row>
+                     <entry>3</entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry><entry></entry>
+                     <entry>Y</entry><entry></entry><entry>Y</entry>
+                   </row>
+                 </tbody>
+               </tgroup>
+               </informaltable>
+             </para>
+         </formalpara>
+       </example>
+      </refsect1>
+    </refentry>
index e58934c92895f159fc3200946a0d75ed50434e84..fce143726fd5adb7be0dd3e42f9173a165049809 100644 (file)
@@ -708,6 +708,7 @@ information.</para>
     &sub-y41p;
     &sub-yuv420;
     &sub-yuv420m;
+    &sub-yvu420m;
     &sub-yuv410;
     &sub-yuv422p;
     &sub-yuv411p;
@@ -995,6 +996,34 @@ the other bits are set to 0.</entry>
            <entry>Old 6-bit greyscale format. Only the most significant 6 bits of each byte are used,
 the other bits are set to 0.</entry>
          </row>
+         <row id="V4L2-PIX-FMT-S5C-UYVY-JPG">
+           <entry><constant>V4L2_PIX_FMT_S5C_UYVY_JPG</constant></entry>
+           <entry>'S5CI'</entry>
+           <entry>Two-planar format used by Samsung S5C73MX cameras. The
+first plane contains interleaved JPEG and UYVY image data, followed by meta data
+in form of an array of offsets to the UYVY data blocks. The actual pointer array
+follows immediately the interleaved JPEG/UYVY data, the number of entries in
+this array equals the height of the UYVY image. Each entry is a 4-byte unsigned
+integer in big endian order and it's an offset to a single pixel line of the
+UYVY image. The first plane can start either with JPEG or UYVY data chunk. The
+size of a single UYVY block equals the UYVY image's width multiplied by 2. The
+size of a JPEG chunk depends on the image and can vary with each line.
+<para>The second plane, at an offset of 4084 bytes, contains a 4-byte offset to
+the pointer array in the first plane. This offset is followed by a 4-byte value
+indicating size of the pointer array. All numbers in the second plane are also
+in big endian order. Remaining data in the second plane is undefined. The
+information in the second plane allows to easily find location of the pointer
+array, which can be different for each frame. The size of the pointer array is
+constant for given UYVY image height.</para>
+<para>In order to extract UYVY and JPEG frames an application can initially set
+a data pointer to the start of first plane and then add an offset from the first
+entry of the pointers table. Such a pointer indicates start of an UYVY image
+pixel line. Whole UYVY line can be copied to a separate buffer. These steps
+should be repeated for each line, i.e. the number of entries in the pointer
+array. Anything what's in between the UYVY lines is JPEG data and should be
+concatenated to form the JPEG stream. </para>
+</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index e7ed5077834deaa027fe1a202a555631338dba15..4c238ce068b0aa238155037be481336d800b8c78 100644 (file)
@@ -40,6 +40,7 @@ cropping and composing rectangles have the same size.</para>
     <section>
       <title>Selection targets</title>
 
+      <para>
       <figure id="sel-targets-capture">
        <title>Cropping and composing targets</title>
        <mediaobject>
@@ -52,12 +53,12 @@ cropping and composing rectangles have the same size.</para>
          </textobject>
        </mediaobject>
       </figure>
+      </para>
 
+      <para>See <xref linkend="v4l2-selection-targets" /> for more
+    information.</para>
     </section>
 
-    See <xref linkend="v4l2-selection-targets" /> for more
-    information.
-
   <section>
 
   <title>Configuration</title>
@@ -216,18 +217,17 @@ composing and cropping operations by setting the appropriate targets.  The V4L2
 API lacks any support for composing to and cropping from an image inside a
 memory buffer.  The application could configure a capture device to fill only a
 part of an image by abusing V4L2 API.  Cropping a smaller image from a larger
-one is achieved by setting the field <structfield>
-&v4l2-pix-format;::bytesperline </structfield>.  Introducing an image offsets
-could be done by modifying field <structfield> &v4l2-buffer;::m:userptr
-</structfield> before calling <constant> VIDIOC_QBUF </constant>. Those
+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
 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
 portable way.  Next, with the selection API the concepts of the padded target
-and constraints flags are introduced.  Finally, <structname> &v4l2-crop;
-</structname> and <structname> &v4l2-cropcap; </structname> have no reserved
-fields. Therefore there is no way to extend their functionality.  The new
-<structname> &v4l2-selection; </structname> provides a lot of place for future
+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>
 
index 49c532ebbbbefe3a6aac004dd4192936ec14e880..a0a936455faef1c68d59f5997b8697b7ad1e2d65 100644 (file)
        </tgroup>
       </table>
     </section>
+
+    <section id="v4l2-mbus-vendor-spec-fmts">
+      <title>Vendor and Device Specific Formats</title>
+
+      <note>
+       <title>Experimental</title>
+       <para>This is an <link linkend="experimental">experimental</link>
+interface and may change in the future.</para>
+      </note>
+
+      <para>This section lists complex data formats that are either vendor or
+       device specific.
+      </para>
+
+      <para>The following table lists the existing vendor and device specific
+       formats.</para>
+
+      <table pgwide="0" frame="none" id="v4l2-mbus-pixelcode-vendor-specific">
+       <title>Vendor and device specific formats</title>
+       <tgroup cols="3">
+         <colspec colname="id" align="left" />
+         <colspec colname="code" align="left"/>
+         <colspec colname="remarks" align="left"/>
+         <thead>
+           <row>
+             <entry>Identifier</entry>
+             <entry>Code</entry>
+             <entry>Comments</entry>
+           </row>
+         </thead>
+         <tbody valign="top">
+           <row id="V4L2-MBUS-FMT-S5C-UYVY-JPEG-1X8">
+             <entry>V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8</entry>
+             <entry>0x5001</entry>
+             <entry>
+               Interleaved raw UYVY and JPEG image format with embedded
+               meta-data used by Samsung S3C73MX camera sensors.
+             </entry>
+           </row>
+         </tbody>
+       </tgroup>
+      </table>
+    </section>
+
   </section>
 </section>
index eee6908c749fd3b6fb66e0e9ab84c9775c09509b..10ccde9d16d016d6f141f62479afa8f73753850b 100644 (file)
@@ -145,9 +145,12 @@ applications. -->
        <authorinitials>hv</authorinitials>
        <revremark>Added VIDIOC_ENUM_FREQ_BANDS.
        </revremark>
+      </revision>
+
+      <revision>
        <revnumber>3.5</revnumber>
        <date>2012-05-07</date>
-       <authorinitials>sa, sn</authorinitials>
+       <authorinitials>sa, sn, hv</authorinitials>
        <revremark>Added V4L2_CTRL_TYPE_INTEGER_MENU and V4L2 subdev
            selections API. Improved the description of V4L2_CID_COLORFX
            control, added V4L2_CID_COLORFX_CBCR control.
@@ -158,11 +161,8 @@ applications. -->
            V4L2_CID_3A_LOCK, V4L2_CID_AUTO_FOCUS_START,
            V4L2_CID_AUTO_FOCUS_STOP, V4L2_CID_AUTO_FOCUS_STATUS
            and V4L2_CID_AUTO_FOCUS_RANGE.
-       </revremark>
-       <date>2012-05-01</date>
-       <authorinitials>hv</authorinitials>
-       <revremark>Added VIDIOC_ENUM_DV_TIMINGS, VIDIOC_QUERY_DV_TIMINGS and
-       VIDIOC_DV_TIMINGS_CAP.
+           Added VIDIOC_ENUM_DV_TIMINGS, VIDIOC_QUERY_DV_TIMINGS and
+           VIDIOC_DV_TIMINGS_CAP.
        </revremark>
       </revision>
 
@@ -472,7 +472,7 @@ and discussions on the V4L mailing list.</revremark>
 </partinfo>
 
 <title>Video for Linux Two API Specification</title>
- <subtitle>Revision 3.5</subtitle>
+ <subtitle>Revision 3.6</subtitle>
 
   <chapter id="common">
     &sub-common;
@@ -581,6 +581,7 @@ and discussions on the V4L mailing list.</revremark>
     &sub-subdev-enum-frame-size;
     &sub-subdev-enum-mbus-code;
     &sub-subdev-g-crop;
+    &sub-subdev-g-edid;
     &sub-subdev-g-fmt;
     &sub-subdev-g-frame-interval;
     &sub-subdev-g-selection;
index f1bac2c6e9781e1079ee4ade3a732c515a1cfe42..bf7cc979fdfa6bbba9d92c0d5f7e7b68cc6a1518 100644 (file)
@@ -59,6 +59,9 @@ constant except when switching the video standard. Remember this
 switch can occur implicit when switching the video input or
 output.</para>
 
+    <para>This ioctl must be implemented for video capture or output devices that
+support cropping and/or scaling and/or have non-square pixels, and for overlay devices.</para>
+
     <table pgwide="1" frame="none" id="v4l2-cropcap">
       <title>struct <structname>v4l2_cropcap</structname></title>
       <tgroup cols="3">
@@ -70,10 +73,10 @@ output.</para>
            <entry>Type of the data stream, set by the application.
 Only these types are valid here:
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
+<constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, and custom (driver
-defined) types with code <constant>V4L2_BUF_TYPE_PRIVATE</constant>
-and higher. See <xref linkend="v4l2-buf-type" />.</entry>
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and
+<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
          </row>
          <row>
            <entry>struct <link linkend="v4l2-rect-crop">v4l2_rect</link></entry>
@@ -156,8 +159,7 @@ on 22 Oct 2002 subject "Re:[V4L][patches!] Re:v4l2/kernel-2.5" -->
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
          <para>The &v4l2-cropcap; <structfield>type</structfield> is
-invalid. This is not permitted for video capture, output and overlay devices,
-which must support <constant>VIDIOC_CROPCAP</constant>.</para>
+invalid.</para>
        </listitem>
       </varlistentry>
     </variablelist>
index 74b87f6e480aa241f751c4423060979b078db7be..9215627b04c77827e7b3195857d53c0fbdcea355 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-
-      <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-    </note>
-
     <para>These ioctls control an audio/video (usually MPEG-) decoder.
 <constant>VIDIOC_DECODER_CMD</constant> sends a command to the
 decoder, <constant>VIDIOC_TRY_DECODER_CMD</constant> can be used to
index f431b3ba79bd70ce3e0e277908f57d1168ff2ee2..0619ca5d2d36a250dae8ffe97771c5aad1e06c85 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-
-      <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-    </note>
-
     <para>These ioctls control an audio/video (usually MPEG-) encoder.
 <constant>VIDIOC_ENCODER_CMD</constant> sends a command to the
 encoder, <constant>VIDIOC_TRY_ENCODER_CMD</constant> can be used to
index 509f0012d2a68044860eb59077b0ee6717f28e38..fced5fb0dbf013d264c8be0fc994bbd43d1620f8 100644 (file)
@@ -229,6 +229,12 @@ intended for the user.</entry>
 is out of bounds.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video presets are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
index 24c3bf4fd29a46cdcd71dc3bab3991df46002fc0..b3e17c1dfaf524bd4a485d3ab7bb4ccb5cb70203 100644 (file)
@@ -106,6 +106,12 @@ application.</entry>
 is out of bounds.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video presets are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
index 81ebe48317fe57064045fc77912f1ee17dc96a25..f8dfeed34fcac79793df6303f9e70f3393033104 100644 (file)
@@ -58,6 +58,9 @@ structure. Drivers fill the rest of the structure or return an
 incrementing by one until <errorcode>EINVAL</errorcode> is
 returned.</para>
 
+    <para>Note that after switching input or output the list of enumerated image
+formats may be different.</para>
+
     <table pgwide="1" frame="none" id="v4l2-fmtdesc">
       <title>struct <structname>v4l2_fmtdesc</structname></title>
       <tgroup cols="3">
@@ -78,10 +81,8 @@ Only these types are valid here:
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
 <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE</constant>,
 <constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, and custom (driver
-defined) types with code <constant>V4L2_BUF_TYPE_PRIVATE</constant>
-and higher. See <xref linkend="v4l2-buf-type" />.</entry>
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE</constant> and
+<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
          </row>
          <row>
            <entry>__u32</entry>
index f77a13f486d7968e60128d31a485bde9e580bc5f..a78454b5abcd875e517418f4b803ebed1dce8b1a 100644 (file)
@@ -50,13 +50,6 @@ and pixel format and receives a frame width and height.</para>
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-
-      <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-    </note>
-
     <para>This ioctl allows applications to enumerate all frame sizes
 (&ie; width and height in pixels) that the device supports for the
 given pixel format.</para>
index 46d5a044a537a0f2647a4755f5601f9cbfc86d5c..3c9a81305ad4af75f8c6728dbfa9a879db4e6167 100644 (file)
@@ -283,7 +283,7 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
            <entry>This input supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
          </row>
          <row>
-           <entry><constant>V4L2_IN_CAP_CUSTOM_TIMINGS</constant></entry>
+           <entry><constant>V4L2_IN_CAP_DV_TIMINGS</constant></entry>
            <entry>0x00000002</entry>
            <entry>This input supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
          </row>
index 428020000ef001f4de42b70f243ac551603f1068..f4ab0798545dc7f3ff67a5d5e0d51d2c5562d90b 100644 (file)
@@ -168,7 +168,7 @@ input/output interface to linux-media@vger.kernel.org on 19 Oct 2009.
            <entry>This output supports setting DV presets by using VIDIOC_S_DV_PRESET.</entry>
          </row>
          <row>
-           <entry><constant>V4L2_OUT_CAP_CUSTOM_TIMINGS</constant></entry>
+           <entry><constant>V4L2_OUT_CAP_DV_TIMINGS</constant></entry>
            <entry>0x00000002</entry>
            <entry>This output supports setting video timings by using VIDIOC_S_DV_TIMINGS.</entry>
          </row>
index 3a5fc5405f96a869f0ff93262211c430dcbd4123..8065099401d16fb34a12ce6156592f2a601f3ce0 100644 (file)
@@ -378,6 +378,12 @@ system)</para></footnote></para></entry>
 is out of bounds.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Standard video timings are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
index c4ff3b1887fb6b0782caf2c90c6edfa7fb64ed72..75c6a93de3c173246aff4763da48cfdc4b3ce81f 100644 (file)
@@ -104,10 +104,8 @@ changed and <constant>VIDIOC_S_CROP</constant> returns the
            <entry><structfield>type</structfield></entry>
            <entry>Type of the data stream, set by the application.
 Only these types are valid here: <constant>V4L2_BUF_TYPE_VIDEO_CAPTURE</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant>,
-<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>, and custom (driver
-defined) types with code <constant>V4L2_BUF_TYPE_PRIVATE</constant>
-and higher. See <xref linkend="v4l2-buf-type" />.</entry>
+<constant>V4L2_BUF_TYPE_VIDEO_OUTPUT</constant> and
+<constant>V4L2_BUF_TYPE_VIDEO_OVERLAY</constant>. See <xref linkend="v4l2-buf-type" />.</entry>
          </row>
          <row>
            <entry>&v4l2-rect;</entry>
index 61be9fa3803acbb707277e7e3b5527b4d681533b..b9ea37634f6ccbfe06697df5459ed5232b406543 100644 (file)
@@ -77,6 +77,12 @@ If the preset is not supported, it returns an &EINVAL; </para>
 <constant>VIDIOC_S_DV_PRESET</constant>,<constant>VIDIOC_S_DV_PRESET</constant> parameter was unsuitable.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video presets are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
       <varlistentry>
        <term><errorcode>EBUSY</errorcode></term>
        <listitem>
@@ -104,7 +110,4 @@ If the preset is not supported, it returns an &EINVAL; </para>
       </tgroup>
     </table>
   </refsect1>
-  <refsect1>
-    &return-value;
-  </refsect1>
 </refentry>
index eda1a2991bbe4382f717c5407295407220250161..72369707bd77d00bd78e1546f2d8c17a1e6c0ae8 100644 (file)
@@ -56,7 +56,9 @@ a pointer to the &v4l2-dv-timings; structure as argument. If the ioctl is not su
 or the timing values are not correct, the driver returns &EINVAL;.</para>
 <para>The <filename>linux/v4l2-dv-timings.h</filename> header can be used to get the
 timings of the formats in the <xref linkend="cea861" /> and <xref linkend="vesadmt" />
-standards.</para>
+standards. If the current input or output does not support DV timings (e.g. if
+&VIDIOC-ENUMINPUT; does not set the <constant>V4L2_IN_CAP_DV_TIMINGS</constant> flag), then
+&ENODATA; is returned.</para>
   </refsect1>
 
   <refsect1>
@@ -70,6 +72,12 @@ standards.</para>
 <constant>VIDIOC_S_DV_TIMINGS</constant> parameter was unsuitable.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video timings are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
       <varlistentry>
        <term><errorcode>EBUSY</errorcode></term>
        <listitem>
@@ -320,7 +328,4 @@ detected or used depends on the hardware.
       </tgroup>
     </table>
   </refsect1>
-  <refsect1>
-    &return-value;
-  </refsect1>
 </refentry>
index 2aef02c9044e039db683f9b37307e24ae0c8eb3e..be25029a16f11dff77a39e5b026fe888db4f5ada 100644 (file)
   <refsect1>
     <title>Description</title>
 
-    <note>
-      <title>Experimental</title>
-
-      <para>This is an <link linkend="experimental">experimental</link>
-interface and may change in the future.</para>
-    </note>
-
     <para>The <constant>VIDIOC_G_ENC_INDEX</constant> ioctl provides
 meta data about a compressed video stream the same or another
 application currently reads from the driver, which is useful for
index 52acff193a6f5dc651d10e5c0413c9e90e05cdbc..ee8f56e1bac0924a1cffc27462743ad24aa62088 100644 (file)
@@ -81,7 +81,7 @@ the application calls the <constant>VIDIOC_S_FMT</constant> ioctl
 with a pointer to a <structname>v4l2_format</structname> structure
 the driver checks
 and adjusts the parameters against hardware abilities. Drivers
-should not return an error code unless the input is ambiguous, this is
+should not return an error code unless the <structfield>type</structfield> field is invalid, this is
 a mechanism to fathom device capabilities and to approach parameters
 acceptable for both the application and driver. On success the driver
 may program the hardware, allocate resources and generally prepare for
@@ -107,6 +107,10 @@ disabling I/O or possibly time consuming hardware preparations.
 Although strongly recommended drivers are not required to implement
 this ioctl.</para>
 
+    <para>The format as returned by <constant>VIDIOC_TRY_FMT</constant>
+must be identical to what <constant>VIDIOC_S_FMT</constant> returns for
+the same input or output.</para>
+
     <table pgwide="1" frame="none" id="v4l2-format">
       <title>struct <structname>v4l2_format</structname></title>
       <tgroup cols="4">
@@ -170,9 +174,7 @@ capture and output devices.</entry>
            <entry></entry>
            <entry>__u8</entry>
            <entry><structfield>raw_data</structfield>[200]</entry>
-           <entry>Place holder for future extensions and custom
-(driver defined) formats with <structfield>type</structfield>
-<constant>V4L2_BUF_TYPE_PRIVATE</constant> and higher.</entry>
+           <entry>Place holder for future extensions.</entry>
          </row>
        </tbody>
       </tgroup>
@@ -187,8 +189,7 @@ capture and output devices.</entry>
        <term><errorcode>EINVAL</errorcode></term>
        <listitem>
          <para>The &v4l2-format; <structfield>type</structfield>
-field is invalid, the requested buffer type not supported, or the
-format is not supported with this buffer type.</para>
+field is invalid or the requested buffer type not supported.</para>
        </listitem>
       </varlistentry>
     </variablelist>
index f83d2cdd1185419850783f18830abac424b340b8..9058224d1bbfff9c9bcbb71ca017793569a92941 100644 (file)
@@ -108,9 +108,7 @@ devices.</para>
            <entry></entry>
            <entry>__u8</entry>
            <entry><structfield>raw_data</structfield>[200]</entry>
-           <entry>A place holder for future extensions and custom
-(driver defined) buffer types <constant>V4L2_BUF_TYPE_PRIVATE</constant> and
-higher.</entry>
+           <entry>A place holder for future extensions.</entry>
          </row>
        </tbody>
       </tgroup>
index f76d8a6d9b92df2133babc08456ac3bfc4d9c171..b11ec75e21a10ddff0ea99f16897ec4d660179be 100644 (file)
@@ -152,12 +152,10 @@ 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>
 
-  </refsect1>
-
   <para>Selection targets and flags are documented in <xref
   linkend="v4l2-selections-common"/>.</para>
 
-    <section>
+    <para>
       <figure id="sel-const-adjust">
        <title>Size adjustments with constraint flags.</title>
        <mediaobject>
@@ -170,9 +168,9 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
          </textobject>
        </mediaobject>
       </figure>
-    </section>
+    </para>
 
-  <refsect1>
+  <para>
     <table pgwide="1" frame="none" id="v4l2-selection">
       <title>struct <structname>v4l2_selection</structname></title>
       <tgroup cols="3">
@@ -208,6 +206,7 @@ exist no rectangle </emphasis> that satisfies the constraints.</para>
        </tbody>
       </tgroup>
     </table>
+  </para>
   </refsect1>
 
   <refsect1>
index 99ff1a016220aee8461cddf088de122057c29ecf..4a898417de28933cf319d7ea110db3c7365bf199 100644 (file)
@@ -72,7 +72,9 @@ flags, being a write-only ioctl it does not return the actual new standard as
 the current input does not support the requested standard the driver
 returns an &EINVAL;. When the standard set is ambiguous drivers may
 return <errorcode>EINVAL</errorcode> or choose any of the requested
-standards.</para>
+standards. If the current input or output does not support standard video timings (e.g. if
+&VIDIOC-ENUMINPUT; does not set the <constant>V4L2_IN_CAP_STD</constant> flag), then
+&ENODATA; is returned.</para>
   </refsect1>
 
   <refsect1>
@@ -85,6 +87,12 @@ standards.</para>
          <para>The <constant>VIDIOC_S_STD</constant> parameter was unsuitable.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Standard video timings are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 </refentry>
index 701138f1209de10ae439aff4da056803fbb79713..6cc82010c7366921792eb4204655bfc92675d0bc 100644 (file)
@@ -354,6 +354,12 @@ radio tuners.</entry>
        <entry>The &VIDIOC-ENUM-FREQ-BANDS; ioctl can be used to enumerate
        the available frequency bands.</entry>
          </row>
+         <row>
+       <entry><constant>V4L2_TUNER_CAP_HWSEEK_PROG_LIM</constant></entry>
+       <entry>0x0800</entry>
+       <entry>The range to search when using the hardware seek functionality
+       is programmable, see &VIDIOC-S-HW-FREQ-SEEK; for details.</entry>
+         </row>
        </tbody>
       </tgroup>
     </table>
index 77ff5be0809d13ef530ff07718e243aab98358fc..2d37abefce13e90144941af12cc2baa71f78a700 100644 (file)
@@ -121,8 +121,7 @@ remaining fields or returns an error code. The driver may also set
 field. It indicates a non-critical (recoverable) streaming error. In such case
 the application may continue as normal, but should be aware that data in the
 dequeued buffer might be corrupted. When using the multi-planar API, the
-planes array does not have to be passed; the <structfield>m.planes</structfield>
-member must be set to NULL in that case.</para>
+planes array must be passed in as well.</para>
 
     <para>By default <constant>VIDIOC_DQBUF</constant> blocks when no
 buffer is in the outgoing queue. When the
@@ -155,6 +154,8 @@ or no buffers have been allocated yet, or the
 <structfield>userptr</structfield> or
 <structfield>length</structfield> are invalid.</para>
        </listitem>
+      </varlistentry>
+      <varlistentry>
        <term><errorcode>EIO</errorcode></term>
        <listitem>
          <para><constant>VIDIOC_DQBUF</constant> failed due to an
index 1bc8aeb3ff1fe2a57516f39dd54128fc4c30e116..68b49d09e2454d8e6b988521b672bdd80750e182 100644 (file)
@@ -65,5 +65,14 @@ returned.</para>
 
   <refsect1>
     &return-value;
+
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video presets are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
   </refsect1>
 </refentry>
index 44935a0ffcf0bb619d40898ab0e937f0e13de82b..e185f149e0a18914538eab16e32f684ce15f145d 100644 (file)
@@ -77,6 +77,12 @@ capabilities in order to give more precise feedback to the user.
     &return-value;
 
     <variablelist>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Digital video timings are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
       <varlistentry>
        <term><errorcode>ENOLINK</errorcode></term>
        <listitem>
index 6e414d7b6df759f83f45ad34256c5ace012a6543..a597155c052d723b7b5c5867f67c564dd2eacebe 100644 (file)
@@ -48,8 +48,8 @@
   <refsect1>
     <title>Description</title>
 
-    <para>This ioctl is part of the <link linkend="mmap">memory
-mapping</link> I/O method. It can be used to query the status of a
+    <para>This ioctl is part of the <link linkend="mmap">streaming
+</link> I/O method. It can be used to query the status of a
 buffer at any time after buffers have been allocated with the
 &VIDIOC-REQBUFS; ioctl.</para>
 
@@ -71,6 +71,7 @@ the structure.</para>
 
     <para>In the <structfield>flags</structfield> field the
 <constant>V4L2_BUF_FLAG_MAPPED</constant>,
+<constant>V4L2_BUF_FLAG_PREPARED</constant>,
 <constant>V4L2_BUF_FLAG_QUEUED</constant> and
 <constant>V4L2_BUF_FLAG_DONE</constant> flags will be valid. The
 <structfield>memory</structfield> field will be set to the current
@@ -79,8 +80,10 @@ contains the offset of the buffer from the start of the device memory,
 the <structfield>length</structfield> field its size. For the multi-planar API,
 fields <structfield>m.mem_offset</structfield> and
 <structfield>length</structfield> in the <structfield>m.planes</structfield>
-array elements will be used instead. The driver may or may not set the remaining
-fields and flags, they are meaningless in this context.</para>
+array elements will be used instead and the <structfield>length</structfield>
+field of &v4l2-buffer; is set to the number of filled-in array elements.
+The driver may or may not set the remaining fields and flags, they are
+meaningless in this context.</para>
 
     <para>The <structname>v4l2_buffer</structname> structure is
     specified in <xref linkend="buffer" />.</para>
index f33dd746b66b8177b60f5a431aefc937973e5eea..4c70215ae03fee9040c0472c489753dd3d1fed9a 100644 (file)
@@ -90,11 +90,13 @@ ambiguities.</entry>
            <entry>__u8</entry>
            <entry><structfield>bus_info</structfield>[32]</entry>
            <entry>Location of the device in the system, a
-NUL-terminated ASCII string. For example: "PCI Slot 4". This
+NUL-terminated ASCII string. For example: "PCI:0000:05:06.0". This
 information is intended for users, to distinguish multiple
-identical devices. If no such information is available the field may
-simply count the devices controlled by the driver, or contain the
-empty string (<structfield>bus_info</structfield>[0] = 0).<!-- XXX pci_dev->slot_name example --></entry>
+identical devices. If no such information is available the field must
+simply count the devices controlled by the driver ("platform:vivi-000").
+The bus_info must start with "PCI:" for PCI boards, "PCIe:" for PCI Express boards,
+"usb-" for USB devices, "I2C:" for i2c devices, "ISA:" for ISA devices,
+"parport" for parallel port devices and "platform:" for platform devices.</entry>
          </row>
          <row>
            <entry>__u32</entry>
index 4b79c7c04ed6631c30adc168cf18d5e6608d8478..fe80a183d95776da5c8841ee277496f991420c6c 100644 (file)
@@ -62,5 +62,13 @@ current video input or output.</para>
 
   <refsect1>
     &return-value;
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>Standard video timings are not supported for this input or output.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
   </refsect1>
 </refentry>
index d7c95057bc5197e68a00ea22a388150a61702478..2b50ef2007f3cc96dc363176e2c173af96c3e2a8 100644 (file)
@@ -109,9 +109,8 @@ as the &v4l2-format; <structfield>type</structfield> field. See <xref
          <row>
            <entry>__u32</entry>
            <entry><structfield>reserved</structfield>[2]</entry>
-           <entry>A place holder for future extensions and custom
-(driver defined) buffer types <constant>V4L2_BUF_TYPE_PRIVATE</constant> and
-higher. This array should be zeroed by applications.</entry>
+           <entry>A place holder for future extensions. This array should
+be zeroed by applications.</entry>
          </row>
        </tbody>
       </tgroup>
index 3dd1bec6d3c74c1a6619364aaae41d85d615d17f..5b379e752194a2b096ce512e11facde121c8aabc 100644 (file)
@@ -75,6 +75,9 @@ seek is started.</para>
 
     <para>This ioctl is supported if the <constant>V4L2_CAP_HW_FREQ_SEEK</constant> capability is set.</para>
 
+    <para>If this ioctl is called from a non-blocking filehandle, then &EAGAIN; is
+    returned and no seek takes place.</para>
+
     <table pgwide="1" frame="none" id="v4l2-hw-freq-seek">
       <title>struct <structname>v4l2_hw_freq_seek</structname></title>
       <tgroup cols="3">
@@ -157,6 +160,13 @@ one of the values in the <structfield>type</structfield>,
 fields is wrong.</para>
        </listitem>
       </varlistentry>
+      <varlistentry>
+       <term><errorcode>EAGAIN</errorcode></term>
+       <listitem>
+         <para>Attempted to call <constant>VIDIOC_S_HW_FREQ_SEEK</constant>
+         with the filehandle in non-blocking mode.</para>
+       </listitem>
+      </varlistentry>
       <varlistentry>
        <term><errorcode>ENODATA</errorcode></term>
        <listitem>
index 81cca4569050da8d789dc68973798b69fdbc8a35..716ea15e54a174be6321f19aa4be69fe00487f28 100644 (file)
@@ -74,7 +74,12 @@ not transmitted yet. I/O returns to the same state as after calling
 stream type. This is the same as &v4l2-requestbuffers;
 <structfield>type</structfield>.</para>
 
-    <para>Note applications can be preempted for unknown periods right
+    <para>If <constant>VIDIOC_STREAMON</constant> is called when streaming
+is already in progress, or if <constant>VIDIOC_STREAMOFF</constant> is called
+when streaming is already stopped, then the ioctl does nothing and 0 is
+returned.</para>
+
+    <para>Note that applications can be preempted for unknown periods right
 before or after the <constant>VIDIOC_STREAMON</constant> or
 <constant>VIDIOC_STREAMOFF</constant> calls, there is no notion of
 starting or stopping "now". Buffer timestamps can be used to
diff --git a/Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml b/Documentation/DocBook/media/v4l/vidioc-subdev-g-edid.xml
new file mode 100644 (file)
index 0000000..bbd18f0
--- /dev/null
@@ -0,0 +1,152 @@
+<refentry id="vidioc-subdev-g-edid">
+  <refmeta>
+    <refentrytitle>ioctl VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</refentrytitle>
+    &manvol;
+  </refmeta>
+
+  <refnamediv>
+    <refname>VIDIOC_SUBDEV_G_EDID</refname>
+    <refname>VIDIOC_SUBDEV_S_EDID</refname>
+    <refpurpose>Get or set the EDID of a video receiver/transmitter</refpurpose>
+  </refnamediv>
+
+  <refsynopsisdiv>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>struct v4l2_subdev_edid *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+    <funcsynopsis>
+      <funcprototype>
+       <funcdef>int <function>ioctl</function></funcdef>
+       <paramdef>int <parameter>fd</parameter></paramdef>
+       <paramdef>int <parameter>request</parameter></paramdef>
+       <paramdef>const struct v4l2_subdev_edid *<parameter>argp</parameter></paramdef>
+      </funcprototype>
+    </funcsynopsis>
+  </refsynopsisdiv>
+
+  <refsect1>
+    <title>Arguments</title>
+
+    <variablelist>
+      <varlistentry>
+       <term><parameter>fd</parameter></term>
+       <listitem>
+         <para>&fd;</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>request</parameter></term>
+       <listitem>
+         <para>VIDIOC_SUBDEV_G_EDID, VIDIOC_SUBDEV_S_EDID</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><parameter>argp</parameter></term>
+       <listitem>
+         <para></para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+
+  <refsect1>
+    <title>Description</title>
+    <para>These ioctls can be used to get or set an EDID associated with an input pad
+    from a receiver or an output pad of a transmitter subdevice.</para>
+
+    <para>To get the EDID data the application has to fill in the <structfield>pad</structfield>,
+    <structfield>start_block</structfield>, <structfield>blocks</structfield> and <structfield>edid</structfield>
+    fields and call <constant>VIDIOC_SUBDEV_G_EDID</constant>. The current EDID from block
+    <structfield>start_block</structfield> and of size <structfield>blocks</structfield>
+    will be placed in the memory <structfield>edid</structfield> points to. The <structfield>edid</structfield>
+    pointer must point to memory at least <structfield>blocks</structfield>&nbsp;*&nbsp;128 bytes
+    large (the size of one block is 128 bytes).</para>
+
+    <para>If there are fewer blocks than specified, then the driver will set <structfield>blocks</structfield>
+    to the actual number of blocks. If there are no EDID blocks available at all, then the error code
+    ENODATA is set.</para>
+
+    <para>If blocks have to be retrieved from the sink, then this call will block until they
+    have been read.</para>
+
+    <para>To set the EDID blocks of a receiver the application has to fill in the <structfield>pad</structfield>,
+    <structfield>blocks</structfield> and <structfield>edid</structfield> fields and set
+    <structfield>start_block</structfield> to 0. It is not possible to set part of an EDID,
+    it is always all or nothing. Setting the EDID data is only valid for receivers as it makes
+    no sense for a transmitter.</para>
+
+    <para>The driver assumes that the full EDID is passed in. If there are more EDID blocks than
+    the hardware can handle then the EDID is not written, but instead the error code E2BIG is set
+    and <structfield>blocks</structfield> is set to the maximum that the hardware supports.
+    If <structfield>start_block</structfield> is any
+    value other than 0 then the error code EINVAL is set.</para>
+
+    <para>To disable an EDID you set <structfield>blocks</structfield> to 0. Depending on the
+    hardware this will drive the hotplug pin low and/or block the source from reading the EDID
+    data in some way. In any case, the end result is the same: the EDID is no longer available.
+    </para>
+
+    <table pgwide="1" frame="none" id="v4l2-subdev-edid">
+      <title>struct <structname>v4l2_subdev_edid</structname></title>
+      <tgroup cols="3">
+        &cs-str;
+       <tbody valign="top">
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>pad</structfield></entry>
+           <entry>Pad for which to get/set the EDID blocks.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>start_block</structfield></entry>
+           <entry>Read the EDID from starting with this block. Must be 0 when setting
+           the EDID.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>blocks</structfield></entry>
+           <entry>The number of blocks to get or set. Must be less or equal to 256 (the
+           maximum number of blocks as defined by the standard). When you set the EDID and
+           <structfield>blocks</structfield> is 0, then the EDID is disabled or erased.</entry>
+         </row>
+         <row>
+           <entry>__u8&nbsp;*</entry>
+           <entry><structfield>edid</structfield></entry>
+           <entry>Pointer to memory that contains the EDID. The minimum size is
+           <structfield>blocks</structfield>&nbsp;*&nbsp;128.</entry>
+         </row>
+         <row>
+           <entry>__u32</entry>
+           <entry><structfield>reserved</structfield>[5]</entry>
+           <entry>Reserved for future extensions. Applications and drivers must
+           set the array to zero.</entry>
+         </row>
+       </tbody>
+      </tgroup>
+    </table>
+  </refsect1>
+
+  <refsect1>
+    &return-value;
+
+    <variablelist>
+      <varlistentry>
+       <term><errorcode>ENODATA</errorcode></term>
+       <listitem>
+         <para>The EDID data is not available.</para>
+       </listitem>
+      </varlistentry>
+      <varlistentry>
+       <term><errorcode>E2BIG</errorcode></term>
+       <listitem>
+         <para>The EDID data you provided is more than the hardware can handle.</para>
+       </listitem>
+      </varlistentry>
+    </variablelist>
+  </refsect1>
+</refentry>
index f33cc814a01d14d07483a04051f4513ace88876c..1ba9e999af3fec1bed5a3a116f37ac0358caf4e0 100644 (file)
     more information on how each selection target affects the image
     processing pipeline inside the subdevice.</para>
 
-    <section>
+    <refsect2>
       <title>Types of selection targets</title>
 
       <para>There are two types of selection targets: actual and bounds. The
       actual targets are the targets which configure the hardware. The BOUNDS
       target will return a rectangle that contain all possible actual
       rectangles.</para>
-    </section>
+    </refsect2>
 
-    <section>
+    <refsect2>
       <title>Discovering supported features</title>
 
       <para>To discover which targets are supported, the user can
       perform <constant>VIDIOC_SUBDEV_G_SELECTION</constant> on them.
       Any unsupported target will return
       <constant>EINVAL</constant>.</para>
-    </section>
 
     <para>Selection targets and flags are documented in <xref
     linkend="v4l2-selections-common"/>.</para>
        </tbody>
       </tgroup>
     </table>
+    </refsect2>
 
   </refsect1>
 
index 4e8e8985cc1722a5594efdb61c2c0a5af1294929..f2413acfe24105b00b529feca5a0490d6a9b126d 100644 (file)
@@ -29,7 +29,7 @@
 <title>LINUX MEDIA INFRASTRUCTURE API</title>
 
 <copyright>
-       <year>2009-2011</year>
+       <year>2009-2012</year>
        <holder>LinuxTV Developers</holder>
 </copyright>
 
@@ -53,7 +53,7 @@ Foundation. A copy of the license is included in the chapter entitled
                video and radio straming devices, including video cameras,
                analog and digital TV receiver cards, AM/FM receiver cards,
                streaming capture devices.</para>
-       <para>It is divided into three parts.</para>
+       <para>It is divided into four parts.</para>
        <para>The first part covers radio, capture,
                cameras and analog TV devices.</para>
        <para>The second part covers the
@@ -62,7 +62,8 @@ Foundation. A copy of the license is included in the chapter entitled
                in fact it covers several different video standards including
                DVB-T, DVB-S, DVB-C and ATSC. The API is currently being updated
                to documment support also for DVB-S2, ISDB-T and ISDB-S.</para>
-       <para>The third part covers Remote Controller API</para>
+       <para>The third part covers the Remote Controller API.</para>
+       <para>The fourth part covers the Media Controller API.</para>
        <para>For additional information and for the latest development code,
                see: <ulink url="http://linuxtv.org">http://linuxtv.org</ulink>.</para>
        <para>For discussing improvements, reporting troubles, sending new drivers, etc, please mail to: <ulink url="http://vger.kernel.org/vger-lists.html#linux-media">Linux Media Mailing List (LMML).</ulink>.</para>
@@ -87,7 +88,7 @@ Foundation. A copy of the license is included in the chapter entitled
 </author>
 </authorgroup>
 <copyright>
-       <year>2009-2011</year>
+       <year>2009-2012</year>
        <holder>Mauro Carvalho Chehab</holder>
 </copyright>
 
index d111e3b23db0bbc0bdf23d81c27e74158ccd9a66..d18ecd827c408d0fb42a8d8a7fc669ce88c95fc2 100644 (file)
@@ -3,15 +3,21 @@
 biodoc.txt
        - Notes on the Generic Block Layer Rewrite in Linux 2.5
 capability.txt
-       - Generic Block Device Capability (/sys/block/<disk>/capability)
+       - Generic Block Device Capability (/sys/block/<device>/capability)
+cfq-iosched.txt
+       - CFQ IO scheduler tunables
+data-integrity.txt
+       - Block data integrity
 deadline-iosched.txt
        - Deadline IO scheduler tunables
 ioprio.txt
        - Block io priorities (in CFQ scheduler)
+queue-sysfs.txt
+       - Queue's sysfs entries
 request.txt
        - The members of struct request (in include/linux/blkdev.h)
 stat.txt
-       - Block layer statistics in /sys/block/<dev>/stat
+       - Block layer statistics in /sys/block/<device>/stat
 switching-sched.txt
        - Switching I/O schedulers at runtime
 writeback_cache_control.txt
index 6d670f570451a14c1ce4f8c2eb1c69d52736ee01..d89b4fe724d75393a003b33c22bf531252c29672 100644 (file)
@@ -1,3 +1,14 @@
+CFQ (Complete Fairness Queueing)
+===============================
+
+The main aim of CFQ scheduler is to provide a fair allocation of the disk
+I/O bandwidth for all the processes which requests an I/O operation.
+
+CFQ maintains the per process queue for the processes which request I/O
+operation(syncronous requests). In case of asynchronous requests, all the
+requests from all the processes are batched together according to their
+process's I/O priority.
+
 CFQ ioscheduler tunables
 ========================
 
@@ -25,6 +36,72 @@ there are multiple spindles behind single LUN (Host based hardware RAID
 controller or for storage arrays), setting slice_idle=0 might end up in better
 throughput and acceptable latencies.
 
+back_seek_max
+-------------
+This specifies, given in Kbytes, the maximum "distance" for backward seeking.
+The distance is the amount of space from the current head location to the
+sectors that are backward in terms of distance.
+
+This parameter allows the scheduler to anticipate requests in the "backward"
+direction and consider them as being the "next" if they are within this
+distance from the current head location.
+
+back_seek_penalty
+-----------------
+This parameter is used to compute the cost of backward seeking. If the
+backward distance of request is just 1/back_seek_penalty from a "front"
+request, then the seeking cost of two requests is considered equivalent.
+
+So scheduler will not bias toward one or the other request (otherwise scheduler
+will bias toward front request). Default value of back_seek_penalty is 2.
+
+fifo_expire_async
+-----------------
+This parameter is used to set the timeout of asynchronous requests. Default
+value of this is 248ms.
+
+fifo_expire_sync
+----------------
+This parameter is used to set the timeout of synchronous requests. Default
+value of this is 124ms. In case to favor synchronous requests over asynchronous
+one, this value should be decreased relative to fifo_expire_async.
+
+slice_async
+-----------
+This parameter is same as of slice_sync but for asynchronous queue. The
+default value is 40ms.
+
+slice_async_rq
+--------------
+This parameter is used to limit the dispatching of asynchronous request to
+device request queue in queue's slice time. The maximum number of request that
+are allowed to be dispatched also depends upon the io priority. Default value
+for this is 2.
+
+slice_sync
+----------
+When a queue is selected for execution, the queues IO requests are only
+executed for a certain amount of time(time_slice) before switching to another
+queue. This parameter is used to calculate the time slice of synchronous
+queue.
+
+time_slice is computed using the below equation:-
+time_slice = slice_sync + (slice_sync/5 * (4 - prio)). To increase the
+time_slice of synchronous queue, increase the value of slice_sync. Default
+value is 100ms.
+
+quantum
+-------
+This specifies the number of request dispatched to the device queue. In a
+queue's time slice, a request will not be dispatched if the number of request
+in the device exceeds this parameter. This parameter is used for synchronous
+request.
+
+In case of storage with several disk, this setting can limit the parallel
+processing of request. Therefore, increasing the value can imporve the
+performace although this can cause the latency of some I/O to increase due
+to more number of requests.
+
 CFQ IOPS Mode for group scheduling
 ===================================
 Basic CFQ design is to provide priority based time slices. Higher priority
index 6518a55273e7094f62f84a5d83467fd96b26fd26..e54ac1d53403094c59e019b1f5e5397e8f4f637d 100644 (file)
@@ -9,20 +9,71 @@ These files are the ones found in the /sys/block/xxx/queue/ directory.
 Files denoted with a RO postfix are readonly and the RW postfix means
 read-write.
 
+add_random (RW)
+----------------
+This file allows to trun off the disk entropy contribution. Default
+value of this file is '1'(on).
+
+discard_granularity (RO)
+-----------------------
+This shows the size of internal allocation of the device in bytes, if
+reported by the device. A value of '0' means device does not support
+the discard functionality.
+
+discard_max_bytes (RO)
+----------------------
+Devices that support discard functionality may have internal limits on
+the number of bytes that can be trimmed or unmapped in a single operation.
+The discard_max_bytes parameter is set by the device driver to the maximum
+number of bytes that can be discarded in a single operation. Discard
+requests issued to the device must not exceed this limit. A discard_max_bytes
+value of 0 means that the device does not support discard functionality.
+
+discard_zeroes_data (RO)
+------------------------
+When read, this file will show if the discarded block are zeroed by the
+device or not. If its value is '1' the blocks are zeroed otherwise not.
+
 hw_sector_size (RO)
 -------------------
 This is the hardware sector size of the device, in bytes.
 
+iostats (RW)
+-------------
+This file is used to control (on/off) the iostats accounting of the
+disk.
+
+logical_block_size (RO)
+-----------------------
+This is the logcal block size of the device, in bytes.
+
 max_hw_sectors_kb (RO)
 ----------------------
 This is the maximum number of kilobytes supported in a single data transfer.
 
+max_integrity_segments (RO)
+---------------------------
+When read, this file shows the max limit of integrity segments as
+set by block layer which a hardware controller can handle.
+
 max_sectors_kb (RW)
 -------------------
 This is the maximum number of kilobytes that the block layer will allow
 for a filesystem request. Must be smaller than or equal to the maximum
 size allowed by the hardware.
 
+max_segments (RO)
+-----------------
+Maximum number of segments of the device.
+
+max_segment_size (RO)
+---------------------
+Maximum segment size of the device.
+
+minimum_io_size (RO)
+--------------------
+This is the smallest preferred io size reported by the device.
+
 nomerges (RW)
 -------------
 This enables the user to disable the lookup logic involved with IO
@@ -45,11 +96,24 @@ per-block-cgroup request pool.  IOW, if there are N block cgroups,
 each request queue may have upto N request pools, each independently
 regulated by nr_requests.
 
+optimal_io_size (RO)
+--------------------
+This is the optimal io size reported by the device.
+
+physical_block_size (RO)
+------------------------
+This is the physical block size of device, in bytes.
+
 read_ahead_kb (RW)
 ------------------
 Maximum number of kilobytes to read-ahead for filesystems on this block
 device.
 
+rotational (RW)
+---------------
+This file is used to stat if the device is of rotational type or
+non-rotational type.
+
 rq_affinity (RW)
 ----------------
 If this option is '1', the block layer will migrate request completions to the
index 70cd49b1caa8c07e71b7d0855a9469fc989cb7f6..1dd622546d06b711bf262358b387b4bb9af3f68a 100644 (file)
@@ -10,8 +10,8 @@ Required properties:
 - compatible : Should be "fsl,<chip>-esdhc"
 
 Optional properties:
-- fsl,cd-internal : Indicate to use controller internal card detection
-- fsl,wp-internal : Indicate to use controller internal write protection
+- fsl,cd-controller : Indicate to use controller internal card detection
+- fsl,wp-controller : Indicate to use controller internal write protection
 
 Examples:
 
@@ -19,8 +19,8 @@ esdhc@70004000 {
        compatible = "fsl,imx51-esdhc";
        reg = <0x70004000 0x4000>;
        interrupts = <1>;
-       fsl,cd-internal;
-       fsl,wp-internal;
+       fsl,cd-controller;
+       fsl,wp-controller;
 };
 
 esdhc@70008000 {
index c4d963a67d6ffc1ec7e54b8d31cc7d9b41537796..8eb92264ee047163caa25738a30c09ad04d20fcc 100644 (file)
@@ -30,7 +30,7 @@ with the device via the bus. The connection between the DVB-API-functionality
 is done via callbacks, assigned in a static device-description (struct
 dvb_usb_device) each device-driver has to have.
 
-For an example have a look in drivers/media/dvb/dvb-usb/vp7045*.
+For an example have a look in drivers/media/usb/dvb-usb/vp7045*.
 
 Objective is to migrate all the usb-devices (dibusb, cinergyT2, maybe the
 ttusb; flexcop-usb already benefits from the generic flexcop-device) to use
index 12d3952e83d5b0305c26afba116047aabf3c2850..32bc56b13b1c7c527669d0a2525486f46115faee 100755 (executable)
@@ -116,7 +116,7 @@ sub tda10045 {
 
 sub tda10046 {
        my $sourcefile = "TT_PCI_2.19h_28_11_2006.zip";
-       my $url = "http://www.tt-download.com/download/updates/219/$sourcefile";
+       my $url = "http://technotrend.com.ua/download/software/219/$sourcefile";
        my $hash = "6a7e1e2f2644b162ff0502367553c72d";
        my $outfile = "dvb-fe-tda10046.fw";
        my $tmpdir = tempdir(DIR => "/tmp", CLEANUP => 1);
index afaff312bf415acb59449aeb9bee4c848c197ff2..28179cfdace6daf0cd10c9a04ab3a7b33127feef 100644 (file)
@@ -6,6 +6,15 @@ be removed from this file.  The suggested deprecation period is 3 releases.
 
 ---------------------------
 
+What:  support for i.mx25 in mx2_camera.c
+When:  v3.8
+Why:   it's been broken for a year. Furthermore, i.MX25 video capture
+       HW doesn't have much in common with i.MX27. A separate driver
+       will be needed for it.
+Who:   Javier Martin<javier.martin@vista-silicon.com>
+
+---------------------------
+
 What:  ddebug_query="query" boot cmdline param
 When:  v3.8
 Why:   obsoleted by dyndbg="query" and module.dyndbg="query"
@@ -579,7 +588,7 @@ Why:        KVM tracepoints provide mostly equivalent information in a much more
 ----------------------------
 
 What:  at91-mci driver ("CONFIG_MMC_AT91")
-When:  3.7
+When:  3.8
 Why:   There are two mci drivers: at91-mci and atmel-mci. The PDC support
        was added to atmel-mci as a first step to support more chips.
        Then at91-mci was kept only for old IP versions (on at91rm9200 and
@@ -637,3 +646,12 @@ Who:       Russell King <linux@arm.linux.org.uk>,
        Santosh Shilimkar <santosh.shilimkar@ti.com>
 
 ----------------------------
+
+What:  Remove deprecated DV timings capability defines V4L2_IN_CAP_CUSTOM_TIMINGS
+       and V4L2_OUT_CAP_CUSTOM_TIMINGS.
+When:  3.9
+Why:   These defines have been replaced by V4L2_IN_CAP_TIMINGS and
+       V4L2_OUT_CAP_TIMINGS respectively.
+Who:   Hans Verkuil <hans.verkuil@cisco.com>
+
+----------------------------
index 615142da4ef64c6ec8ae87893425046a1564e786..157416e78cc4168859c89c88b13bcfeb71c4848f 100644 (file)
@@ -21,6 +21,7 @@ Supported adapters:
   * Intel DH89xxCC (PCH)
   * Intel Panther Point (PCH)
   * Intel Lynx Point (PCH)
+  * Intel Lynx Point-LP (PCH)
    Datasheets: Publicly available at the Intel website
 
 On Intel Patsburg and later chipsets, both the normal host SMBus controller
index 849b771c5e03620799cbdce625e16bab7ffa275b..2152b0e7237db87a60ef4897a949974f0c2b8d2d 100644 (file)
@@ -178,7 +178,6 @@ Code  Seq#(hex)     Include File            Comments
 'V'    C0      linux/ivtv.h            conflict!
 'V'    C0      media/davinci/vpfe_capture.h    conflict!
 'V'    C0      media/si4713.h          conflict!
-'V'    C0-CF   drivers/media/video/mxb.h       conflict!
 'W'    00-1F   linux/watchdog.h        conflict!
 'W'    00-1F   linux/wanrouter.h       conflict!
 'W'    00-3F   sound/asound.h          conflict!
@@ -204,8 +203,6 @@ Code  Seq#(hex)     Include File            Comments
 'c'    A0-AF   arch/x86/include/asm/msr.h      conflict!
 'd'    00-FF   linux/char/drm/drm/h    conflict!
 'd'    02-40   pcmcia/ds.h             conflict!
-'d'    10-3F   drivers/media/video/dabusb.h    conflict!
-'d'    C0-CF   drivers/media/video/saa7191.h   conflict!
 'd'    F0-FF   linux/digi1.h
 'e'    all     linux/digi1.h           conflict!
 'e'    00-1F   drivers/net/irda/irtty-sir.h    conflict!
@@ -267,9 +264,7 @@ Code  Seq#(hex)     Include File            Comments
 'v'    00-1F   linux/ext2_fs.h         conflict!
 'v'    00-1F   linux/fs.h              conflict!
 'v'    00-0F   linux/sonypi.h          conflict!
-'v'    C0-DF   media/pwc-ioctl.h       conflict!
 'v'    C0-FF   linux/meye.h            conflict!
-'v'    D0-DF   drivers/media/video/cpia2/cpia2dev.h    conflict!
 'w'    all                             CERN SCI driver
 'y'    00-1F                           packet based user level communications
                                        <mailto:zapman@interlan.net>
index 0cb6685c802904c0d7becccb00e3a00321bfb928..8eda3635a17da0e8d610a01e88d928a68f833f93 100644 (file)
@@ -133,7 +133,7 @@ character devices for this group:
 $ lspci -n -s 0000:06:0d.0
 06:0d.0 0401: 1102:0002 (rev 08)
 # echo 0000:06:0d.0 > /sys/bus/pci/devices/0000:06:0d.0/driver/unbind
-# echo 1102 0002 > /sys/bus/pci/drivers/vfio/new_id
+# echo 1102 0002 > /sys/bus/pci/drivers/vfio-pci/new_id
 
 Now we need to look at what other devices are in the group to free
 it for use by VFIO:
index 652aecd131998a7d2958a6a7cc2978e0eeeaa9ae..1299b5e82d7f42450e12eef450dbf6a650823428 100644 (file)
@@ -35,3 +35,4 @@
  34 -> TerraTec Cinergy T PCIe Dual                        [153b:117e]
  35 -> TeVii S471                                          [d471:9022]
  36 -> Hauppauge WinTV-HVR1255                             [0070:2259]
+ 37 -> Prof Revolution DVB-S2 8000                         [8000:3034]
index 6e680fec1e9c1d5e43a39e3e160572beb7c1b4c2..0b69e4ee8e312d8dd8e26489b706f83aa6851382 100644 (file)
@@ -18,7 +18,7 @@ Table of Contents
 
 1.0 Introduction
 
-  The file ../../drivers/media/video/c-qcam.c is a device driver for
+  The file ../../drivers/media/parport/c-qcam.c is a device driver for
 the Logitech (nee Connectix) parallel port interface color CCD camera.
 This is a fairly inexpensive device for capturing images.  Logitech
 does not currently provide information for developers, but many people
index 7a460b0685bb6cfe8d2f631de9ee7a24d9031401..dc9a297f49c3fb0551294b0b89e9b70e0446b1b9 100644 (file)
@@ -5,22 +5,22 @@
  File partitioning
  -----------------
  V4L2 display device driver
-         drivers/media/video/davinci/vpbe_display.c
-         drivers/media/video/davinci/vpbe_display.h
+         drivers/media/platform/davinci/vpbe_display.c
+         drivers/media/platform/davinci/vpbe_display.h
 
  VPBE display controller
-         drivers/media/video/davinci/vpbe.c
-         drivers/media/video/davinci/vpbe.h
+         drivers/media/platform/davinci/vpbe.c
+         drivers/media/platform/davinci/vpbe.h
 
  VPBE venc sub device driver
-         drivers/media/video/davinci/vpbe_venc.c
-         drivers/media/video/davinci/vpbe_venc.h
-         drivers/media/video/davinci/vpbe_venc_regs.h
+         drivers/media/platform/davinci/vpbe_venc.c
+         drivers/media/platform/davinci/vpbe_venc.h
+         drivers/media/platform/davinci/vpbe_venc_regs.h
 
  VPBE osd driver
-         drivers/media/video/davinci/vpbe_osd.c
-         drivers/media/video/davinci/vpbe_osd.h
-         drivers/media/video/davinci/vpbe_osd_regs.h
+         drivers/media/platform/davinci/vpbe_osd.c
+         drivers/media/platform/davinci/vpbe_osd.h
+         drivers/media/platform/davinci/vpbe_osd_regs.h
 
  Functional partitioning
  -----------------------
index eb049708f3e4b10b3464f6eb2f149651cd722893..fd02d9a4930a35bee8407b8fb701a617c7b93d5a 100644 (file)
@@ -10,7 +10,7 @@ data from LCD controller (FIMD) through the SoC internal writeback data
 path.  There are multiple FIMC instances in the SoCs (up to 4), having
 slightly different capabilities, like pixel alignment constraints, rotator
 availability, LCD writeback support, etc. The driver is located at
-drivers/media/video/s5p-fimc directory.
+drivers/media/platform/s5p-fimc directory.
 
 1. Supported SoCs
 =================
@@ -36,21 +36,21 @@ Not currently supported:
 =====================
 
 - media device driver
-  drivers/media/video/s5p-fimc/fimc-mdevice.[ch]
+  drivers/media/platform/s5p-fimc/fimc-mdevice.[ch]
 
  - camera capture video device driver
-  drivers/media/video/s5p-fimc/fimc-capture.c
+  drivers/media/platform/s5p-fimc/fimc-capture.c
 
  - MIPI-CSI2 receiver subdev
-  drivers/media/video/s5p-fimc/mipi-csis.[ch]
+  drivers/media/platform/s5p-fimc/mipi-csis.[ch]
 
  - video post-processor (mem-to-mem)
-  drivers/media/video/s5p-fimc/fimc-core.c
+  drivers/media/platform/s5p-fimc/fimc-core.c
 
  - common files
-  drivers/media/video/s5p-fimc/fimc-core.h
-  drivers/media/video/s5p-fimc/fimc-reg.h
-  drivers/media/video/s5p-fimc/regs-fimc.h
+  drivers/media/platform/s5p-fimc/fimc-core.h
+  drivers/media/platform/s5p-fimc/fimc-reg.h
+  drivers/media/platform/s5p-fimc/regs-fimc.h
 
 4. User space interfaces
 ========================
index 5dd1439b61fd512b94b3404f959e824ab3816f4d..b9a9f83b1587f40008b3201890f973205d743f80 100644 (file)
@@ -12,7 +12,7 @@ Introduction
 ============
 
 This file documents the Texas Instruments OMAP 3 Image Signal Processor (ISP)
-driver located under drivers/media/video/omap3isp. The original driver was
+driver located under drivers/media/platform/omap3isp. The original driver was
 written by Texas Instruments but since that it has been rewritten (twice) at
 Nokia.
 
index 43da22b8972869c7d283d751674d6633d7cd822d..cfe52c798d743b0979a31c414948a5c72c491e46 100644 (file)
@@ -136,11 +136,25 @@ Or alternatively for integer menu controls, by calling v4l2_ctrl_new_int_menu:
                        const struct v4l2_ctrl_ops *ops,
                        u32 id, s32 max, s32 def, const s64 *qmenu_int);
 
+Standard menu controls with a driver specific menu are added by calling
+v4l2_ctrl_new_std_menu_items:
+
+       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 skip_mask, s32 def, const char * const *qmenu);
+
 These functions are typically called right after the v4l2_ctrl_handler_init:
 
        static const s64 exp_bias_qmenu[] = {
               -2, -1, 0, 1, 2
        };
+       static const char * const test_pattern[] = {
+               "Disabled",
+               "Vertical Bars",
+               "Solid Black",
+               "Solid White",
+       };
 
        v4l2_ctrl_handler_init(&foo->ctrl_handler, nr_of_controls);
        v4l2_ctrl_new_std(&foo->ctrl_handler, &foo_ctrl_ops,
@@ -156,6 +170,9 @@ These functions are typically called right after the v4l2_ctrl_handler_init:
                        ARRAY_SIZE(exp_bias_qmenu) - 1,
                        ARRAY_SIZE(exp_bias_qmenu) / 2 - 1,
                        exp_bias_qmenu);
+       v4l2_ctrl_new_std_menu_items(&foo->ctrl_handler, &foo_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN, ARRAY_SIZE(test_pattern) - 1, 0,
+                       0, test_pattern);
        ...
        if (foo->ctrl_handler.error) {
                int err = foo->ctrl_handler.error;
@@ -185,6 +202,13 @@ v4l2_ctrl_new_std_menu in that it doesn't have the mask argument and takes
 as the last argument an array of signed 64-bit integers that form an exact
 menu item list.
 
+The v4l2_ctrl_new_std_menu_items function is very similar to
+v4l2_ctrl_new_std_menu but takes an extra parameter qmenu, which is the driver
+specific menu for an otherwise standard menu control. A good example for this
+control is the test pattern control for capture/display/sensors devices that
+have the capability to generate test patterns. These test patterns are hardware
+specific, so the contents of the menu will vary from device to device.
+
 Note that if something fails, the function will return NULL or an error and
 set ctrl_handler->error to the error code. If ctrl_handler->error was already
 set, then it will just return and do nothing. This is also true for
@@ -594,7 +618,11 @@ handler and finally add the first handler to the second. For example:
        v4l2_ctrl_new_std(&radio_ctrl_handler, &radio_ops, V4L2_CID_AUDIO_MUTE, ...);
        v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_BRIGHTNESS, ...);
        v4l2_ctrl_new_std(&video_ctrl_handler, &video_ops, V4L2_CID_CONTRAST, ...);
-       v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler);
+       v4l2_ctrl_add_handler(&video_ctrl_handler, &radio_ctrl_handler, NULL);
+
+The last argument to v4l2_ctrl_add_handler() is a filter function that allows
+you to filter which controls will be added. Set it to NULL if you want to add
+all controls.
 
 Or you can add specific controls to a handler:
 
index 89318be6c1d2117581b0dfbb5fc478370c8e0f5a..32bfe926e8d77717e67a9e485ca89b398f5c26a8 100644 (file)
@@ -583,11 +583,19 @@ You should also set these fields:
 
 - name: set to something descriptive and unique.
 
+- vfl_dir: set this to VFL_DIR_RX for capture devices (VFL_DIR_RX has value 0,
+  so this is normally already the default), set to VFL_DIR_TX for output
+  devices and VFL_DIR_M2M for mem2mem (codec) devices.
+
 - fops: set to the v4l2_file_operations struct.
 
 - ioctl_ops: if you use the v4l2_ioctl_ops to simplify ioctl maintenance
   (highly recommended to use this and it might become compulsory in the
-  future!), then set this to your v4l2_ioctl_ops struct.
+  future!), then set this to your v4l2_ioctl_ops struct. The vfl_type and
+  vfl_dir fields are used to disable ops that do not match the type/dir
+  combination. E.g. VBI ops are disabled for non-VBI nodes, and output ops
+  are disabled for a capture device. This makes it possible to provide
+  just one v4l2_ioctl_ops struct for both vbi and video nodes.
 
 - lock: leave to NULL if you want to do all the locking in the driver.
   Otherwise you give it a pointer to a struct mutex_lock and before the
@@ -1054,4 +1062,4 @@ The first event type in the class is reserved for future use, so the first
 available event type is 'class base + 1'.
 
 An example on how the V4L2 events may be used can be found in the OMAP
-3 ISP driver (drivers/media/video/omap3isp).
+3 ISP driver (drivers/media/platform/omap3isp).
index 1d00d7f15b8f730ee4de10ca2f9f28d5a529eadc..3ffe9e960b6f65e1be78e2480573389f1d940f6c 100644 (file)
@@ -349,7 +349,7 @@ again.
 Developers who are interested in more information can go into the relevant
 header files; there are a few low-level functions declared there which have
 not been talked about here.  Also worthwhile is the vivi driver
-(drivers/media/video/vivi.c), which is maintained as an example of how V4L2
+(drivers/media/platform/vivi.c), which is maintained as an example of how V4L2
 drivers should be written.  Vivi only uses the vmalloc() API, but it's good
 enough to get started with.  Note also that all of these calls are exported
 GPL-only, so they will not be available to non-GPL kernel modules.
index 73ff5cc93e05db4c93321464cb8ae948571a18fe..3da822967ee0e13d1a2dbcd88d2d75f5a4aca370 100644 (file)
@@ -31,7 +31,7 @@ static void keep_alive(void)
  * or "-e" to enable the card.
  */
 
-void term(int sig)
+static void term(int sig)
 {
     close(fd);
     fprintf(stderr, "Stopping watchdog ticks...\n");
index fdc0119963e70f12c4f9e1eae3a613447e7d8781..a21df13ffbcdffa098ff3afb7fa33fe63459711a 100644 (file)
@@ -184,6 +184,16 @@ S: Maintained
 F:     Documentation/filesystems/9p.txt
 F:     fs/9p/
 
+A8293 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/dvb-frontends/a8293*
+
 AACRAID SCSI RAID DRIVER
 M:     Adaptec OEM Raid Solutions <aacraid@adaptec.com>
 L:     linux-scsi@vger.kernel.org
@@ -391,6 +401,26 @@ M: Riccardo Facchetti <fizban@tin.it>
 S:     Maintained
 F:     sound/oss/aedsp16.c
 
+AF9013 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/dvb-frontends/af9013*
+
+AF9033 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/dvb-frontends/af9033*
+
 AFFS FILE SYSTEM
 L:     linux-fsdevel@vger.kernel.org
 S:     Orphan
@@ -1073,7 +1103,7 @@ L:        linux-media@vger.kernel.org
 S:     Maintained
 F:     arch/arm/plat-s5p/dev-fimc*
 F:     arch/arm/plat-samsung/include/plat/*fimc*
-F:     drivers/media/video/s5p-fimc/
+F:     drivers/media/platform/s5p-fimc/
 
 ARM/SAMSUNG S5P SERIES Multi Format Codec (MFC) SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -1083,7 +1113,7 @@ L:        linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
 F:     arch/arm/plat-s5p/dev-mfc.c
-F:     drivers/media/video/s5p-mfc/
+F:     drivers/media/platform/s5p-mfc/
 
 ARM/SAMSUNG S5P SERIES TV SUBSYSTEM SUPPORT
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -1091,7 +1121,7 @@ M:        Tomasz Stanislawski <t.stanislaws@samsung.com>
 L:     linux-arm-kernel@lists.infradead.org
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/video/s5p-tv/
+F:     drivers/media/platform/s5p-tv/
 
 ARM/SHMOBILE ARM ARCHITECTURE
 M:     Paul Mundt <lethal@linux-sh.org>
@@ -1357,7 +1387,7 @@ ATMEL ISI DRIVER
 M:     Josh Wu <josh.wu@atmel.com>
 L:     linux-media@vger.kernel.org
 S:     Supported
-F:     drivers/media/video/atmel-isi.c
+F:     drivers/media/platform/atmel-isi.c
 F:     include/media/atmel-isi.h
 
 ATMEL LCDFB DRIVER
@@ -1695,7 +1725,7 @@ W:        http://linuxtv.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
 F:     Documentation/video4linux/bttv/
-F:     drivers/media/video/bt8xx/bttv*
+F:     drivers/media/pci/bt8xx/bttv*
 
 C-MEDIA CMI8788 DRIVER
 M:     Clemens Ladisch <clemens@ladisch.de>
@@ -1725,7 +1755,7 @@ L:        linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
 F:     Documentation/video4linux/cafe_ccic
-F:     drivers/media/video/marvell-ccic/
+F:     drivers/media/platform/marvell-ccic/
 
 CAIF NETWORK LAYER
 M:     Sjur Braendeland <sjur.brandeland@stericsson.com>
@@ -2114,7 +2144,17 @@ W:       http://linuxtv.org
 W:     http://www.ivtvdriver.org/index.php/Cx18
 S:     Maintained
 F:     Documentation/video4linux/cx18.txt
-F:     drivers/media/video/cx18/
+F:     drivers/media/pci/cx18/
+
+CXD2820R 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/dvb-frontends/cxd2820r*
 
 CXGB3 ETHERNET DRIVER (CXGB3)
 M:     Divy Le Ray <divy@chelsio.com>
@@ -2469,6 +2509,117 @@ L:      netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/wan/dscc4.c
 
+DVB_USB_AF9015 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/dvb-usb-v2/af9015*
+
+DVB_USB_AF9035 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/dvb-usb-v2/af9035*
+
+DVB_USB_ANYSEE 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/dvb-usb-v2/anysee*
+
+DVB_USB_AU6610 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/dvb-usb-v2/au6610*
+
+DVB_USB_CE6230 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/dvb-usb-v2/ce6230*
+
+DVB_USB_CXUSB MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/media_tree.git
+S:     Maintained
+F:     drivers/media/usb/dvb-usb-v2/cxusb*
+
+DVB_USB_CYPRESS_FIRMWARE 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/dvb-usb-v2/cypress_firmware*
+
+DVB_USB_EC168 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/dvb-usb-v2/ec168*
+
+DVB_USB_MXL111SF MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/mxl111sf.git
+S:     Maintained
+F:     drivers/media/usb/dvb-usb-v2/mxl111sf*
+
+DVB_USB_RTL28XXU 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/dvb-usb-v2/rtl28xxu*
+
+DVB_USB_V2 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/dvb-usb-v2/dvb_usb*
+F:     drivers/media/usb/dvb-usb-v2/usb_urb.c
+
 DYNAMIC DEBUG
 M:     Jason Baron <jbaron@redhat.com>
 S:     Maintained
@@ -2480,6 +2631,16 @@ M:       "Maciej W. Rozycki" <macro@linux-mips.org>
 S:     Maintained
 F:     drivers/tty/serial/dz.*
 
+E4000 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/tuners/e4000*
+
 EATA-DMA SCSI DRIVER
 M:     Michael Neuffer <mike@i-Connect.Net>
 L:     linux-eata@i-connect.net
@@ -2508,6 +2669,16 @@ S:       Maintained
 F:     include/linux/netfilter_bridge/ebt_*.h
 F:     net/bridge/netfilter/ebt*.c
 
+EC100 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/dvb-frontends/ec100*
+
 ECRYPT FILE SYSTEM
 M:     Tyler Hicks <tyhicks@canonical.com>
 M:     Dustin Kirkland <dustin.kirkland@gazzang.com>
@@ -2778,8 +2949,18 @@ FC0011 TUNER DRIVER
 M:     Michael Buesch <m@bues.ch>
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/common/tuners/fc0011.h
-F:     drivers/media/common/tuners/fc0011.c
+F:     drivers/media/tuners/fc0011.h
+F:     drivers/media/tuners/fc0011.c
+
+FC2580 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/tuners/fc2580*
 
 FANOTIFY
 M:     Eric Paris <eparis@redhat.com>
@@ -3007,7 +3188,7 @@ M:        Kyungmin Park <kyungmin.park@samsung.com>
 M:     Heungjun Kim <riverful.kim@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/video/m5mols/
+F:     drivers/media/i2c/m5mols/
 F:     include/media/m5mols.h
 
 FUJITSU TABLET EXTRAS
@@ -3124,49 +3305,56 @@ M:      Frank Zago <frank@zago.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/finepix.c
+F:     drivers/media/usb/gspca/finepix.c
 
 GSPCA GL860 SUBDRIVER
 M:     Olivier Lorin <o.lorin@laposte.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/gl860/
+F:     drivers/media/usb/gspca/gl860/
 
 GSPCA M5602 SUBDRIVER
 M:     Erik Andren <erik.andren@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/m5602/
+F:     drivers/media/usb/gspca/m5602/
 
 GSPCA PAC207 SONIXB SUBDRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/pac207.c
+F:     drivers/media/usb/gspca/pac207.c
 
 GSPCA SN9C20X SUBDRIVER
 M:     Brian Johnson <brijohn@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/sn9c20x.c
+F:     drivers/media/usb/gspca/sn9c20x.c
 
 GSPCA T613 SUBDRIVER
 M:     Leandro Costantino <lcostantino@gmail.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/t613.c
+F:     drivers/media/usb/gspca/t613.c
 
 GSPCA USB WEBCAM DRIVER
 M:     Hans de Goede <hdegoede@redhat.com>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/gspca/
+F:     drivers/media/usb/gspca/
+
+STK1160 USB VIDEO CAPTURE DRIVER
+M:     Ezequiel Garcia <elezegarcia@gmail.com>
+L:     linux-media@vger.kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
+S:     Maintained
+F:     drivers/media/usb/stk1160/
 
 HARD DRIVE ACTIVE PROTECTION SYSTEM (HDAPS) DRIVER
 M:     Frank Seidel <frank@f-seidel.de>
@@ -3220,6 +3408,16 @@ L:       linux-parisc@vger.kernel.org
 S:     Maintained
 F:     sound/parisc/harmony.*
 
+HD29L2 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/dvb-frontends/hd29l2*
+
 HEWLETT-PACKARD SMART2 RAID DRIVER
 M:     Chirag Kantharia <chirag.kantharia@hp.com>
 L:     iss_storagedev@hp.com
@@ -3388,7 +3586,7 @@ M:        "Wolfram Sang (embedded platforms)" <w.sang@pengutronix.de>
 L:     linux-i2c@vger.kernel.org
 W:     http://i2c.wiki.kernel.org/
 T:     quilt kernel.org/pub/linux/kernel/people/jdelvare/linux-2.6/jdelvare-i2c/
-T:     git git://git.fluff.org/bjdooks/linux.git
+T:     git git://git.pengutronix.de/git/wsa/linux.git
 S:     Maintained
 F:     Documentation/i2c/
 F:     drivers/i2c/
@@ -3552,11 +3750,12 @@ K:      \b(ABS|SYN)_MT_
 
 INTEL C600 SERIES SAS CONTROLLER DRIVER
 M:     Intel SCU Linux support <intel-linux-scu@intel.com>
+M:     Lukasz Dorau <lukasz.dorau@intel.com>
+M:     Maciej Patelczyk <maciej.patelczyk@intel.com>
 M:     Dave Jiang <dave.jiang@intel.com>
-M:     Ed Nadolski <edmund.nadolski@intel.com>
 L:     linux-scsi@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/djbw/isci.git
-S:     Maintained
+T:     git git://git.code.sf.net/p/intel-sas/isci
+S:     Supported
 F:     drivers/scsi/isci/
 F:     firmware/isci/
 
@@ -3666,11 +3865,12 @@ F:      Documentation/networking/README.ipw2200
 F:     drivers/net/wireless/ipw2x00/
 
 INTEL(R) TRUSTED EXECUTION TECHNOLOGY (TXT)
-M:     Joseph Cihula <joseph.cihula@intel.com>
+M:     Richard L Maliszewski <richard.l.maliszewski@intel.com>
+M:     Gang Wei <gang.wei@intel.com>
 M:     Shane Wang <shane.wang@intel.com>
 L:     tboot-devel@lists.sourceforge.net
 W:     http://tboot.sourceforge.net
-T:     Mercurial http://www.bughost.org/repos.hg/tboot.hg
+T:     hg http://tboot.hg.sourceforge.net:8000/hgroot/tboot/tboot
 S:     Supported
 F:     Documentation/intel_txt.txt
 F:     include/linux/tboot.h
@@ -3865,7 +4065,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.ivtvdriver.org
 S:     Maintained
 F:     Documentation/video4linux/*.ivtv
-F:     drivers/media/video/ivtv/
+F:     drivers/media/pci/ivtv/
 F:     include/linux/ivtv*
 
 JC42.4 TEMPERATURE SENSOR DRIVER
@@ -4159,6 +4359,26 @@ W:       http://legousb.sourceforge.net/
 S:     Maintained
 F:     drivers/usb/misc/legousbtower.c
 
+LG2160 MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/dvb-frontends/lg2160.*
+
+LGDT3305 MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/dvb-frontends/lgdt3305.*
+
 LGUEST
 M:     Rusty Russell <rusty@rustcorp.com.au>
 L:     lguest@lists.ozlabs.org
@@ -4561,7 +4781,7 @@ MOTION EYE VAIO PICTUREBOOK CAMERA DRIVER
 W:     http://popies.net/meye/
 S:     Orphan
 F:     Documentation/video4linux/meye.txt
-F:     drivers/media/video/meye.*
+F:     drivers/media/pci/meye/
 F:     include/linux/meye.h
 
 MOTOROLA IMX MMC/SD HOST CONTROLLER INTERFACE DRIVER
@@ -4625,6 +4845,16 @@ T:       git git://git.kernel.org/pub/scm/linux/kernel/git/balbi/usb.git
 S:     Maintained
 F:     drivers/usb/musb/
 
+MXL5007T MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/tuners/mxl5007t.*
+
 MYRICOM MYRI-10G 10GbE DRIVER (MYRI10GE)
 M:     Andrew Gallatin <gallatin@myri.com>
 L:     netdev@vger.kernel.org
@@ -4964,7 +5194,7 @@ OMAP IMAGE SIGNAL PROCESSOR (ISP)
 M:     Laurent Pinchart <laurent.pinchart@ideasonboard.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/video/omap3isp/*
+F:     drivers/media/platform/omap3isp/
 
 OMAP USB SUPPORT
 M:     Felipe Balbi <balbi@ti.com>
@@ -5005,7 +5235,7 @@ M:        Jonathan Corbet <corbet@lwn.net>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     drivers/media/video/ov7670.c
+F:     drivers/media/i2c/ov7670.c
 
 ONENAND FLASH DRIVER
 M:     Kyungmin Park <kyungmin.park@samsung.com>
@@ -5530,7 +5760,7 @@ W:        http://www.isely.net/pvrusb2/
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
 F:     Documentation/video4linux/README.pvrusb2
-F:     drivers/media/video/pvrusb2/
+F:     drivers/media/usb/pvrusb2/
 
 PWM SUBSYSTEM
 M:     Thierry Reding <thierry.reding@avionic-design.de>
@@ -5543,6 +5773,8 @@ F:        Documentation/devicetree/bindings/pwm/
 F:     include/linux/pwm.h
 F:     include/linux/of_pwm.h
 F:     drivers/pwm/
+F:     drivers/video/backlight/pwm_bl.c
+F:     include/linux/pwm_backlight.h
 
 PXA2xx/PXA3xx SUPPORT
 M:     Eric Miao <eric.y.miao@gmail.com>
@@ -5638,6 +5870,16 @@ F:       fs/qnx4/
 F:     include/linux/qnx4_fs.h
 F:     include/linux/qnxtypes.h
 
+QT1010 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/tuners/qt1010*
+
 QUALCOMM HEXAGON ARCHITECTURE
 M:     Richard Kuo <rkuo@codeaurora.org>
 L:     linux-hexagon@vger.kernel.org
@@ -5804,6 +6046,16 @@ F:       include/linux/rose.h
 F:     include/net/rose.h
 F:     net/rose/
 
+RTL2830 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/dvb-frontends/rtl2830*
+
 RTL8180 WIRELESS DRIVER
 M:     "John W. Linville" <linville@tuxdriver.com>
 L:     linux-wireless@vger.kernel.org
@@ -5898,9 +6150,9 @@ L:        linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.mihu.de/linux/saa7146
 S:     Maintained
-F:     drivers/media/common/saa7146*
-F:     drivers/media/video/*7146*
-F:     include/media/*7146*
+F:     drivers/media/common/saa7146/
+F:     drivers/media/pci/saa7146/
+F:     include/media/saa7146*
 
 SAMSUNG LAPTOP DRIVER
 M:     Corentin Chary <corentincj@iksaif.net>
@@ -5961,7 +6213,7 @@ M:        Huang Shijie <shijie8@gmail.com>
 M:     Kang Yong <kangyong@telegent.com>
 M:     Zhang Xiaobing <xbzhang@telegent.com>
 S:     Supported
-F:     drivers/media/video/tlg2300
+F:     drivers/media/usb/tlg2300
 
 SC1200 WDT DRIVER
 M:     Zwane Mwaikambo <zwane@arm.linux.org.uk>
@@ -6349,8 +6601,9 @@ M:        Guennadi Liakhovetski <g.liakhovetski@gmx.de>
 L:     linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 S:     Maintained
-F:     include/media/v4l2*
-F:     drivers/media/video/v4l2*
+F:     include/media/soc*
+F:     drivers/media/i2c/soc_camera/
+F:     drivers/media/platform/soc_camera/
 
 SOEKRIS NET48XX LED SUPPORT
 M:     Chris Boot <bootc@bootc.net>
@@ -6768,6 +7021,66 @@ W:       http://tcp-lp-mod.sourceforge.net/
 S:     Maintained
 F:     net/ipv4/tcp_lp.c
 
+TDA10071 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/dvb-frontends/tda10071*
+
+TDA18212 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/tuners/tda18212*
+
+TDA18218 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/tuners/tda18218*
+
+TDA18271 MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/tuners/tda18271*
+
+TDA827x MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/tuners/tda8290.*
+
+TDA8290 MEDIA DRIVER
+M:     Michael Krufky <mkrufky@linuxtv.org>
+L:     linux-media@vger.kernel.org
+W:     http://linuxtv.org/
+W:     http://github.com/mkrufky
+Q:     http://patchwork.linuxtv.org/project/linux-media/list/
+T:     git git://linuxtv.org/mkrufky/tuners.git
+S:     Maintained
+F:     drivers/media/tuners/tda8290.*
+
 TEAM DRIVER
 M:     Jiri Pirko <jpirko@redhat.com>
 L:     netdev@vger.kernel.org
@@ -6958,6 +7271,16 @@ F:       include/linux/serial_core.h
 F:     include/linux/serial.h
 F:     include/linux/tty.h
 
+TUA9001 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/tuners/tua9001*
+
 TULIP NETWORK DRIVERS
 M:     Grant Grundler <grundler@parisc-linux.org>
 L:     netdev@vger.kernel.org
@@ -7130,15 +7453,6 @@ S:       Maintained
 F:     Documentation/usb/ehci.txt
 F:     drivers/usb/host/ehci*
 
-USB ET61X[12]51 DRIVER
-M:     Luca Risolia <luca.risolia@studio.unibo.it>
-L:     linux-usb@vger.kernel.org
-L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-W:     http://www.linux-projects.org
-S:     Maintained
-F:     drivers/media/video/et61x251/
-
 USB GADGET/PERIPHERAL SUBSYSTEM
 M:     Felipe Balbi <balbi@ti.com>
 L:     linux-usb@vger.kernel.org
@@ -7308,7 +7622,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.linux-projects.org
 S:     Maintained
 F:     Documentation/video4linux/sn9c102.txt
-F:     drivers/media/video/sn9c102/
+F:     drivers/media/usb/sn9c102/
 
 USB SUBSYSTEM
 M:     Greg Kroah-Hartman <gregkh@linuxfoundation.org>
@@ -7343,17 +7657,7 @@ L:       linux-media@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://www.ideasonboard.org/uvc/
 S:     Maintained
-F:     drivers/media/video/uvc/
-
-USB W996[87]CF DRIVER
-M:     Luca Risolia <luca.risolia@studio.unibo.it>
-L:     linux-usb@vger.kernel.org
-L:     linux-media@vger.kernel.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
-W:     http://www.linux-projects.org
-S:     Maintained
-F:     Documentation/video4linux/w9968cf.txt
-F:     drivers/media/video/w996*
+F:     drivers/media/usb/uvc/
 
 USB WIRELESS RNDIS DRIVER (rndis_wlan)
 M:     Jussi Kivilinna <jussi.kivilinna@mbnet.fi>
@@ -7382,7 +7686,7 @@ T:        git git://git.kernel.org/pub/scm/linux/kernel/git/mchehab/linux-media.git
 W:     http://royale.zerezo.com/zr364xx/
 S:     Maintained
 F:     Documentation/video4linux/zr364xx.txt
-F:     drivers/media/video/zr364xx.c
+F:     drivers/media/usb/zr364xx/
 
 USER-MODE LINUX (UML)
 M:     Jeff Dike <jdike@addtoit.com>
@@ -7440,7 +7744,7 @@ M:        Marek Szyprowski <m.szyprowski@samsung.com>
 M:     Kyungmin Park <kyungmin.park@samsung.com>
 L:     linux-media@vger.kernel.org
 S:     Maintained
-F:     drivers/media/video/videobuf2-*
+F:     drivers/media/v4l2-core/videobuf2-*
 F:     include/media/videobuf2-*
 
 VIRTIO CONSOLE DRIVER
@@ -7842,7 +8146,7 @@ L:        linux-media@vger.kernel.org
 W:     http://mjpeg.sourceforge.net/driver-zoran/
 T:     Mercurial http://linuxtv.org/hg/v4l-dvb
 S:     Odd Fixes
-F:     drivers/media/video/zoran/
+F:     drivers/media/pci/zoran/
 
 ZS DECSTATION Z85C30 SERIAL DRIVER
 M:     "Maciej W. Rozycki" <macro@linux-mips.org>
index 354026873b13329e5add40f1863903ffc2fba9dc..bb9fff26f078063c395fe8f86488349614c84261 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,8 +1,8 @@
 VERSION = 3
 PATCHLEVEL = 6
 SUBLEVEL = 0
-EXTRAVERSION = -rc3
-NAME = Saber-toothed Squirrel
+EXTRAVERSION =
+NAME = Terrified Chipmunk
 
 # *DOCUMENTATION*
 # To see a list of typical targets execute "make help"
index 6d6e18fee9fe08bacf876e749837d4b0156a5fd9..2f88d8d9770116014f7ff55e80d98c65fbb191ed 100644 (file)
@@ -6,7 +6,7 @@ config ARM
        select HAVE_DMA_API_DEBUG
        select HAVE_IDE if PCI || ISA || PCMCIA
        select HAVE_DMA_ATTRS
-       select HAVE_DMA_CONTIGUOUS if (CPU_V6 || CPU_V6K || CPU_V7)
+       select HAVE_DMA_CONTIGUOUS if MMU
        select HAVE_MEMBLOCK
        select RTC_LIB
        select SYS_SUPPORTS_APM_EMULATION
@@ -2144,6 +2144,7 @@ source "drivers/cpufreq/Kconfig"
 config CPU_FREQ_IMX
        tristate "CPUfreq driver for i.MX CPUs"
        depends on ARCH_MXC && CPU_FREQ
+       select CPU_FREQ_TABLE
        help
          This enables the CPUfreq driver for i.MX CPUs.
 
index f15f82bf3a50f808005af479ff9c334f100c1044..e968a52e4881967a01f8aa68fc586aafe61edf38 100644 (file)
@@ -356,15 +356,15 @@ choice
                  is nothing connected to read from the DCC.
 
        config DEBUG_SEMIHOSTING
-               bool "Kernel low-level debug output via semihosting I"
+               bool "Kernel low-level debug output via semihosting I/O"
                help
                  Semihosting enables code running on an ARM target to use
                  the I/O facilities on a host debugger/emulator through a
-                 simple SVC calls. The host debugger or emulator must have
+                 simple SVC call. The host debugger or emulator must have
                  semihosting enabled for the special svc call to be trapped
                  otherwise the kernel will crash.
 
-                 This is known to work with OpenOCD, as wellas
+                 This is known to work with OpenOCD, as well as
                  ARM's Fast Models, or any other controlling environment
                  that implements semihosting.
 
index 30eae87ead6d4b245bc6707040645f5182464e90..a051dfbdd7db07fb12db913d85050a5bb0ea7167 100644 (file)
@@ -284,10 +284,10 @@ zImage Image xipImage bootpImage uImage: vmlinux
 zinstall uinstall install: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $@
 
-%.dtb:
+%.dtb: scripts
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
-dtbs:
+dtbs: scripts
        $(Q)$(MAKE) $(build)=$(boot) MACHINE=$(MACHINE) $(boot)/$@
 
 # We use MRPROPER_FILES and CLEAN_FILES now
index b8c64b80bafc848032dfff366a9ac4428a7f82b5..bc67cbff39448ff84a3f0c14cd22876975ee1965 100644 (file)
@@ -653,16 +653,21 @@ __armv7_mmu_cache_on:
                mcrne   p15, 0, r0, c8, c7, 0   @ flush I,D TLBs
 #endif
                mrc     p15, 0, r0, c1, c0, 0   @ read control reg
+               bic     r0, r0, #1 << 28        @ clear SCTLR.TRE
                orr     r0, r0, #0x5000         @ I-cache enable, RR cache replacement
                orr     r0, r0, #0x003c         @ write buffer
 #ifdef CONFIG_MMU
 #ifdef CONFIG_CPU_ENDIAN_BE8
                orr     r0, r0, #1 << 25        @ big-endian page tables
 #endif
+               mrcne   p15, 0, r6, c2, c0, 2   @ read ttb control reg
                orrne   r0, r0, #1              @ MMU enabled
                movne   r1, #0xfffffffd         @ domain 0 = client
+               bic     r6, r6, #1 << 31        @ 32-bit translation system
+               bic     r6, r6, #3 << 0         @ use only ttbr0
                mcrne   p15, 0, r3, c2, c0, 0   @ load page table pointer
                mcrne   p15, 0, r1, c3, c0, 0   @ load domain access control
+               mcrne   p15, 0, r6, c2, c0, 2   @ load ttb control
 #endif
                mcr     p15, 0, r0, c7, c5, 4   @ ISB
                mcr     p15, 0, r0, c1, c0, 0   @ load control register
index 59509c48d7e5a5c2474f73ac028f73537e0a6659..bd0cff3f808c7c5be55ce79dd31b343d37e6297a 100644 (file)
                        #size-cells = <0>;
                        ti,hwmods = "i2c3";
                };
+
+               wdt2: wdt@44e35000 {
+                       compatible = "ti,omap3-wdt";
+                       ti,hwmods = "wd_timer2";
+               };
        };
 };
index 66389c1c6f6297e50c8ae3b944d7311dcbb26b6c..7c95f76398de401ac166af8f32d4a34a6b918e79 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index b460d6ce9eb592da5191871b40b2d3433156bcef..195019b7ca0e046073361a587862c885c8fbfb7e 100644 (file)
@@ -95,6 +95,7 @@
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff400 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioE: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@ffffee00 {
index 7829a4d0cb22e2b4c010def2ca689e46c7682044..96514c134e54bafd1540c5f55524411b09f1e7a8 100644 (file)
@@ -15,7 +15,7 @@
        compatible = "atmel,at91sam9g25ek", "atmel,at91sam9x5ek", "atmel,at91sam9x5", "atmel,at91sam9";
 
        chosen {
-               bootargs = "128M console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
+               bootargs = "console=ttyS0,115200 root=/dev/mtdblock1 rw rootfstype=ubifs ubi.mtd=1 root=ubi0:rootfs";
        };
 
        ahb {
index bafa8806fc17293e3bddc28aff5b4829f677c178..63751b1e744b42611f8e74d17738ccd69dd1efe1 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff400 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioE: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@ffffee00 {
index bfac0dfc332c7d10bc3fe2f87458ec728c48b885..ef9336ae9614f85ffb0ce2348b69fc06b0f756e5 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index 4a18c393b1360f490c9796f3c598d349338ed2f5..8a387a8d61b745fc763c9e13f015896bc3e2bff7 100644 (file)
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioB: gpio@fffff600 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioC: gpio@fffff800 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        pioD: gpio@fffffa00 {
                                #gpio-cells = <2>;
                                gpio-controller;
                                interrupt-controller;
+                               #interrupt-cells = <2>;
                        };
 
                        dbgu: serial@fffff200 {
index cd86177a3ea21aa1dbe3d0dcea633b50661e5552..59d9789e550898cc041e6670ca0430776b204c2b 100644 (file)
@@ -25,8 +25,8 @@
                aips@70000000 { /* aips-1 */
                        spba@70000000 {
                                esdhc@70004000 { /* ESDHC1 */
-                                       fsl,cd-internal;
-                                       fsl,wp-internal;
+                                       fsl,cd-controller;
+                                       fsl,wp-controller;
                                        status = "okay";
                                };
 
index 52d9470451069f5445661c79ffa902a7cc49eee1..f8ca6fa88192a5d36edb0c484a7a13c7c11e6e7c 100644 (file)
                };
                power-blue {
                        label = "power:blue";
-                       gpios = <&gpio1 11 0>;
+                       gpios = <&gpio1 10 0>;
                        linux,default-trigger = "timer";
                };
+               power-red {
+                       label = "power:red";
+                       gpios = <&gpio1 11 0>;
+               };
                usb1 {
                        label = "usb1:blue";
                        gpios = <&gpio1 12 0>;
index 3b2f3510d7eb91ca5ce520692682ad26aca89d31..d351b27d7213f65c50680e50965d41cdfd4218f2 100644 (file)
@@ -66,6 +66,7 @@
 
        vcxio: regulator@8 {
                compatible = "ti,twl6030-vcxio";
+               regulator-always-on;
        };
 
        vusb: regulator@9 {
 
        v1v8: regulator@10 {
                compatible = "ti,twl6030-v1v8";
+               regulator-always-on;
        };
 
        v2v1: regulator@11 {
                compatible = "ti,twl6030-v2v1";
+               regulator-always-on;
        };
 
        clk32kg: regulator@12 {
index 7d8718468e0dff1ec28b63014f6c56ec62650d10..90610c7030f7aafd4ccc9663983bc367e89324dd 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_AEABI=y
 CONFIG_FORCE_MAX_ZONEORDER=13
 CONFIG_ZBOOT_ROM_TEXT=0x0
 CONFIG_ZBOOT_ROM_BSS=0x0
-CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096"
+CONFIG_CMDLINE="console=tty0 console=ttySC1,115200 earlyprintk=sh-sci.1,115200 ignore_loglevel root=/dev/nfs ip=dhcp nfsroot=,rsize=4096,wsize=4096 rw"
 CONFIG_CMDLINE_FORCE=y
 CONFIG_KEXEC=y
 CONFIG_VFP=y
index 2d4f661d1cf6e757739429a4ba7730ea7be14eeb..da6845493caabae29842d959f0b80bdcc1bd7790 100644 (file)
@@ -86,6 +86,7 @@ CONFIG_NEW_LEDS=y
 CONFIG_LEDS_CLASS=y
 CONFIG_LEDS_LM3530=y
 CONFIG_LEDS_LP5521=y
+CONFIG_LEDS_GPIO=y
 CONFIG_RTC_CLASS=y
 CONFIG_RTC_DRV_AB8500=y
 CONFIG_RTC_DRV_PL031=y
index 03fb93621d0d6046b7b416c9c4328437380fd843..5c8b3bf4d8252f1013af6fea25848ce9c41dcfeb 100644 (file)
        .size \name , . - \name
        .endm
 
+       .macro check_uaccess, addr:req, size:req, limit:req, tmp:req, bad:req
+#ifndef CONFIG_CPU_USE_DOMAINS
+       adds    \tmp, \addr, #\size - 1
+       sbcccs  \tmp, \tmp, \limit
+       bcs     \bad
+#endif
+       .endm
+
 #endif /* __ASM_ASSEMBLER_H__ */
index 2ae842df455180d3bcd445d339ecd332d3b36c4e..5c44dcb0987bd31418298f7932baaa5a82320477 100644 (file)
@@ -202,6 +202,13 @@ static inline void dma_free_writecombine(struct device *dev, size_t size,
        return dma_free_attrs(dev, size, cpu_addr, dma_handle, &attrs);
 }
 
+/*
+ * This can be called during early boot to increase the size of the atomic
+ * coherent DMA pool above the default value of 256KiB. It must be called
+ * before postcore_initcall.
+ */
+extern void __init init_dma_coherent_pool_size(unsigned long size);
+
 /*
  * This can be called during boot to increase the size of the consistent
  * DMA region above it's default value of 2MB. It must be called before the
index e965f1b560f11e3a504814183c98f8f1b11bbf25..5f6ddcc56452998f40b1c16d7e20a0ff1ec010bd 100644 (file)
@@ -187,6 +187,7 @@ static inline unsigned long __phys_to_virt(unsigned long x)
 #define __phys_to_virt(x)      ((x) - PHYS_OFFSET + PAGE_OFFSET)
 #endif
 #endif
+#endif /* __ASSEMBLY__ */
 
 #ifndef PHYS_OFFSET
 #ifdef PLAT_PHYS_OFFSET
@@ -196,6 +197,8 @@ static inline unsigned long __phys_to_virt(unsigned long x)
 #endif
 #endif
 
+#ifndef __ASSEMBLY__
+
 /*
  * PFNs are used to describe any physical page; this means
  * PFN 0 == physical address 0.
index 314d4664eae7d9976a5fe656f74918cb8d15ab8b..99a19512ee26e2e5d99135d21f10d8b99e606226 100644 (file)
@@ -199,6 +199,9 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
 {
        pgtable_page_dtor(pte);
 
+#ifdef CONFIG_ARM_LPAE
+       tlb_add_flush(tlb, addr);
+#else
        /*
         * With the classic ARM MMU, a pte page has two corresponding pmd
         * entries, each covering 1MB.
@@ -206,6 +209,7 @@ static inline void __pte_free_tlb(struct mmu_gather *tlb, pgtable_t pte,
        addr &= PMD_MASK;
        tlb_add_flush(tlb, addr + SZ_1M - PAGE_SIZE);
        tlb_add_flush(tlb, addr + SZ_1M);
+#endif
 
        tlb_remove_page(tlb, pte);
 }
index 479a6352e0b5075911e91a4e0b60b7e9443fd4fd..77bd79f2ffdbd0344d096ca7fb2db809fb52d387 100644 (file)
@@ -101,28 +101,39 @@ extern int __get_user_1(void *);
 extern int __get_user_2(void *);
 extern int __get_user_4(void *);
 
-#define __get_user_x(__r2,__p,__e,__s,__i...)                          \
+#define __GUP_CLOBBER_1        "lr", "cc"
+#ifdef CONFIG_CPU_USE_DOMAINS
+#define __GUP_CLOBBER_2        "ip", "lr", "cc"
+#else
+#define __GUP_CLOBBER_2 "lr", "cc"
+#endif
+#define __GUP_CLOBBER_4        "lr", "cc"
+
+#define __get_user_x(__r2,__p,__e,__l,__s)                             \
           __asm__ __volatile__ (                                       \
                __asmeq("%0", "r0") __asmeq("%1", "r2")                 \
+               __asmeq("%3", "r1")                                     \
                "bl     __get_user_" #__s                               \
                : "=&r" (__e), "=r" (__r2)                              \
-               : "0" (__p)                                             \
-               : __i, "cc")
+               : "0" (__p), "r" (__l)                                  \
+               : __GUP_CLOBBER_##__s)
 
-#define get_user(x,p)                                                  \
+#define __get_user_check(x,p)                                                  \
        ({                                                              \
+               unsigned long __limit = current_thread_info()->addr_limit - 1; \
                register const typeof(*(p)) __user *__p asm("r0") = (p);\
                register unsigned long __r2 asm("r2");                  \
+               register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
-                       __get_user_x(__r2, __p, __e, 1, "lr");          \
-                       break;                                          \
+                       __get_user_x(__r2, __p, __e, __l, 1);           \
+                       break;                                          \
                case 2:                                                 \
-                       __get_user_x(__r2, __p, __e, 2, "r3", "lr");    \
+                       __get_user_x(__r2, __p, __e, __l, 2);           \
                        break;                                          \
                case 4:                                                 \
-                       __get_user_x(__r2, __p, __e, 4, "lr");          \
+                       __get_user_x(__r2, __p, __e, __l, 4);           \
                        break;                                          \
                default: __e = __get_user_bad(); break;                 \
                }                                                       \
@@ -130,42 +141,57 @@ extern int __get_user_4(void *);
                __e;                                                    \
        })
 
+#define get_user(x,p)                                                  \
+       ({                                                              \
+               might_fault();                                          \
+               __get_user_check(x,p);                                  \
+        })
+
 extern int __put_user_1(void *, unsigned int);
 extern int __put_user_2(void *, unsigned int);
 extern int __put_user_4(void *, unsigned int);
 extern int __put_user_8(void *, unsigned long long);
 
-#define __put_user_x(__r2,__p,__e,__s)                                 \
+#define __put_user_x(__r2,__p,__e,__l,__s)                             \
           __asm__ __volatile__ (                                       \
                __asmeq("%0", "r0") __asmeq("%2", "r2")                 \
+               __asmeq("%3", "r1")                                     \
                "bl     __put_user_" #__s                               \
                : "=&r" (__e)                                           \
-               : "0" (__p), "r" (__r2)                                 \
+               : "0" (__p), "r" (__r2), "r" (__l)                      \
                : "ip", "lr", "cc")
 
-#define put_user(x,p)                                                  \
+#define __put_user_check(x,p)                                                  \
        ({                                                              \
+               unsigned long __limit = current_thread_info()->addr_limit - 1; \
                register const typeof(*(p)) __r2 asm("r2") = (x);       \
                register const typeof(*(p)) __user *__p asm("r0") = (p);\
+               register unsigned long __l asm("r1") = __limit;         \
                register int __e asm("r0");                             \
                switch (sizeof(*(__p))) {                               \
                case 1:                                                 \
-                       __put_user_x(__r2, __p, __e, 1);                \
+                       __put_user_x(__r2, __p, __e, __l, 1);           \
                        break;                                          \
                case 2:                                                 \
-                       __put_user_x(__r2, __p, __e, 2);                \
+                       __put_user_x(__r2, __p, __e, __l, 2);           \
                        break;                                          \
                case 4:                                                 \
-                       __put_user_x(__r2, __p, __e, 4);                \
+                       __put_user_x(__r2, __p, __e, __l, 4);           \
                        break;                                          \
                case 8:                                                 \
-                       __put_user_x(__r2, __p, __e, 8);                \
+                       __put_user_x(__r2, __p, __e, __l, 8);           \
                        break;                                          \
                default: __e = __put_user_bad(); break;                 \
                }                                                       \
                __e;                                                    \
        })
 
+#define put_user(x,p)                                                  \
+       ({                                                              \
+               might_fault();                                          \
+               __put_user_check(x,p);                                  \
+        })
+
 #else /* CONFIG_MMU */
 
 /*
@@ -219,6 +245,7 @@ do {                                                                        \
        unsigned long __gu_addr = (unsigned long)(ptr);                 \
        unsigned long __gu_val;                                         \
        __chk_user_ptr(ptr);                                            \
+       might_fault();                                                  \
        switch (sizeof(*(ptr))) {                                       \
        case 1: __get_user_asm_byte(__gu_val,__gu_addr,err);    break;  \
        case 2: __get_user_asm_half(__gu_val,__gu_addr,err);    break;  \
@@ -300,6 +327,7 @@ do {                                                                        \
        unsigned long __pu_addr = (unsigned long)(ptr);                 \
        __typeof__(*(ptr)) __pu_val = (x);                              \
        __chk_user_ptr(ptr);                                            \
+       might_fault();                                                  \
        switch (sizeof(*(ptr))) {                                       \
        case 1: __put_user_asm_byte(__pu_val,__pu_addr,err);    break;  \
        case 2: __put_user_asm_half(__pu_val,__pu_addr,err);    break;  \
index 0cab47d4a83ff97a23c7a9d2975cfb855a687e3e..2fde5fd1accedda5a00accac967e1985be9c7f08 100644 (file)
 #define __NR_setns                     (__NR_SYSCALL_BASE+375)
 #define __NR_process_vm_readv          (__NR_SYSCALL_BASE+376)
 #define __NR_process_vm_writev         (__NR_SYSCALL_BASE+377)
+                                       /* 378 for kcmp */
 
 /*
  * The following SWIs are ARM private.
  */
 #define __IGNORE_fadvise64_64
 #define __IGNORE_migrate_pages
+#define __IGNORE_kcmp
 
 #endif /* __KERNEL__ */
 #endif /* __ASM_ARM_UNISTD_H */
index 463ff4a0ec8acaa69372b8abd40a39260ee91736..e337879595e565e5666cbd8ac0c40a4a72908c0e 100644 (file)
 /* 375 */      CALL(sys_setns)
                CALL(sys_process_vm_readv)
                CALL(sys_process_vm_writev)
+               CALL(sys_ni_syscall)    /* reserved for sys_kcmp */
 #ifndef syscalls_counted
 .equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
 #define syscalls_counted
index ba386bd94107642d9819a7d8bafb7ba04e92b83f..281bf3301241fba2a1ce1baafeaf3020b7cd57ff 100644 (file)
@@ -159,6 +159,12 @@ static int debug_arch_supported(void)
                arch >= ARM_DEBUG_ARCH_V7_1;
 }
 
+/* Can we determine the watchpoint access type from the fsr? */
+static int debug_exception_updates_fsr(void)
+{
+       return 0;
+}
+
 /* Determine number of WRP registers available. */
 static int get_num_wrp_resources(void)
 {
@@ -604,13 +610,14 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
                /* Aligned */
                break;
        case 1:
-               /* Allow single byte watchpoint. */
-               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
-                       break;
        case 2:
                /* Allow halfword watchpoints and breakpoints. */
                if (info->ctrl.len == ARM_BREAKPOINT_LEN_2)
                        break;
+       case 3:
+               /* Allow single byte watchpoint. */
+               if (info->ctrl.len == ARM_BREAKPOINT_LEN_1)
+                       break;
        default:
                ret = -EINVAL;
                goto out;
@@ -619,18 +626,35 @@ int arch_validate_hwbkpt_settings(struct perf_event *bp)
        info->address &= ~alignment_mask;
        info->ctrl.len <<= offset;
 
-       /*
-        * Currently we rely on an overflow handler to take
-        * care of single-stepping the breakpoint when it fires.
-        * In the case of userspace breakpoints on a core with V7 debug,
-        * we can use the mismatch feature as a poor-man's hardware
-        * single-step, but this only works for per-task breakpoints.
-        */
-       if (!bp->overflow_handler && (arch_check_bp_in_kernelspace(bp) ||
-           !core_has_mismatch_brps() || !bp->hw.bp_target)) {
-               pr_warning("overflow handler required but none found\n");
-               ret = -EINVAL;
+       if (!bp->overflow_handler) {
+               /*
+                * Mismatch breakpoints are required for single-stepping
+                * breakpoints.
+                */
+               if (!core_has_mismatch_brps())
+                       return -EINVAL;
+
+               /* We don't allow mismatch breakpoints in kernel space. */
+               if (arch_check_bp_in_kernelspace(bp))
+                       return -EPERM;
+
+               /*
+                * Per-cpu breakpoints are not supported by our stepping
+                * mechanism.
+                */
+               if (!bp->hw.bp_target)
+                       return -EINVAL;
+
+               /*
+                * We only support specific access types if the fsr
+                * reports them.
+                */
+               if (!debug_exception_updates_fsr() &&
+                   (info->ctrl.type == ARM_BREAKPOINT_LOAD ||
+                    info->ctrl.type == ARM_BREAKPOINT_STORE))
+                       return -EINVAL;
        }
+
 out:
        return ret;
 }
@@ -706,10 +730,12 @@ static void watchpoint_handler(unsigned long addr, unsigned int fsr,
                                goto unlock;
 
                        /* Check that the access type matches. */
-                       access = (fsr & ARM_FSR_ACCESS_MASK) ? HW_BREAKPOINT_W :
-                                HW_BREAKPOINT_R;
-                       if (!(access & hw_breakpoint_type(wp)))
-                               goto unlock;
+                       if (debug_exception_updates_fsr()) {
+                               access = (fsr & ARM_FSR_ACCESS_MASK) ?
+                                         HW_BREAKPOINT_W : HW_BREAKPOINT_R;
+                               if (!(access & hw_breakpoint_type(wp)))
+                                       goto unlock;
+                       }
 
                        /* We have a winner. */
                        info->trigger = addr;
index fef42b21cecba517e67e8ed74ef8c88d3cfd2afd..e1f906989bb8161963d8a714073a8d84a8e2c2e6 100644 (file)
@@ -11,7 +11,6 @@
 #include <linux/init.h>
 #include <linux/kernel.h>
 #include <linux/clk.h>
-#include <linux/cpufreq.h>
 #include <linux/delay.h>
 #include <linux/device.h>
 #include <linux/err.h>
@@ -96,7 +95,52 @@ static void twd_timer_stop(struct clock_event_device *clk)
        disable_percpu_irq(clk->irq);
 }
 
-#ifdef CONFIG_CPU_FREQ
+#ifdef CONFIG_COMMON_CLK
+
+/*
+ * Updates clockevent frequency when the cpu frequency changes.
+ * Called on the cpu that is changing frequency with interrupts disabled.
+ */
+static void twd_update_frequency(void *new_rate)
+{
+       twd_timer_rate = *((unsigned long *) new_rate);
+
+       clockevents_update_freq(*__this_cpu_ptr(twd_evt), twd_timer_rate);
+}
+
+static int twd_rate_change(struct notifier_block *nb,
+       unsigned long flags, void *data)
+{
+       struct clk_notifier_data *cnd = data;
+
+       /*
+        * The twd clock events must be reprogrammed to account for the new
+        * frequency.  The timer is local to a cpu, so cross-call to the
+        * changing cpu.
+        */
+       if (flags == POST_RATE_CHANGE)
+               smp_call_function(twd_update_frequency,
+                                 (void *)&cnd->new_rate, 1);
+
+       return NOTIFY_OK;
+}
+
+static struct notifier_block twd_clk_nb = {
+       .notifier_call = twd_rate_change,
+};
+
+static int twd_clk_init(void)
+{
+       if (twd_evt && *__this_cpu_ptr(twd_evt) && !IS_ERR(twd_clk))
+               return clk_notifier_register(twd_clk, &twd_clk_nb);
+
+       return 0;
+}
+core_initcall(twd_clk_init);
+
+#elif defined (CONFIG_CPU_FREQ)
+
+#include <linux/cpufreq.h>
 
 /*
  * Updates clockevent frequency when the cpu frequency changes.
index f7945218b8c63a722cf08badc229345d7083b052..b0179b89a04ce26062184aaf23f86c521fb3009c 100644 (file)
@@ -420,20 +420,23 @@ asmlinkage void __exception do_undefinstr(struct pt_regs *regs)
 #endif
                        instr = *(u32 *) pc;
        } else if (thumb_mode(regs)) {
-               get_user(instr, (u16 __user *)pc);
+               if (get_user(instr, (u16 __user *)pc))
+                       goto die_sig;
                if (is_wide_instruction(instr)) {
                        unsigned int instr2;
-                       get_user(instr2, (u16 __user *)pc+1);
+                       if (get_user(instr2, (u16 __user *)pc+1))
+                               goto die_sig;
                        instr <<= 16;
                        instr |= instr2;
                }
-       } else {
-               get_user(instr, (u32 __user *)pc);
+       } else if (get_user(instr, (u32 __user *)pc)) {
+               goto die_sig;
        }
 
        if (call_undef_hook(regs, instr) == 0)
                return;
 
+die_sig:
 #ifdef CONFIG_DEBUG_USER
        if (user_debug & UDBG_UNDEFINED) {
                printk(KERN_INFO "%s (%d): undefined instruction: pc=%p\n",
index d6dacc69254e47ddca3f399cc6f37eef12b073d8..395d5fbb8fa20c01c8b71d37dce42df700820c91 100644 (file)
@@ -59,6 +59,7 @@ void __init init_current_timer_delay(unsigned long freq)
 {
        pr_info("Switching to timer-based delay loop\n");
        lpj_fine                        = freq / HZ;
+       loops_per_jiffy                 = lpj_fine;
        arm_delay_ops.delay             = __timer_delay;
        arm_delay_ops.const_udelay      = __timer_const_udelay;
        arm_delay_ops.udelay            = __timer_udelay;
index 11093a7c3e32289e95a8c100cc01ef2bbb8d7101..9b06bb41fca659b9bbfc2f996e703ce2b8c315aa 100644 (file)
@@ -16,8 +16,9 @@
  * __get_user_X
  *
  * Inputs:     r0 contains the address
+ *             r1 contains the address limit, which must be preserved
  * Outputs:    r0 is the error code
- *             r2, r3 contains the zero-extended value
+ *             r2 contains the zero-extended value
  *             lr corrupted
  *
  * No other registers must be altered.  (see <asm/uaccess.h>
  * Note also that it is intended that __get_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__get_user_1)
+       check_uaccess r0, 1, r1, r2, __get_user_bad
 1: TUSER(ldrb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_1)
 
 ENTRY(__get_user_2)
-#ifdef CONFIG_THUMB2_KERNEL
-2: TUSER(ldrb) r2, [r0]
-3: TUSER(ldrb) r3, [r0, #1]
+       check_uaccess r0, 2, r1, r2, __get_user_bad
+#ifdef CONFIG_CPU_USE_DOMAINS
+rb     .req    ip
+2:     ldrbt   r2, [r0], #1
+3:     ldrbt   rb, [r0], #0
 #else
-2: TUSER(ldrb) r2, [r0], #1
-3: TUSER(ldrb) r3, [r0]
+rb     .req    r0
+2:     ldrb    r2, [r0]
+3:     ldrb    rb, [r0, #1]
 #endif
 #ifndef __ARMEB__
-       orr     r2, r2, r3, lsl #8
+       orr     r2, r2, rb, lsl #8
 #else
-       orr     r2, r3, r2, lsl #8
+       orr     r2, rb, r2, lsl #8
 #endif
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__get_user_2)
 
 ENTRY(__get_user_4)
+       check_uaccess r0, 4, r1, r2, __get_user_bad
 4: TUSER(ldr)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
index 7db25990c589f3d98554d9aee47cf7b5c3c486fd..3d73dcb959b0da83bc8affe3a781b7fcbdb17752 100644 (file)
@@ -16,6 +16,7 @@
  * __put_user_X
  *
  * Inputs:     r0 contains the address
+ *             r1 contains the address limit, which must be preserved
  *             r2, r3 contains the value
  * Outputs:    r0 is the error code
  *             lr corrupted
  * Note also that it is intended that __put_user_bad is not global.
  */
 #include <linux/linkage.h>
+#include <asm/assembler.h>
 #include <asm/errno.h>
 #include <asm/domain.h>
 
 ENTRY(__put_user_1)
+       check_uaccess r0, 1, r1, ip, __put_user_bad
 1: TUSER(strb) r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_1)
 
 ENTRY(__put_user_2)
+       check_uaccess r0, 2, r1, ip, __put_user_bad
        mov     ip, r2, lsr #8
 #ifdef CONFIG_THUMB2_KERNEL
 #ifndef __ARMEB__
@@ -60,12 +64,14 @@ ENTRY(__put_user_2)
 ENDPROC(__put_user_2)
 
 ENTRY(__put_user_4)
+       check_uaccess r0, 4, r1, ip, __put_user_bad
 4: TUSER(str)  r2, [r0]
        mov     r0, #0
        mov     pc, lr
 ENDPROC(__put_user_4)
 
 ENTRY(__put_user_8)
+       check_uaccess r0, 8, r1, ip, __put_user_bad
 #ifdef CONFIG_THUMB2_KERNEL
 5: TUSER(str)  r2, [r0]
 6: TUSER(str)  r3, [r0, #4]
index 104ca40d8d18908cb463e7ae1cd56790c926d971..aaa443b48c91f121e2f698792fb94bb4d6e2afa6 100644 (file)
@@ -197,7 +197,7 @@ void __init at91rm9200_timer_init(void)
        at91_st_read(AT91_ST_SR);
 
        /* Make IRQs happen for the system timer */
-       setup_irq(AT91_ID_SYS, &at91rm9200_timer_irq);
+       setup_irq(NR_IRQS_LEGACY + AT91_ID_SYS, &at91rm9200_timer_irq);
 
        /* The 32KiHz "Slow Clock" (tick every 30517.58 nanoseconds) is used
         * directly for the clocksource and all clockevents, after adjusting
index 7b9c2ba396edb854cfd78ddef676250a751e60bc..bce572a530ef2c59946e2f574229d905bbfe041b 100644 (file)
@@ -726,6 +726,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        },
 };
 
@@ -744,10 +746,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9260_rtt_device.num_resources = 2;
+       at91sam9260_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9260_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index 8df5c1bdff92f1d1194fa9d64da61e2aa9bc2598..bc2590d712d06b214a81171a90c45c9f00ac9252 100644 (file)
@@ -609,6 +609,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -626,10 +628,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9261_rtt_device.num_resources = 2;
+       at91sam9261_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9261_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index eb6bbf86fb9f597cc7424a52b459bb04ecff2326..9b6ca734f1a96e6b903f177185fc9d23af2f28e5 100644 (file)
@@ -990,6 +990,8 @@ static struct resource rtt0_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1006,6 +1008,8 @@ static struct resource rtt1_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1027,14 +1031,14 @@ static void __init at91_add_device_rtt_rtc(void)
                 * The second resource is needed only for the chosen RTT:
                 * GPBR will serve as the storage for RTC time offset
                 */
-               at91sam9263_rtt0_device.num_resources = 2;
+               at91sam9263_rtt0_device.num_resources = 3;
                at91sam9263_rtt1_device.num_resources = 1;
                pdev = &at91sam9263_rtt0_device;
                r = rtt0_resources;
                break;
        case 1:
                at91sam9263_rtt0_device.num_resources = 1;
-               at91sam9263_rtt1_device.num_resources = 2;
+               at91sam9263_rtt1_device.num_resources = 3;
                pdev = &at91sam9263_rtt1_device;
                r = rtt1_resources;
                break;
@@ -1047,6 +1051,8 @@ static void __init at91_add_device_rtt_rtc(void)
        pdev->name = "rtc-at91sam9";
        r[1].start = AT91SAM9263_BASE_GPBR + 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        r[1].end = r[1].start + 3;
+       r[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       r[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index 0aa9bdb755765e2116281d66b9ef3486be79e282..e4c3b3709204256297f6887ed89ab74847159841 100644 (file)
@@ -1293,6 +1293,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -1310,10 +1312,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9g45_rtt_device.num_resources = 2;
+       at91sam9g45_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9G45_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index e4da7179e5459565c87e526cbf805b6bb95de1b1..dcda24838b5abb4f382fdabe591c0ff849d01907 100644 (file)
@@ -688,6 +688,8 @@ static struct resource rtt_resources[] = {
                .flags  = IORESOURCE_MEM,
        }, {
                .flags  = IORESOURCE_MEM,
+       }, {
+               .flags  = IORESOURCE_IRQ,
        }
 };
 
@@ -705,10 +707,12 @@ static void __init at91_add_device_rtt_rtc(void)
         * The second resource is needed:
         * GPBR will serve as the storage for RTC time offset
         */
-       at91sam9rl_rtt_device.num_resources = 2;
+       at91sam9rl_rtt_device.num_resources = 3;
        rtt_resources[1].start = AT91SAM9RL_BASE_GPBR +
                                 4 * CONFIG_RTC_DRV_AT91SAM9_GPBR;
        rtt_resources[1].end = rtt_resources[1].start + 3;
+       rtt_resources[2].start = NR_IRQS_LEGACY + AT91_ID_SYS;
+       rtt_resources[2].end = NR_IRQS_LEGACY + AT91_ID_SYS;
 }
 #else
 static void __init at91_add_device_rtt_rtc(void)
index de2ec6b8fea7693555c2b25367b4efb1e06cae25..188c82971ebd069ac890f90726660e8181e6848b 100644 (file)
@@ -63,6 +63,12 @@ EXPORT_SYMBOL_GPL(at91_pmc_base);
 
 #define cpu_has_300M_plla()    (cpu_is_at91sam9g10())
 
+#define cpu_has_240M_plla()    (cpu_is_at91sam9261() \
+                               || cpu_is_at91sam9263() \
+                               || cpu_is_at91sam9rl())
+
+#define cpu_has_210M_plla()    (cpu_is_at91sam9260())
+
 #define cpu_has_pllb()         (!(cpu_is_at91sam9rl() \
                                || cpu_is_at91sam9g45() \
                                || cpu_is_at91sam9x5() \
@@ -706,6 +712,12 @@ static int __init at91_pmc_init(unsigned long main_clock)
        } else if (cpu_has_800M_plla()) {
                if (plla.rate_hz > 800000000)
                        pll_overclock = true;
+       } else if (cpu_has_240M_plla()) {
+               if (plla.rate_hz > 240000000)
+                       pll_overclock = true;
+       } else if (cpu_has_210M_plla()) {
+               if (plla.rate_hz > 210000000)
+                       pll_overclock = true;
        } else {
                if (plla.rate_hz > 209000000)
                        pll_overclock = true;
index ab99c3c3b752689e50db5720e2d36beb23ee2b21..026b4b277ae5d54e4d911f69c91c7bfee21ea68d 100644 (file)
@@ -186,6 +186,13 @@ config DA850_UI_RMII
          NOTE: Please take care while choosing this option, MII PHY will
          not be functional if RMII mode is selected.
 
+config DA850_UI_SD_VIDEO_PORT
+       bool "Video Port Interface"
+       help
+         Say Y if you want to use Video Port Interface (VPIF) on the
+         DA850/OMAP-L138 EVM. The Video decoders/encoders are found on the
+         UI daughter card that is supplied with the EVM.
+
 endchoice
 
 config DA850_WL12XX
index 1295e616ceee7e32a5b31d62b3cf52a4286578b3..32ee3f89596738d988a00105c0358d4ff1a61f1b 100644 (file)
@@ -45,6 +45,9 @@
 #include <linux/platform_data/mtd-davinci-aemif.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/tvp514x.h>
+#include <media/adv7343.h>
+
 #define DA850_EVM_PHY_ID               "davinci_mdio-0:00"
 #define DA850_LCD_PWR_PIN              GPIO_TO_PIN(2, 8)
 #define DA850_LCD_BL_PIN               GPIO_TO_PIN(2, 15)
@@ -452,6 +455,15 @@ static void da850_evm_ui_keys_init(unsigned gpio)
        }
 }
 
+#ifdef CONFIG_DA850_UI_SD_VIDEO_PORT
+static inline void da850_evm_setup_video_port(int video_sel)
+{
+       gpio_set_value_cansleep(video_sel, 0);
+}
+#else
+static inline void da850_evm_setup_video_port(int video_sel) { }
+#endif
+
 static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
                                                unsigned ngpio, void *c)
 {
@@ -497,6 +509,8 @@ static int da850_evm_ui_expander_setup(struct i2c_client *client, unsigned gpio,
 
        da850_evm_setup_emac_rmii(sel_a);
 
+       da850_evm_setup_video_port(sel_c);
+
        return 0;
 
 exp_setup_keys_fail:
@@ -1149,6 +1163,169 @@ static __init int da850_evm_init_cpufreq(void)
 static __init int da850_evm_init_cpufreq(void) { return 0; }
 #endif
 
+#if defined(CONFIG_DA850_UI_SD_VIDEO_PORT)
+
+#define TVP5147_CH0            "tvp514x-0"
+#define TVP5147_CH1            "tvp514x-1"
+
+/* VPIF capture configuration */
+static struct tvp514x_platform_data tvp5146_pdata = {
+               .clk_polarity = 0,
+               .hs_polarity  = 1,
+               .vs_polarity  = 1,
+};
+
+#define TVP514X_STD_ALL (V4L2_STD_NTSC | V4L2_STD_PAL)
+
+static const struct vpif_input da850_ch0_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "Composite",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH0,
+       },
+};
+
+static const struct vpif_input da850_ch1_inputs[] = {
+       {
+               .input = {
+                       .index = 0,
+                       .name  = "S-Video",
+                       .type  = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
+                       .std   = TVP514X_STD_ALL,
+               },
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
+               .subdev_name = TVP5147_CH1,
+       },
+};
+
+static struct vpif_subdev_info da850_vpif_capture_sdev_info[] = {
+       {
+               .name = TVP5147_CH0,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5d),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+       {
+               .name = TVP5147_CH1,
+               .board_info = {
+                       I2C_BOARD_INFO("tvp5146", 0x5c),
+                       .platform_data = &tvp5146_pdata,
+               },
+       },
+};
+
+static struct vpif_capture_config da850_vpif_capture_config = {
+       .subdev_info = da850_vpif_capture_sdev_info,
+       .subdev_count = ARRAY_SIZE(da850_vpif_capture_sdev_info),
+       .chan_config[0] = {
+               .inputs = da850_ch0_inputs,
+               .input_count = ARRAY_SIZE(da850_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .chan_config[1] = {
+               .inputs = da850_ch1_inputs,
+               .input_count = ARRAY_SIZE(da850_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol  = 1,
+                       .vd_pol  = 1,
+                       .fid_pol = 0,
+               },
+       },
+       .card_name = "DA850/OMAP-L138 Video Capture",
+};
+
+/* VPIF display configuration */
+static struct vpif_subdev_info da850_vpif_subdev[] = {
+       {
+               .name = "adv7343",
+               .board_info = {
+                       I2C_BOARD_INFO("adv7343", 0x2a),
+               },
+       },
+};
+
+static const struct vpif_output da850_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
+};
+
+static struct vpif_display_config da850_vpif_display_config = {
+       .subdevinfo   = da850_vpif_subdev,
+       .subdev_count = ARRAY_SIZE(da850_vpif_subdev),
+       .chan_config[0] = {
+               .outputs = da850_ch0_outputs,
+               .output_count = ARRAY_SIZE(da850_ch0_outputs),
+       },
+       .card_name    = "DA850/OMAP-L138 Video Display",
+};
+
+static __init void da850_vpif_init(void)
+{
+       int ret;
+
+       ret = da850_register_vpif();
+       if (ret)
+               pr_warn("da850_evm_init: VPIF setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_capture_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_capture(&da850_vpif_capture_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF capture setup failed: %d\n", ret);
+
+       ret = davinci_cfg_reg_list(da850_vpif_display_pins);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display mux setup failed: %d\n",
+                       ret);
+
+       ret = da850_register_vpif_display(&da850_vpif_display_config);
+       if (ret)
+               pr_warn("da850_evm_init: VPIF display setup failed: %d\n", ret);
+}
+
+#else
+static __init void da850_vpif_init(void) {}
+#endif
+
 #ifdef CONFIG_DA850_WL12XX
 
 static void wl12xx_set_power(int index, bool power_on)
@@ -1375,6 +1552,8 @@ static __init void da850_evm_init(void)
                pr_warning("da850_evm_init: suspend registration failed: %d\n",
                                ret);
 
+       da850_vpif_init();
+
        ret = da8xx_register_spi(1, da850evm_spi_info,
                                 ARRAY_SIZE(da850evm_spi_info));
        if (ret)
index ca72fc4b8ccaac489b3e5e4e800e84e73730149e..f22572cee49d89ade236851a04fdf2ba94fed2e6 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/phy.h>
 #include <linux/clk.h>
 #include <linux/videodev2.h>
+#include <linux/v4l2-dv-timings.h>
 #include <linux/export.h>
 
 #include <media/tvp514x.h>
@@ -620,7 +621,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "ntsc",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_525_60},
+               .std_id         = V4L2_STD_525_60,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 480,
@@ -632,7 +633,7 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
        {
                .name           = "pal",
                .timings_type   = VPBE_ENC_STD,
-               .timings        = {V4L2_STD_625_50},
+               .std_id         = V4L2_STD_625_50,
                .interlaced     = 1,
                .xres           = 720,
                .yres           = 576,
@@ -647,8 +648,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_std_timing[] = {
 static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        {
                .name           = "480p59_94",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_480P59_94},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X480P59_94,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 480,
@@ -659,8 +660,8 @@ static struct vpbe_enc_mode_info dm644xevm_enc_preset_timing[] = {
        },
        {
                .name           = "576p50",
-               .timings_type   = VPBE_ENC_DV_PRESET,
-               .timings        = {V4L2_DV_576P50},
+               .timings_type   = VPBE_ENC_CUSTOM_TIMINGS,
+               .dv_timings     = V4L2_DV_BT_CEA_720X576P50,
                .interlaced     = 0,
                .xres           = 720,
                .yres           = 576,
@@ -698,7 +699,7 @@ static struct vpbe_output dm644xevm_vpbe_outputs[] = {
                        .index          = 1,
                        .name           = "Component",
                        .type           = V4L2_OUTPUT_TYPE_ANALOG,
-                       .capabilities   = V4L2_OUT_CAP_PRESETS,
+                       .capabilities   = V4L2_OUT_CAP_DV_TIMINGS,
                },
                .subdev_name    = VPBE_VENC_SUBDEV_NAME,
                .default_mode   = "480p59_94",
index 9944367b4931b9a630a5bd91db7d6e784aebf75f..1dbf85beed1baaf55718a7f00debd3416327e66d 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/i2c/pcf857x.h>
 
 #include <media/tvp514x.h>
+#include <media/adv7343.h>
 
 #include <linux/mtd/mtd.h>
 #include <linux/mtd/nand.h>
@@ -496,18 +497,49 @@ static struct vpif_subdev_info dm646x_vpif_subdev[] = {
        },
 };
 
-static const char *output[] = {
-       "Composite",
-       "Component",
-       "S-Video",
+static const struct vpif_output dm6467_ch0_outputs[] = {
+       {
+               .output = {
+                       .index = 0,
+                       .name = "Composite",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPOSITE_ID,
+       },
+       {
+               .output = {
+                       .index = 1,
+                       .name = "Component",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_CUSTOM_TIMINGS,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_COMPONENT_ID,
+       },
+       {
+               .output = {
+                       .index = 2,
+                       .name = "S-Video",
+                       .type = V4L2_OUTPUT_TYPE_ANALOG,
+                       .capabilities = V4L2_OUT_CAP_STD,
+                       .std = V4L2_STD_ALL,
+               },
+               .subdev_name = "adv7343",
+               .output_route = ADV7343_SVIDEO_ID,
+       },
 };
 
 static struct vpif_display_config dm646x_vpif_display_config = {
        .set_clock      = set_vpif_clock,
        .subdevinfo     = dm646x_vpif_subdev,
        .subdev_count   = ARRAY_SIZE(dm646x_vpif_subdev),
-       .output         = output,
-       .output_count   = ARRAY_SIZE(output),
+       .chan_config[0] = {
+               .outputs = dm6467_ch0_outputs,
+               .output_count = ARRAY_SIZE(dm6467_ch0_outputs),
+       },
        .card_name      = "DM646x EVM",
 };
 
@@ -601,15 +633,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5d),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_CVBS_VI2B,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
        {
                .name   = TVP5147_CH1,
@@ -617,15 +640,6 @@ static struct vpif_subdev_info vpif_capture_sdev_info[] = {
                        I2C_BOARD_INFO("tvp5146", 0x5c),
                        .platform_data = &tvp5146_pdata,
                },
-               .input = INPUT_SVIDEO_VI2C_VI1C,
-               .output = OUTPUT_10BIT_422_EMBEDDED_SYNC,
-               .can_route = 1,
-               .vpif_if = {
-                       .if_type = VPIF_IF_BT656,
-                       .hd_pol = 1,
-                       .vd_pol = 1,
-                       .fid_pol = 0,
-               },
        },
 };
 
@@ -635,9 +649,12 @@ static const struct vpif_input dm6467_ch0_inputs[] = {
                        .index = 0,
                        .name = "Composite",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH0,
+               .input_route = INPUT_CVBS_VI2B,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -647,9 +664,12 @@ static const struct vpif_input dm6467_ch1_inputs[] = {
                        .index = 0,
                        .name = "S-Video",
                        .type = V4L2_INPUT_TYPE_CAMERA,
+                       .capabilities = V4L2_IN_CAP_STD,
                        .std = TVP514X_STD_ALL,
                },
                .subdev_name = TVP5147_CH1,
+               .input_route = INPUT_SVIDEO_VI2C_VI1C,
+               .output_route = OUTPUT_10BIT_422_EMBEDDED_SYNC,
        },
 };
 
@@ -661,10 +681,22 @@ static struct vpif_capture_config dm646x_vpif_capture_cfg = {
        .chan_config[0] = {
                .inputs = dm6467_ch0_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch0_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
        .chan_config[1] = {
                .inputs = dm6467_ch1_inputs,
                .input_count = ARRAY_SIZE(dm6467_ch1_inputs),
+               .vpif_if = {
+                       .if_type = VPIF_IF_BT656,
+                       .hd_pol = 1,
+                       .vd_pol = 1,
+                       .fid_pol = 0,
+               },
        },
 };
 
index b44dc844e15e0c2ce8c404486c75494749dfec51..20d16fff6efd5c9a84a22eaede299b7a19bcbe58 100644 (file)
@@ -347,6 +347,13 @@ static struct clk spi1_clk = {
        .flags          = DA850_CLK_ASYNC3,
 };
 
+static struct clk vpif_clk = {
+       .name           = "vpif",
+       .parent         = &pll0_sysclk2,
+       .lpsc           = DA850_LPSC1_VPIF,
+       .gpsc           = 1,
+};
+
 static struct clk sata_clk = {
        .name           = "sata",
        .parent         = &pll0_sysclk2,
@@ -397,6 +404,7 @@ static struct clk_lookup da850_clks[] = {
        CLK(NULL,               "usb20",        &usb20_clk),
        CLK("spi_davinci.0",    NULL,           &spi0_clk),
        CLK("spi_davinci.1",    NULL,           &spi1_clk),
+       CLK("vpif",             NULL,           &vpif_clk),
        CLK("ahci",             NULL,           &sata_clk),
        CLK(NULL,               NULL,           NULL),
 };
@@ -573,6 +581,46 @@ static const struct mux_config da850_pins[] = {
        MUX_CFG(DA850, GPIO6_10,        13,     20,     15,     8,      false)
        MUX_CFG(DA850, GPIO6_13,        13,     8,      15,     8,      false)
        MUX_CFG(DA850, RTC_ALARM,       0,      28,     15,     2,      false)
+       /* VPIF Capture */
+       MUX_CFG(DA850, VPIF_DIN0,       15,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN1,       15,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN2,       14,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN3,       14,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN4,       14,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN5,       14,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN6,       14,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN7,       14,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN8,       16,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN9,       16,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN10,      15,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN11,      15,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN12,      15,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN13,      15,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN14,      15,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DIN15,      15,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN0,     14,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN1,     14,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN2,     19,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKIN3,     19,     16,     15,     1,      false)
+       /* VPIF Display */
+       MUX_CFG(DA850, VPIF_DOUT0,      17,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT1,      17,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT2,      16,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT3,      16,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT4,      16,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT5,      16,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT6,      16,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT7,      16,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT8,      18,     4,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT9,      18,     0,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT10,     17,     28,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT11,     17,     24,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT12,     17,     20,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT13,     17,     16,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT14,     17,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_DOUT15,     17,     8,      15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO2,      19,     12,     15,     1,      false)
+       MUX_CFG(DA850, VPIF_CLKO3,      19,     20,     15,     1,      false)
 #endif
 };
 
@@ -595,6 +643,26 @@ const short da850_lcdcntl_pins[] __initdata = {
        -1
 };
 
+const short da850_vpif_capture_pins[] __initdata = {
+       DA850_VPIF_DIN0, DA850_VPIF_DIN1, DA850_VPIF_DIN2, DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4, DA850_VPIF_DIN5, DA850_VPIF_DIN6, DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8, DA850_VPIF_DIN9, DA850_VPIF_DIN10, DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12, DA850_VPIF_DIN13, DA850_VPIF_DIN14, DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0, DA850_VPIF_CLKIN1, DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+       -1
+};
+
+const short da850_vpif_display_pins[] __initdata = {
+       DA850_VPIF_DOUT0, DA850_VPIF_DOUT1, DA850_VPIF_DOUT2, DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4, DA850_VPIF_DOUT5, DA850_VPIF_DOUT6, DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8, DA850_VPIF_DOUT9, DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11, DA850_VPIF_DOUT12, DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14, DA850_VPIF_DOUT15, DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
+       -1
+};
+
 /* FIQ are pri 0-1; otherwise 2-7, with 7 lowest priority */
 static u8 da850_default_priorities[DA850_N_CP_INTC_IRQ] = {
        [IRQ_DA8XX_COMMTX]              = 7,
@@ -1064,6 +1132,90 @@ no_ddrpll_mem:
        return ret;
 }
 
+/* VPIF resource, platform data */
+static u64 da850_vpif_dma_mask = DMA_BIT_MASK(32);
+
+static struct resource da850_vpif_resource[] = {
+       {
+               .start = DA8XX_VPIF_BASE,
+               .end   = DA8XX_VPIF_BASE + 0xfff,
+               .flags = IORESOURCE_MEM,
+       }
+};
+
+static struct platform_device da850_vpif_dev = {
+       .name           = "vpif",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_resource),
+};
+
+static struct resource da850_vpif_display_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_display_dev = {
+       .name           = "vpif_display",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_display_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_display_resource),
+};
+
+static struct resource da850_vpif_capture_resource[] = {
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+       {
+               .start = IRQ_DA850_VPIFINT,
+               .end   = IRQ_DA850_VPIFINT,
+               .flags = IORESOURCE_IRQ,
+       },
+};
+
+static struct platform_device da850_vpif_capture_dev = {
+       .name           = "vpif_capture",
+       .id             = -1,
+       .dev            = {
+               .dma_mask               = &da850_vpif_dma_mask,
+               .coherent_dma_mask      = DMA_BIT_MASK(32),
+       },
+       .resource       = da850_vpif_capture_resource,
+       .num_resources  = ARRAY_SIZE(da850_vpif_capture_resource),
+};
+
+int __init da850_register_vpif(void)
+{
+       return platform_device_register(&da850_vpif_dev);
+}
+
+int __init da850_register_vpif_display(struct vpif_display_config
+                                               *display_config)
+{
+       da850_vpif_display_dev.dev.platform_data = display_config;
+       return platform_device_register(&da850_vpif_display_dev);
+}
+
+int __init da850_register_vpif_capture(struct vpif_capture_config
+                                                       *capture_config)
+{
+       da850_vpif_capture_dev.dev.platform_data = capture_config;
+       return platform_device_register(&da850_vpif_capture_dev);
+}
+
 static struct davinci_soc_info davinci_soc_info_da850 = {
        .io_desc                = da850_io_desc,
        .io_desc_num            = ARRAY_SIZE(da850_io_desc),
index c8b866657fcbf1a2d240c3711fce4bba1093c775..79d2880c9d2d9e10cba263b6efd87cc7d43115c2 100644 (file)
@@ -701,7 +701,7 @@ static struct resource dm644x_venc_resources[] = {
 #define DM644X_VPSS_DACCLKEN                  BIT(4)
 
 static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
-                                  unsigned int mode)
+                                  unsigned int pclock)
 {
        int ret = 0;
        u32 v = DM644X_VPSS_VENCLKEN;
@@ -711,27 +711,18 @@ static int dm644x_venc_setup_clock(enum vpbe_enc_timings_type type,
                v |= DM644X_VPSS_DACCLKEN;
                writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
                break;
-       case VPBE_ENC_DV_PRESET:
-               switch (mode) {
-               case V4L2_DV_480P59_94:
-               case V4L2_DV_576P50:
+       case VPBE_ENC_CUSTOM_TIMINGS:
+               if (pclock <= 27000000) {
                        v |= DM644X_VPSS_MUXSEL_PLL2_MODE |
                             DM644X_VPSS_DACCLKEN;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               case V4L2_DV_720P60:
-               case V4L2_DV_1080I60:
-               case V4L2_DV_1080P30:
+               } else {
                        /*
                         * For HD, use external clock source since
                         * HD requires higher clock rate
                         */
                        v |= DM644X_VPSS_MUXSEL_VPBECLK_MODE;
                        writel(v, DAVINCI_SYSMOD_VIRT(SYSMOD_VPSS_CLKCTL));
-                       break;
-               default:
-                       ret = -EINVAL;
-                       break;
                }
                break;
        default:
index 33e78ae2a254d3106f97a42dcf68aa2cebc076c2..13d229575757ffadcce3636068c03512d04fa948 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/platform_device.h>
 #include <linux/davinci_emac.h>
 #include <linux/spi/spi.h>
+#include <linux/videodev2.h>
 
 #include <mach/serial.h>
 #include <mach/edma.h>
@@ -26,6 +27,8 @@
 #include <linux/platform_data/usb-davinci.h>
 #include <linux/platform_data/spi-davinci.h>
 
+#include <media/davinci/vpif_types.h>
+
 extern void __iomem *da8xx_syscfg0_base;
 extern void __iomem *da8xx_syscfg1_base;
 
@@ -63,6 +66,7 @@ extern unsigned int da850_max_speed;
 #define DA8XX_PLL0_BASE                0x01c11000
 #define DA8XX_TIMER64P0_BASE   0x01c20000
 #define DA8XX_TIMER64P1_BASE   0x01c21000
+#define DA8XX_VPIF_BASE                0x01e17000
 #define DA8XX_GPIO_BASE                0x01e26000
 #define DA8XX_PSC1_BASE                0x01e27000
 #define DA8XX_AEMIF_CS2_BASE   0x60000000
@@ -92,6 +96,11 @@ int da8xx_register_cpuidle(void);
 void __iomem * __init da8xx_get_mem_ctlr(void);
 int da850_register_pm(struct platform_device *pdev);
 int __init da850_register_sata(unsigned long refclkpn);
+int __init da850_register_vpif(void);
+int __init da850_register_vpif_display
+                       (struct vpif_display_config *display_config);
+int __init da850_register_vpif_capture
+                       (struct vpif_capture_config *capture_config);
 void da8xx_restart(char mode, const char *cmd);
 
 extern struct platform_device da8xx_serial_device;
@@ -126,6 +135,8 @@ extern const short da830_ecap1_pins[];
 extern const short da830_ecap2_pins[];
 extern const short da830_eqep0_pins[];
 extern const short da830_eqep1_pins[];
+extern const short da850_vpif_capture_pins[];
+extern const short da850_vpif_display_pins[];
 
 extern const short da850_i2c0_pins[];
 extern const short da850_i2c1_pins[];
index a7e92fca32e6719457167f1c2f9efbdd2921df73..9e95b8a1edb62964cc473c1947bc61ebc6ca0402 100644 (file)
@@ -928,6 +928,48 @@ enum davinci_da850_index {
        DA850_GPIO6_10,
        DA850_GPIO6_13,
        DA850_RTC_ALARM,
+
+       /* VPIF Capture */
+       DA850_VPIF_DIN0,
+       DA850_VPIF_DIN1,
+       DA850_VPIF_DIN2,
+       DA850_VPIF_DIN3,
+       DA850_VPIF_DIN4,
+       DA850_VPIF_DIN5,
+       DA850_VPIF_DIN6,
+       DA850_VPIF_DIN7,
+       DA850_VPIF_DIN8,
+       DA850_VPIF_DIN9,
+       DA850_VPIF_DIN10,
+       DA850_VPIF_DIN11,
+       DA850_VPIF_DIN12,
+       DA850_VPIF_DIN13,
+       DA850_VPIF_DIN14,
+       DA850_VPIF_DIN15,
+       DA850_VPIF_CLKIN0,
+       DA850_VPIF_CLKIN1,
+       DA850_VPIF_CLKIN2,
+       DA850_VPIF_CLKIN3,
+
+       /* VPIF Display */
+       DA850_VPIF_DOUT0,
+       DA850_VPIF_DOUT1,
+       DA850_VPIF_DOUT2,
+       DA850_VPIF_DOUT3,
+       DA850_VPIF_DOUT4,
+       DA850_VPIF_DOUT5,
+       DA850_VPIF_DOUT6,
+       DA850_VPIF_DOUT7,
+       DA850_VPIF_DOUT8,
+       DA850_VPIF_DOUT9,
+       DA850_VPIF_DOUT10,
+       DA850_VPIF_DOUT11,
+       DA850_VPIF_DOUT12,
+       DA850_VPIF_DOUT13,
+       DA850_VPIF_DOUT14,
+       DA850_VPIF_DOUT15,
+       DA850_VPIF_CLKO2,
+       DA850_VPIF_CLKO3,
 };
 
 enum davinci_tnetv107x_index {
index 405318e35bf63f8422dc5263088d2a9cbe64a212..40a0027838e81601427fbb2bc7ff04311e5300ad 100644 (file)
 #define DA830_LPSC1_McASP1             8
 #define DA850_LPSC1_SATA               8
 #define DA830_LPSC1_McASP2             9
+#define DA850_LPSC1_VPIF               9
 #define DA8XX_LPSC1_SPI1               10
 #define DA8XX_LPSC1_I2C                        11
 #define DA8XX_LPSC1_UART1              12
index 29d63fa68f3ca2c56db27799e4961f7a803cacfe..5d577fb1b67d493f05a3aeeac3ea285a6b5c8d32 100644 (file)
@@ -102,7 +102,8 @@ void __init dove_ehci1_init(void)
 void __init dove_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge00_init(eth_data, DOVE_GE00_PHYS_BASE,
-                       IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR);
+                       IRQ_DOVE_GE00_SUM, IRQ_DOVE_GE00_ERR,
+                       1600);
 }
 
 /*****************************************************************************
index 393d2ce99af7e896ece026c294b7b4996c64d866..bdbaef2ae2cd47d9a1c09115ef81512fdc550107 100644 (file)
@@ -378,10 +378,10 @@ static struct regulator_consumer_supply __initdata max8997_ldo1_[] = {
 };
 static struct regulator_consumer_supply __initdata max8997_ldo3_[] = {
        REGULATOR_SUPPLY("vusb_d", "s3c-hsotg"), /* USB */
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo4_[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata max8997_ldo5_[] = {
        REGULATOR_SUPPLY("vhsic", "modemctl"), /* MODEM */
@@ -1180,9 +1180,7 @@ static struct platform_device cam_8m_12v_fixed_rdev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_MEGA_RST      EXYNOS4_GPY3(7) /* ISP_RESET */
@@ -1226,7 +1224,6 @@ static struct s5p_fimc_isp_info nuri_camera_sensors[] = {
                .bus_type       = FIMC_MIPI_CSI2,
                .board_info     = &m5mols_board_info,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index 4a531dccd0c6f175efbbbd09c97d6849d30fc2de..0b8d24e27e74d45eeff900341b62808673dd066e 100644 (file)
@@ -42,6 +42,7 @@
 #include <plat/backlight.h>
 #include <plat/fb.h>
 #include <plat/mfc.h>
+#include <plat/hdmi.h>
 
 #include <linux/platform_data/usb-exynos.h>
 #include <mach/map.h>
@@ -95,12 +96,12 @@ static struct s3c2410_uartcfg origen_uartcfgs[] __initdata = {
 };
 
 static struct regulator_consumer_supply __initdata ldo3_consumer[] = {
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"), /* MIPI */
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"), /* HDMI */
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"), /* HDMI */
 };
 static struct regulator_consumer_supply __initdata ldo6_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"), /* MIPI */
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"), /* MIPI */
 };
 static struct regulator_consumer_supply __initdata ldo7_consumer[] = {
        REGULATOR_SUPPLY("avdd", "alc5625"), /* Realtek ALC5625 */
@@ -734,6 +735,11 @@ static void __init origen_bt_setup(void)
        s3c_gpio_setpull(EXYNOS4_GPX2(2), S3C_GPIO_PULL_NONE);
 }
 
+/* I2C module and id for HDMIPHY */
+static struct i2c_board_info hdmiphy_info = {
+       I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38),
+};
+
 static void s5p_tv_setup(void)
 {
        /* Direct HPD to HDMI chip */
@@ -781,6 +787,7 @@ static void __init origen_machine_init(void)
 
        s5p_tv_setup();
        s5p_i2c_hdmiphy_set_platdata(NULL);
+       s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0);
 
 #ifdef CONFIG_DRM_EXYNOS
        s5p_device_fimd0.dev.platform_data = &drm_fimd_pdata;
index fa2ada6c9ca7d09bef0b4256c5f14ce1985748d0..1b864ee387cd70a73e65f93fb74058891c0ed273 100644 (file)
@@ -40,6 +40,7 @@
 #include <plat/mfc.h>
 #include <linux/platform_data/usb-ehci-s5p.h>
 #include <plat/clock.h>
+#include <plat/hdmi.h>
 
 #include <mach/map.h>
 #include <linux/platform_data/usb-exynos.h>
@@ -354,6 +355,11 @@ static struct platform_pwm_backlight_data smdkv310_bl_data = {
        .pwm_period_ns  = 1000,
 };
 
+/* I2C module and id for HDMIPHY */
+static struct i2c_board_info hdmiphy_info = {
+       I2C_BOARD_INFO("hdmiphy-exynos4210", 0x38),
+};
+
 static void s5p_tv_setup(void)
 {
        /* direct HPD to HDMI chip */
@@ -388,6 +394,7 @@ static void __init smdkv310_machine_init(void)
 
        s5p_tv_setup();
        s5p_i2c_hdmiphy_set_platdata(NULL);
+       s5p_hdmi_set_platdata(&hdmiphy_info, NULL, 0);
 
        samsung_keypad_set_platdata(&smdkv310_keypad_data);
 
index bc49e5ab200bcf9793a649cdaf760c548b578a76..8b9ee219efb71fed6694c739ff70bc03645c70dc 100644 (file)
@@ -209,7 +209,7 @@ static struct regulator_consumer_supply lp3974_ldo3_consumer[] = {
        REGULATOR_SUPPLY("vusb_a", "s3c-hsotg"),
        REGULATOR_SUPPLY("vdd", "exynos4-hdmi"),
        REGULATOR_SUPPLY("vdd_pll", "exynos4-hdmi"),
-       REGULATOR_SUPPLY("vdd11", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddcore", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo3_data = {
@@ -273,7 +273,7 @@ static struct regulator_init_data lp3974_ldo6_data = {
 };
 
 static struct regulator_consumer_supply lp3974_ldo7_consumer[] = {
-       REGULATOR_SUPPLY("vdd18", "s5p-mipi-csis.0"),
+       REGULATOR_SUPPLY("vddio", "s5p-mipi-csis.0"),
 };
 
 static struct regulator_init_data lp3974_ldo7_data = {
@@ -942,9 +942,7 @@ static struct platform_device cam_s_if_fixed_reg_dev = {
 static struct s5p_platform_mipi_csis mipi_csis_platdata = {
        .clk_rate       = 166000000UL,
        .lanes          = 2,
-       .alignment      = 32,
        .hs_settle      = 12,
-       .phy_enable     = s5p_csis_phy_enable,
 };
 
 #define GPIO_CAM_LEVEL_EN(n)   EXYNOS4_GPE4(n + 3)
@@ -1008,7 +1006,6 @@ static struct s5p_fimc_isp_info universal_camera_sensors[] = {
                .board_info     = &m5mols_board_info,
                .i2c_bus_num    = 0,
                .clk_frequency  = 24000000UL,
-               .csi_data_align = 32,
        },
 };
 
index ca70e5fcc7ac12cbd519d9d8a1b246253fe7f12a..020852d3bdd8bd002710e79aba3e036074fefd55 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/sched.h>
 #include <asm/irq.h>
 #include <asm/mach/irq.h>
+#include <asm/system_misc.h>
 #include <mach/hardware.h>
 
 #define IRQ_SOURCE(base_addr)  (base_addr + 0x00)
index 07f7c226e4cfe6eec6181e5e506655223c2f1e1a..d004d37ad9d8595648dbbf981e56391e58432eda 100644 (file)
@@ -9,7 +9,8 @@ obj-$(CONFIG_SOC_IMX27) += clk-imx27.o mm-imx27.o ehci-imx27.o
 obj-$(CONFIG_SOC_IMX31) += mm-imx3.o cpu-imx31.o clk-imx31.o iomux-imx31.o ehci-imx31.o pm-imx3.o
 obj-$(CONFIG_SOC_IMX35) += mm-imx3.o cpu-imx35.o clk-imx35.o ehci-imx35.o pm-imx3.o
 
-obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o pm-imx5.o cpu_op-mx51.o
+imx5-pm-$(CONFIG_PM) += pm-imx5.o
+obj-$(CONFIG_SOC_IMX5) += cpu-imx5.o mm-imx5.o clk-imx51-imx53.o ehci-imx5.o $(imx5-pm-y) cpu_op-mx51.o
 
 obj-$(CONFIG_COMMON_CLK) += clk-pllv1.o clk-pllv2.o clk-pllv3.o clk-gate2.o \
                            clk-pfd.o clk-busy.o
@@ -70,14 +71,13 @@ obj-$(CONFIG_DEBUG_LL) += lluart.o
 obj-$(CONFIG_HAVE_IMX_GPC) += gpc.o
 obj-$(CONFIG_HAVE_IMX_MMDC) += mmdc.o
 obj-$(CONFIG_HAVE_IMX_SRC) += src.o
-obj-$(CONFIG_CPU_V7) += head-v7.o
-AFLAGS_head-v7.o :=-Wa,-march=armv7-a
-obj-$(CONFIG_SMP) += platsmp.o
+AFLAGS_headsmp.o :=-Wa,-march=armv7-a
+obj-$(CONFIG_SMP) += headsmp.o platsmp.o
 obj-$(CONFIG_HOTPLUG_CPU) += hotplug.o
 obj-$(CONFIG_SOC_IMX6Q) += clk-imx6q.o mach-imx6q.o
 
 ifeq ($(CONFIG_PM),y)
-obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o
+obj-$(CONFIG_SOC_IMX6Q) += pm-imx6q.o headsmp.o
 endif
 
 # i.MX5 based machines
index fdd8cc87c9feee388ca8a94b0fb46fa20305f33a..d20d4795f4eaebeb633c73ec441c36a661949a47 100644 (file)
@@ -222,10 +222,8 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[lcdc_ipg], "ipg", "imx-fb.0");
        clk_register_clkdev(clk[lcdc_ahb], "ahb", "imx-fb.0");
        clk_register_clkdev(clk[wdt_ipg], NULL, "imx2-wdt.0");
-       clk_register_clkdev(clk[ssi1_ipg_per], "per", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi1_ipg], "ipg", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi2_ipg_per], "per", "imx-ssi.1");
-       clk_register_clkdev(clk[ssi2_ipg], "ipg", "imx-ssi.1");
+       clk_register_clkdev(clk[ssi1_ipg], NULL, "imx-ssi.0");
+       clk_register_clkdev(clk[ssi2_ipg], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[esdhc1_ipg_per], "per", "sdhci-esdhc-imx25.0");
        clk_register_clkdev(clk[esdhc1_ipg], "ipg", "sdhci-esdhc-imx25.0");
        clk_register_clkdev(clk[esdhc1_ahb], "ahb", "sdhci-esdhc-imx25.0");
@@ -243,6 +241,6 @@ int __init mx25_clocks_init(void)
        clk_register_clkdev(clk[sdma_ahb], "ahb", "imx35-sdma");
        clk_register_clkdev(clk[iim_ipg], "iim", NULL);
 
-       mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), 54);
+       mxc_timer_init(MX25_IO_ADDRESS(MX25_GPT1_BASE_ADDR), MX25_INT_GPT1);
        return 0;
 }
index f69ca4680049dd9f253e30eec5fc1690569f8d0d..3b6b640eed247ea1b7848c7a7fa01801f0190cde 100644 (file)
@@ -239,8 +239,8 @@ int __init mx27_clocks_init(unsigned long fref)
        clk_register_clkdev(clk[ssi1_ipg_gate], NULL, "imx-ssi.0");
        clk_register_clkdev(clk[ssi2_ipg_gate], NULL, "imx-ssi.1");
        clk_register_clkdev(clk[nfc_baud_gate], NULL, "mxc_nand.0");
-       clk_register_clkdev(clk[vpu_baud_gate], "per", "imx-vpu");
-       clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "imx-vpu");
+       clk_register_clkdev(clk[vpu_baud_gate], "per", "coda-imx27.0");
+       clk_register_clkdev(clk[vpu_ahb_gate], "ahb", "coda-imx27.0");
        clk_register_clkdev(clk[dma_ahb_gate], "ahb", "imx-dma");
        clk_register_clkdev(clk[dma_ipg_gate], "ipg", "imx-dma");
        clk_register_clkdev(clk[fec_ipg_gate], "ipg", "imx27-fec.0");
index c6422fb10bae37756693f3323f79df62e4fc932e..65fb8bcd86cb1652385ee0320679d04a427f8295 100644 (file)
@@ -230,10 +230,8 @@ int __init mx35_clocks_init()
        clk_register_clkdev(clk[ipu_gate], NULL, "mx3_sdc_fb");
        clk_register_clkdev(clk[owire_gate], NULL, "mxc_w1");
        clk_register_clkdev(clk[sdma_gate], NULL, "imx35-sdma");
-       clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.0");
-       clk_register_clkdev(clk[ssi1_div_post], "per", "imx-ssi.0");
-       clk_register_clkdev(clk[ipg], "ipg", "imx-ssi.1");
-       clk_register_clkdev(clk[ssi2_div_post], "per", "imx-ssi.1");
+       clk_register_clkdev(clk[ssi1_gate], NULL, "imx-ssi.0");
+       clk_register_clkdev(clk[ssi2_gate], NULL, "imx-ssi.1");
        /* i.mx35 has the i.mx21 type uart */
        clk_register_clkdev(clk[uart1_gate], "per", "imx21-uart.0");
        clk_register_clkdev(clk[ipg], "ipg", "imx21-uart.0");
index ea89520b6e223fd3ab4db3227574c7299605e265..4233d9e3531d838e3cad29c9d2dceb012606d378 100644 (file)
@@ -152,7 +152,7 @@ enum mx6q_clks {
        ssi2, ssi3, uart_ipg, uart_serial, usboh3, usdhc1, usdhc2, usdhc3,
        usdhc4, vdo_axi, vpu_axi, cko1, pll1_sys, pll2_bus, pll3_usb_otg,
        pll4_audio, pll5_video, pll6_mlb, pll7_usb_host, pll8_enet, ssi1_ipg,
-       ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2,
+       ssi2_ipg, ssi3_ipg, rom, usbphy1, usbphy2, ldb_di0_div_3_5, ldb_di1_div_3_5,
        clk_max
 };
 
@@ -288,8 +288,10 @@ int __init mx6q_clocks_init(void)
        clk[gpu3d_shader]     = imx_clk_divider("gpu3d_shader",     "gpu3d_shader_sel",  base + 0x18, 29, 3);
        clk[ipu1_podf]        = imx_clk_divider("ipu1_podf",        "ipu1_sel",          base + 0x3c, 11, 3);
        clk[ipu2_podf]        = imx_clk_divider("ipu2_podf",        "ipu2_sel",          base + 0x3c, 16, 3);
-       clk[ldb_di0_podf]     = imx_clk_divider("ldb_di0_podf",     "ldb_di0_sel",       base + 0x20, 10, 1);
-       clk[ldb_di1_podf]     = imx_clk_divider("ldb_di1_podf",     "ldb_di1_sel",       base + 0x20, 11, 1);
+       clk[ldb_di0_div_3_5]  = imx_clk_fixed_factor("ldb_di0_div_3_5", "ldb_di0_sel", 2, 7);
+       clk[ldb_di0_podf]     = imx_clk_divider("ldb_di0_podf",     "ldb_di0_div_3_5",       base + 0x20, 10, 1);
+       clk[ldb_di1_div_3_5]  = imx_clk_fixed_factor("ldb_di1_div_3_5", "ldb_di1_sel", 2, 7);
+       clk[ldb_di1_podf]     = imx_clk_divider("ldb_di1_podf",     "ldb_di1_div_3_5",   base + 0x20, 11, 1);
        clk[ipu1_di0_pre]     = imx_clk_divider("ipu1_di0_pre",     "ipu1_di0_pre_sel",  base + 0x34, 3,  3);
        clk[ipu1_di1_pre]     = imx_clk_divider("ipu1_di1_pre",     "ipu1_di1_pre_sel",  base + 0x34, 12, 3);
        clk[ipu2_di0_pre]     = imx_clk_divider("ipu2_di0_pre",     "ipu2_di0_pre_sel",  base + 0x38, 3,  3);
index 436c5720fe6a40255a2c3bc5ab05378c23855e02..04822932cdd1d13c260b4e950ccb51dec9f4ff39 100644 (file)
@@ -17,6 +17,10 @@ extern const struct imx_fsl_usb2_udc_data imx27_fsl_usb2_udc_data;
 #define imx27_add_fsl_usb2_udc(pdata)  \
        imx_add_fsl_usb2_udc(&imx27_fsl_usb2_udc_data, pdata)
 
+extern const struct imx_imx27_coda_data imx27_coda_data;
+#define imx27_add_coda()       \
+       imx_add_imx27_coda(&imx27_coda_data)
+
 extern const struct imx_imx2_wdt_data imx27_imx2_wdt_data;
 #define imx27_add_imx2_wdt()   \
        imx_add_imx2_wdt(&imx27_imx2_wdt_data)
index 20ed2d56c1af6a3109ff3ea10843cda25d2a289e..f8f7437c83b82dbb07307e78895e66bb6af320e6 100644 (file)
@@ -42,22 +42,6 @@ static inline void cpu_enter_lowpower(void)
          : "cc");
 }
 
-static inline void cpu_leave_lowpower(void)
-{
-       unsigned int v;
-
-       asm volatile(
-               "mrc    p15, 0, %0, c1, c0, 0\n"
-       "       orr     %0, %0, %1\n"
-       "       mcr     p15, 0, %0, c1, c0, 0\n"
-       "       mrc     p15, 0, %0, c1, c0, 1\n"
-       "       orr     %0, %0, %2\n"
-       "       mcr     p15, 0, %0, c1, c0, 1\n"
-         : "=&r" (v)
-         : "Ir" (CR_C), "Ir" (0x40)
-         : "cc");
-}
-
 /*
  * platform-specific code to shutdown a CPU
  *
@@ -67,11 +51,10 @@ void platform_cpu_die(unsigned int cpu)
 {
        cpu_enter_lowpower();
        imx_enable_cpu(cpu, false);
-       cpu_do_idle();
-       cpu_leave_lowpower();
 
-       /* We should never return from idle */
-       panic("cpu %d unexpectedly exit from shutdown\n", cpu);
+       /* spin here until hardware takes it down */
+       while (1)
+               ;
 }
 
 int platform_cpu_disable(unsigned int cpu)
index 2c6ab3273f9e4d4a419e54a4f7cde417fdb213a6..5985ed1b8c9875cffc99ab74233147912ae01eca 100644 (file)
@@ -526,7 +526,8 @@ static void __init armadillo5x0_init(void)
        imx31_add_mxc_nand(&armadillo5x0_nand_board_info);
 
        /* set NAND page size to 2k if not configured via boot mode pins */
-       __raw_writel(__raw_readl(MXC_CCM_RCSR) | (1 << 30), MXC_CCM_RCSR);
+       __raw_writel(__raw_readl(mx3_ccm_base + MXC_CCM_RCSR) |
+                                       (1 << 30), mx3_ccm_base + MXC_CCM_RCSR);
 
        /* RTC */
        /* Get RTC IRQ and register the chip */
index f264ddddd47c395404203cdebf43b7dc2206abb0..821d6aac411cb9e5d9d56f8ffb3100b3affa1b6b 100644 (file)
 #include <linux/delay.h>
 #include <linux/dma-mapping.h>
 #include <linux/leds.h>
-#include <linux/memblock.h>
 #include <media/soc_camera.h>
 #include <sound/tlv320aic32x4.h>
 #include <asm/mach-types.h>
 #include <asm/mach/arch.h>
 #include <asm/mach/time.h>
 #include <asm/system_info.h>
+#include <asm/memblock.h>
 #include <mach/common.h>
 #include <mach/hardware.h>
 #include <mach/iomux-mx27.h>
@@ -233,10 +233,8 @@ static void __init visstrim_camera_init(void)
 static void __init visstrim_reserve(void)
 {
        /* reserve 4 MiB for mx2-camera */
-       mx2_camera_base = memblock_alloc(MX2_CAMERA_BUF_SIZE,
+       mx2_camera_base = arm_memblock_steal(3 * MX2_CAMERA_BUF_SIZE,
                        MX2_CAMERA_BUF_SIZE);
-       memblock_free(mx2_camera_base, MX2_CAMERA_BUF_SIZE);
-       memblock_remove(mx2_camera_base, MX2_CAMERA_BUF_SIZE);
 }
 
 /* GPIOs used as events for applications */
@@ -405,6 +403,47 @@ static const struct imx_ssi_platform_data visstrim_m10_ssi_pdata __initconst = {
        .flags                  = IMX_SSI_DMA | IMX_SSI_SYN,
 };
 
+/* coda */
+
+static void __init visstrim_coda_init(void)
+{
+       struct platform_device *pdev;
+       int dma;
+
+       pdev = imx27_add_coda();
+       dma = dma_declare_coherent_memory(&pdev->dev,
+                                         mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+                                         mx2_camera_base + MX2_CAMERA_BUF_SIZE,
+                                         MX2_CAMERA_BUF_SIZE,
+                                         DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+       if (!(dma & DMA_MEMORY_MAP))
+               return;
+}
+
+/* DMA deinterlace */
+static struct platform_device visstrim_deinterlace = {
+       .name = "m2m-deinterlace",
+       .id = 0,
+};
+
+static void __init visstrim_deinterlace_init(void)
+{
+       int ret = -ENOMEM;
+       struct platform_device *pdev = &visstrim_deinterlace;
+       int dma;
+
+       ret = platform_device_register(pdev);
+
+       dma = dma_declare_coherent_memory(&pdev->dev,
+                                         mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+                                         mx2_camera_base + 2 * MX2_CAMERA_BUF_SIZE,
+                                         MX2_CAMERA_BUF_SIZE,
+                                         DMA_MEMORY_MAP | DMA_MEMORY_EXCLUSIVE);
+       if (!(dma & DMA_MEMORY_MAP))
+               return;
+}
+
+
 static void __init visstrim_m10_revision(void)
 {
        int exp_version = 0;
@@ -467,7 +506,9 @@ static void __init visstrim_m10_board_init(void)
        platform_device_register_resndata(NULL, "soc-camera-pdrv", 0, NULL, 0,
                                      &iclink_tvp5150, sizeof(iclink_tvp5150));
        gpio_led_register_device(0, &visstrim_m10_led_data);
+       visstrim_deinterlace_init();
        visstrim_camera_init();
+       visstrim_coda_init();
 }
 
 static void __init visstrim_m10_timer_init(void)
index 5ec0608f2a764a9be584ea1bebbe1339f981a259..045b3f6a387dadef095f2900dc5b786464b525fa 100644 (file)
@@ -71,7 +71,7 @@ soft:
 /* For imx6q sabrelite board: set KSZ9021RN RGMII pad skew */
 static int ksz9021rn_phy_fixup(struct phy_device *phydev)
 {
-       if (IS_ENABLED(CONFIG_PHYLIB)) {
+       if (IS_BUILTIN(CONFIG_PHYLIB)) {
                /* min rx data delay */
                phy_write(phydev, 0x0b, 0x8105);
                phy_write(phydev, 0x0c, 0x0000);
@@ -112,7 +112,7 @@ put_clk:
 
 static void __init imx6q_sabrelite_init(void)
 {
-       if (IS_ENABLED(CONFIG_PHYLIB))
+       if (IS_BUILTIN(CONFIG_PHYLIB))
                phy_register_fixup_for_uid(PHY_ID_KSZ9021, MICREL_PHY_ID_MASK,
                                ksz9021rn_phy_fixup);
        imx6q_sabrelite_cko1_setup();
index a5717558ee892fd61aac83997bb3ccff5411a0df..a13299d758e15540cfd6fef81b399efbe53d1691 100644 (file)
@@ -7,7 +7,8 @@ dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns320.dtb
 dtb-$(CONFIG_MACH_DLINK_KIRKWOOD_DT) += kirkwood-dns325.dtb
 dtb-$(CONFIG_MACH_ICONNECT_DT) += kirkwood-iconnect.dtb
 dtb-$(CONFIG_MACH_IB62X0_DT) += kirkwood-ib62x0.dtb
-dtb-$(CONFIG_MACH_TS219_DT)    += kirkwood-qnap-ts219.dtb
+dtb-$(CONFIG_MACH_TS219_DT)    += kirkwood-ts219-6281.dtb
+dtb-$(CONFIG_MACH_TS219_DT)    += kirkwood-ts219-6282.dtb
 dtb-$(CONFIG_MACH_GOFLEXNET_DT) += kirkwood-goflexnet.dtb
 dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lschlv2.dtb
 dtb-$(CONFIG_MACH_LSXL_DT) += kirkwood-lsxhl.dtb
index bd5ea6913e5bc1b14917def32ede4547d6d95a9a..5ab4a968398155be93d3140894f7fcfbe5825fbf 100644 (file)
@@ -301,7 +301,7 @@ void __init kirkwood_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge00_init(eth_data,
                        GE00_PHYS_BASE, IRQ_KIRKWOOD_GE00_SUM,
-                       IRQ_KIRKWOOD_GE00_ERR);
+                       IRQ_KIRKWOOD_GE00_ERR, 1600);
        /* The interface forgets the MAC address assigned by u-boot if
        the clock is turned off, so claim the clk now. */
        clk_prepare_enable(ge0);
@@ -315,7 +315,7 @@ void __init kirkwood_ge01_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge01_init(eth_data,
                        GE01_PHYS_BASE, IRQ_KIRKWOOD_GE01_SUM,
-                       IRQ_KIRKWOOD_GE01_ERR);
+                       IRQ_KIRKWOOD_GE01_ERR, 1600);
        clk_prepare_enable(ge1);
 }
 
@@ -517,6 +517,13 @@ void __init kirkwood_wdt_init(void)
 void __init kirkwood_init_early(void)
 {
        orion_time_set_base(TIMER_VIRT_BASE);
+
+       /*
+        * Some Kirkwood devices allocate their coherent buffers from atomic
+        * context. Increase size of atomic coherent pool to make sure such
+        * the allocations won't fail.
+        */
+       init_dma_coherent_pool_size(SZ_1M);
 }
 
 int kirkwood_tclk;
index 044a631ce241f437d7c36eed9abb15ef5e329cae..c49b177c15236a1e8c3bc0bf2fa7d719b5132145 100644 (file)
@@ -10,6 +10,7 @@
 
 #include <linux/kernel.h>
 #include <linux/init.h>
+#include <linux/sizes.h>
 #include <linux/platform_device.h>
 #include <linux/mtd/partitions.h>
 #include <linux/ata_platform.h>
index b4899b04e4a921b03b7af45e75f5f831befafbb3..a6c08ede4491dfb2672806de2021b8c95c63848a 100644 (file)
@@ -68,7 +68,7 @@ static int __devinit sram_probe(struct platform_device *pdev)
        struct resource *res;
        int ret = 0;
 
-       if (!pdata && !pdata->pool_name)
+       if (!pdata || !pdata->pool_name)
                return -ENODEV;
 
        info = kzalloc(sizeof(*info), GFP_KERNEL);
index 62b53d710efde1a0a71095b2e9e54186cb454886..a9bc84180d21fb378ff27eafb32bcb2ea81f2e89 100644 (file)
@@ -37,7 +37,7 @@
 #define WIN0_OFF(n)            (BRIDGE_VIRT_BASE + 0x0000 + ((n) << 4))
 #define WIN8_OFF(n)            (BRIDGE_VIRT_BASE + 0x0900 + (((n) - 8) << 4))
 
-static void __init __iomem *win_cfg_base(int win)
+static void __init __iomem *win_cfg_base(const struct orion_addr_map_cfg *cfg, int win)
 {
        /*
         * Find the control register base address for this window.
index 26de7f4880932a038b0c5280a6455299bab8edf4..adea02bb10a34ee8a341b4d92d183be6ca7d9df2 100644 (file)
@@ -213,7 +213,8 @@ void __init mv78xx0_ge00_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge00_init(eth_data,
                        GE00_PHYS_BASE, IRQ_MV78XX0_GE00_SUM,
-                       IRQ_MV78XX0_GE_ERR);
+                       IRQ_MV78XX0_GE_ERR,
+                       MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
@@ -224,7 +225,8 @@ void __init mv78xx0_ge01_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge01_init(eth_data,
                        GE01_PHYS_BASE, IRQ_MV78XX0_GE01_SUM,
-                       NO_IRQ);
+                       NO_IRQ,
+                       MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
index 8dabfe81d07c5f143626f10c57cfb993e87c6a1a..ff886e01a0b0371367ae49f3d0d323e547845478 100644 (file)
@@ -261,7 +261,7 @@ static void __init apx4devkit_init(void)
        enable_clk_enet_out();
 
        if (IS_BUILTIN(CONFIG_PHYLIB))
-               phy_register_fixup_for_uid(PHY_ID_KS8051, MICREL_PHY_ID_MASK,
+               phy_register_fixup_for_uid(PHY_ID_KSZ8051, MICREL_PHY_ID_MASK,
                                           apx4devkit_phy_fixup);
 
        mxsfb_pdata.mode_list = apx4devkit_video_modes;
index dd2db025f7787e590d94bb229cb143559f9a8317..346fd26f3aa62bcbe29757ddaa1c98fb9929c53b 100644 (file)
@@ -62,13 +62,14 @@ config ARCH_OMAP4
        select PM_OPP if PM
        select USB_ARCH_HAS_EHCI if USB_SUPPORT
        select ARM_CPU_SUSPEND if PM
-       select ARCH_NEEDS_CPU_IDLE_COUPLED
+       select ARCH_NEEDS_CPU_IDLE_COUPLED if SMP
 
 config SOC_OMAP5
        bool "TI OMAP5"
        select CPU_V7
        select ARM_GIC
        select HAVE_SMP
+       select ARM_CPU_SUSPEND if PM
 
 comment "OMAP Core Type"
        depends on ARCH_OMAP2
@@ -231,10 +232,11 @@ config MACH_OMAP3_PANDORA
        select OMAP_PACKAGE_CBB
        select REGULATOR_FIXED_VOLTAGE if REGULATOR
 
-config MACH_OMAP3_TOUCHBOOK
+config MACH_TOUCHBOOK
        bool "OMAP3 Touch Book"
        depends on ARCH_OMAP3
        default y
+       select OMAP_PACKAGE_CBB
 
 config MACH_OMAP_3430SDP
        bool "OMAP 3430 SDP board"
index f6a24b3f9c4f7b4dd3e381eb3ff7823444d99e70..34c2c7f59f0a855b2be4ddcd5f2ad2a8995995b1 100644 (file)
@@ -255,7 +255,7 @@ obj-$(CONFIG_MACH_OMAP_3630SDP)             += board-zoom-display.o
 obj-$(CONFIG_MACH_CM_T35)              += board-cm-t35.o
 obj-$(CONFIG_MACH_CM_T3517)            += board-cm-t3517.o
 obj-$(CONFIG_MACH_IGEP0020)            += board-igep0020.o
-obj-$(CONFIG_MACH_OMAP3_TOUCHBOOK)     += board-omap3touchbook.o
+obj-$(CONFIG_MACH_TOUCHBOOK)           += board-omap3touchbook.o
 obj-$(CONFIG_MACH_OMAP_4430SDP)                += board-4430sdp.o
 obj-$(CONFIG_MACH_OMAP4_PANDA)         += board-omap4panda.o
 
index 74915295482ec849e0d0fefe5fc9a22703ee1f2c..28214483aaba24420e96fde47cf5ce91482a0d29 100644 (file)
@@ -554,6 +554,8 @@ static const struct usbhs_omap_board_data igep3_usbhs_bdata __initconst = {
 
 #ifdef CONFIG_OMAP_MUX
 static struct omap_board_mux board_mux[] __initdata = {
+       /* SMSC9221 LAN Controller ETH IRQ (GPIO_176) */
+       OMAP3_MUX(MCSPI1_CS2, OMAP_MUX_MODE4 | OMAP_PIN_INPUT),
        { .reg_offset = OMAP_MUX_TERMINATOR },
 };
 #endif
index ef230a0eb5eb13e5cedde6f0a6c540f6a348eae6..0d362e9f9cb9a9854c32b378c5dd058f2f785327 100644 (file)
@@ -58,6 +58,7 @@
 #include "hsmmc.h"
 #include "common-board-devices.h"
 
+#define OMAP3_EVM_TS_GPIO      175
 #define OMAP3_EVM_EHCI_VBUS    22
 #define OMAP3_EVM_EHCI_SELECT  61
 
index df2534de3361d5b9c2317db5cec7222e5993d2fb..ca07264bd3ae7633d370e3ba9047988fd8153bf4 100644 (file)
@@ -34,6 +34,7 @@
 #include <plat/gpmc.h>
 #include <plat/onenand.h>
 #include <plat/gpmc-smc91x.h>
+#include <plat/omap-pm.h>
 
 #include <mach/board-rx51.h>
 
 #include <../drivers/staging/iio/light/tsl2563.h>
 #include <linux/lis3lv02d.h>
 
+#if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
+#include <media/ir-rx51.h>
+#endif
+
 #include "mux.h"
 #include "hsmmc.h"
 #include "common-board-devices.h"
@@ -1220,6 +1225,30 @@ static void __init rx51_init_tsc2005(void)
                                gpio_to_irq(RX51_TSC2005_IRQ_GPIO);
 }
 
+#if defined(CONFIG_IR_RX51) || defined(CONFIG_IR_RX51_MODULE)
+static struct lirc_rx51_platform_data rx51_lirc_data = {
+       .set_max_mpu_wakeup_lat = omap_pm_set_max_mpu_wakeup_lat,
+       .pwm_timer = 9, /* Use GPT 9 for CIR */
+};
+
+static struct platform_device rx51_lirc_device = {
+       .name           = "lirc_rx51",
+       .id             = -1,
+       .dev            = {
+               .platform_data = &rx51_lirc_data,
+       },
+};
+
+static void __init rx51_init_lirc(void)
+{
+       platform_device_register(&rx51_lirc_device);
+}
+#else
+static void __init rx51_init_lirc(void)
+{
+}
+#endif
+
 void __init rx51_peripherals_init(void)
 {
        rx51_i2c_init();
@@ -1230,6 +1259,7 @@ void __init rx51_peripherals_init(void)
        rx51_init_wl1251();
        rx51_init_tsc2005();
        rx51_init_si4713();
+       rx51_init_lirc();
        spi_register_board_info(rx51_peripherals_spi_board_info,
                                ARRAY_SIZE(rx51_peripherals_spi_board_info));
 
index 25bbcc7ca4dce9794676001167a23f36474fbd86..ae27de8899a69207ac90aca52164bb7ccf37a582 100644 (file)
@@ -1036,13 +1036,13 @@ static struct omap_clk am33xx_clks[] = {
        CLK(NULL,       "mmu_fck",              &mmu_fck,       CK_AM33XX),
        CLK(NULL,       "smartreflex0_fck",     &smartreflex0_fck,      CK_AM33XX),
        CLK(NULL,       "smartreflex1_fck",     &smartreflex1_fck,      CK_AM33XX),
-       CLK(NULL,       "gpt1_fck",             &timer1_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt2_fck",             &timer2_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt3_fck",             &timer3_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt4_fck",             &timer4_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt5_fck",             &timer5_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt6_fck",             &timer6_fck,    CK_AM33XX),
-       CLK(NULL,       "gpt7_fck",             &timer7_fck,    CK_AM33XX),
+       CLK(NULL,       "timer1_fck",           &timer1_fck,    CK_AM33XX),
+       CLK(NULL,       "timer2_fck",           &timer2_fck,    CK_AM33XX),
+       CLK(NULL,       "timer3_fck",           &timer3_fck,    CK_AM33XX),
+       CLK(NULL,       "timer4_fck",           &timer4_fck,    CK_AM33XX),
+       CLK(NULL,       "timer5_fck",           &timer5_fck,    CK_AM33XX),
+       CLK(NULL,       "timer6_fck",           &timer6_fck,    CK_AM33XX),
+       CLK(NULL,       "timer7_fck",           &timer7_fck,    CK_AM33XX),
        CLK(NULL,       "usbotg_fck",           &usbotg_fck,    CK_AM33XX),
        CLK(NULL,       "ieee5000_fck",         &ieee5000_fck,  CK_AM33XX),
        CLK(NULL,       "wdt1_fck",             &wdt1_fck,      CK_AM33XX),
index a0d68dbecfa3bb96cd52226b0f8d7965379d1252..f99e65cfb86223c77ed544d1a8fbe6a0c4ad4b51 100644 (file)
@@ -241,6 +241,52 @@ static void omap3_clkdm_deny_idle(struct clockdomain *clkdm)
                _clkdm_del_autodeps(clkdm);
 }
 
+static int omap3xxx_clkdm_clk_enable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               return 0;
+
+       hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (hwsup) {
+               /* Disable HW transitions when we are changing deps */
+               _disable_hwsup(clkdm);
+               _clkdm_add_autodeps(clkdm);
+               _enable_hwsup(clkdm);
+       } else {
+               if (clkdm->flags & CLKDM_CAN_FORCE_WAKEUP)
+                       omap3_clkdm_wakeup(clkdm);
+       }
+
+       return 0;
+}
+
+static int omap3xxx_clkdm_clk_disable(struct clockdomain *clkdm)
+{
+       bool hwsup = false;
+
+       if (!clkdm->clktrctrl_mask)
+               return 0;
+
+       hwsup = omap2_cm_is_clkdm_in_hwsup(clkdm->pwrdm.ptr->prcm_offs,
+                               clkdm->clktrctrl_mask);
+
+       if (hwsup) {
+               /* Disable HW transitions when we are changing deps */
+               _disable_hwsup(clkdm);
+               _clkdm_del_autodeps(clkdm);
+               _enable_hwsup(clkdm);
+       } else {
+               if (clkdm->flags & CLKDM_CAN_FORCE_SLEEP)
+                       omap3_clkdm_sleep(clkdm);
+       }
+
+       return 0;
+}
+
 struct clkdm_ops omap2_clkdm_operations = {
        .clkdm_add_wkdep        = omap2_clkdm_add_wkdep,
        .clkdm_del_wkdep        = omap2_clkdm_del_wkdep,
@@ -267,6 +313,6 @@ struct clkdm_ops omap3_clkdm_operations = {
        .clkdm_wakeup           = omap3_clkdm_wakeup,
        .clkdm_allow_idle       = omap3_clkdm_allow_idle,
        .clkdm_deny_idle        = omap3_clkdm_deny_idle,
-       .clkdm_clk_enable       = omap2_clkdm_clk_enable,
-       .clkdm_clk_disable      = omap2_clkdm_clk_disable,
+       .clkdm_clk_enable       = omap3xxx_clkdm_clk_enable,
+       .clkdm_clk_disable      = omap3xxx_clkdm_clk_disable,
 };
index 766338fe4d347746ee04eb3961452a7b3f8f6aa9..975f6bda0e0b7a84855a2e6c90f8051df747f6a2 100644 (file)
@@ -67,6 +67,7 @@
 #define OMAP3430_EN_IVA2_DPLL_MASK                     (0x7 << 0)
 
 /* CM_IDLEST_IVA2 */
+#define OMAP3430_ST_IVA2_SHIFT                         0
 #define OMAP3430_ST_IVA2_MASK                          (1 << 0)
 
 /* CM_IDLEST_PLL_IVA2 */
index 14734746457c2bd8bdfcabd1ea4681dc4edab36e..c1875862679fc7092044644bf83e6948ecdbe4c8 100644 (file)
@@ -35,16 +35,6 @@ static struct omap2_mcspi_device_config ads7846_mcspi_config = {
        .turbo_mode     = 0,
 };
 
-/*
- * ADS7846 driver maybe request a gpio according to the value
- * of pdata->get_pendown_state, but we have done this. So set
- * get_pendown_state to avoid twice gpio requesting.
- */
-static int omap3_get_pendown_state(void)
-{
-       return !gpio_get_value(OMAP3_EVM_TS_GPIO);
-}
-
 static struct ads7846_platform_data ads7846_config = {
        .x_max                  = 0x0fff,
        .y_max                  = 0x0fff,
@@ -55,7 +45,6 @@ static struct ads7846_platform_data ads7846_config = {
        .debounce_rep           = 1,
        .gpio_pendown           = -EINVAL,
        .keep_vref_on           = 1,
-       .get_pendown_state      = &omap3_get_pendown_state,
 };
 
 static struct spi_board_info ads7846_spi_board_info __initdata = {
index 4c4ef6a6166ba28b768ee46580b7f35dbafb7885..a0b4a42836ab9f7a29f1757ee410e37a237af00c 100644 (file)
@@ -4,7 +4,6 @@
 #include "twl-common.h"
 
 #define NAND_BLOCK_SIZE        SZ_128K
-#define OMAP3_EVM_TS_GPIO      175
 
 struct mtd_partition;
 struct ads7846_platform_data;
index ee05e193fc61e317b21b368c583f31ce71bbb76b..288bee6cbb76f701b9b675476d87c3b8f16b90cb 100644 (file)
@@ -238,8 +238,9 @@ int __init omap4_idle_init(void)
        for_each_cpu(cpu_id, cpu_online_mask) {
                dev = &per_cpu(omap4_idle_dev, cpu_id);
                dev->cpu = cpu_id;
+#ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
                dev->coupled_cpus = *cpu_online_mask;
-
+#endif
                cpuidle_register_driver(&omap4_idle_driver);
 
                if (cpuidle_register_device(dev)) {
index 471e62a74a166fb64a7486670a54854239cfb3b6..76f9b3c2f586c577668d7f923f0aabff7bbd53a3 100644 (file)
@@ -127,7 +127,6 @@ struct omap_mux_partition {
  * @gpio:      GPIO number
  * @muxnames:  available signal modes for a ball
  * @balls:     available balls on the package
- * @partition: mux partition
  */
 struct omap_mux {
        u16     reg_offset;
index 05fdebfaa195b0e5fc87e33217f24ce1b5c09822..330d4c6e746b703819f95ba41d733a88523b555a 100644 (file)
@@ -46,7 +46,7 @@
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_SPINLOCK(wakeupgen_lock);
-static unsigned int irq_target_cpu[NR_IRQS];
+static unsigned int irq_target_cpu[MAX_IRQS];
 static unsigned int irq_banks = MAX_NR_REG_BANKS;
 static unsigned int max_irqs = MAX_IRQS;
 static unsigned int omap_secure_apis;
index 6ca8e519968d0c4e82e94fb384ab84da90a892b1..37afbd173c2c27969e81f37917d70a767e8fbc2d 100644 (file)
@@ -1889,6 +1889,7 @@ static int _enable(struct omap_hwmod *oh)
                        _enable_sysc(oh);
                }
        } else {
+               _omap4_disable_module(oh);
                _disable_clocks(oh);
                pr_debug("omap_hwmod: %s: _wait_target_ready: %d\n",
                         oh->name, r);
index c9e38200216b2985cb3ef997e530891b8e3b19dd..ce7e6068768f3cebbb4bb8e32ea94e4ae6aca3a3 100644 (file)
@@ -100,9 +100,9 @@ static struct omap_hwmod omap3xxx_mpu_hwmod = {
 
 /* IVA2 (IVA2) */
 static struct omap_hwmod_rst_info omap3xxx_iva_resets[] = {
-       { .name = "logic", .rst_shift = 0 },
-       { .name = "seq0", .rst_shift = 1 },
-       { .name = "seq1", .rst_shift = 2 },
+       { .name = "logic", .rst_shift = 0, .st_shift = 8 },
+       { .name = "seq0", .rst_shift = 1, .st_shift = 9 },
+       { .name = "seq1", .rst_shift = 2, .st_shift = 10 },
 };
 
 static struct omap_hwmod omap3xxx_iva_hwmod = {
@@ -112,6 +112,15 @@ static struct omap_hwmod omap3xxx_iva_hwmod = {
        .rst_lines      = omap3xxx_iva_resets,
        .rst_lines_cnt  = ARRAY_SIZE(omap3xxx_iva_resets),
        .main_clk       = "iva2_ck",
+       .prcm = {
+               .omap2 = {
+                       .module_offs = OMAP3430_IVA2_MOD,
+                       .prcm_reg_id = 1,
+                       .module_bit = OMAP3430_CM_FCLKEN_IVA2_EN_IVA2_SHIFT,
+                       .idlest_reg_id = 1,
+                       .idlest_idle_bit = OMAP3430_ST_IVA2_SHIFT,
+               }
+       },
 };
 
 /* timer class */
index 242aee498ceb21466e33ee04035ed63147e4a615..afb60917a948b64bb3b0ed9b90924facc27fc7f6 100644 (file)
@@ -4210,7 +4210,7 @@ static struct omap_hwmod_ocp_if omap44xx_dsp__iva = {
 };
 
 /* dsp -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_dsp__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_dsp__sl2if = {
        .master         = &omap44xx_dsp_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "dpll_iva_m5x2_ck",
@@ -4828,7 +4828,7 @@ static struct omap_hwmod_ocp_if omap44xx_l3_main_2__iss = {
 };
 
 /* iva -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_iva__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_iva__sl2if = {
        .master         = &omap44xx_iva_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "dpll_iva_m5x2_ck",
@@ -5362,7 +5362,7 @@ static struct omap_hwmod_ocp_if omap44xx_l4_wkup__scrm = {
 };
 
 /* l3_main_2 -> sl2if */
-static struct omap_hwmod_ocp_if omap44xx_l3_main_2__sl2if = {
+static struct omap_hwmod_ocp_if __maybe_unused omap44xx_l3_main_2__sl2if = {
        .master         = &omap44xx_l3_main_2_hwmod,
        .slave          = &omap44xx_sl2if_hwmod,
        .clk            = "l3_div_ck",
@@ -6032,7 +6032,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_abe__dmic,
        &omap44xx_l4_abe__dmic_dma,
        &omap44xx_dsp__iva,
-       &omap44xx_dsp__sl2if,
+       /* &omap44xx_dsp__sl2if, */
        &omap44xx_l4_cfg__dsp,
        &omap44xx_l3_main_2__dss,
        &omap44xx_l4_per__dss,
@@ -6068,7 +6068,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_per__i2c4,
        &omap44xx_l3_main_2__ipu,
        &omap44xx_l3_main_2__iss,
-       &omap44xx_iva__sl2if,
+       /* &omap44xx_iva__sl2if, */
        &omap44xx_l3_main_2__iva,
        &omap44xx_l4_wkup__kbd,
        &omap44xx_l4_cfg__mailbox,
@@ -6099,7 +6099,7 @@ static struct omap_hwmod_ocp_if *omap44xx_hwmod_ocp_ifs[] __initdata = {
        &omap44xx_l4_cfg__cm_core,
        &omap44xx_l4_wkup__prm,
        &omap44xx_l4_wkup__scrm,
-       &omap44xx_l3_main_2__sl2if,
+       /* &omap44xx_l3_main_2__sl2if, */
        &omap44xx_l4_abe__slimbus1,
        &omap44xx_l4_abe__slimbus1_dma,
        &omap44xx_l4_per__slimbus2,
index 2293ba27101b96fae1f387d5b366c5d77181f99b..c95415da23c275b184d2817372a990a371ddaf0c 100644 (file)
@@ -94,7 +94,7 @@ int __init omap4_opp_init(void)
 {
        int r = -ENODEV;
 
-       if (!cpu_is_omap44xx())
+       if (!cpu_is_omap443x())
                return r;
 
        r = omap_init_opp_table(omap44xx_opp_def_list,
index e4fc88c65dbd6a868b6dac07229de3ee3b7791ea..05bd8f02723f2966bfc559ae30b9c33feee9feb3 100644 (file)
@@ -272,21 +272,16 @@ void omap_sram_idle(void)
        per_next_state = pwrdm_read_next_pwrst(per_pwrdm);
        core_next_state = pwrdm_read_next_pwrst(core_pwrdm);
 
-       if (mpu_next_state < PWRDM_POWER_ON) {
-               pwrdm_pre_transition(mpu_pwrdm);
-               pwrdm_pre_transition(neon_pwrdm);
-       }
+       pwrdm_pre_transition(NULL);
 
        /* PER */
        if (per_next_state < PWRDM_POWER_ON) {
-               pwrdm_pre_transition(per_pwrdm);
                per_going_off = (per_next_state == PWRDM_POWER_OFF) ? 1 : 0;
                omap2_gpio_prepare_for_idle(per_going_off);
        }
 
        /* CORE */
        if (core_next_state < PWRDM_POWER_ON) {
-               pwrdm_pre_transition(core_pwrdm);
                if (core_next_state == PWRDM_POWER_OFF) {
                        omap3_core_save_context();
                        omap3_cm_save_context();
@@ -339,20 +334,14 @@ void omap_sram_idle(void)
                        omap2_prm_clear_mod_reg_bits(OMAP3430_AUTO_OFF_MASK,
                                               OMAP3430_GR_MOD,
                                               OMAP3_PRM_VOLTCTRL_OFFSET);
-               pwrdm_post_transition(core_pwrdm);
        }
        omap3_intc_resume_idle();
 
+       pwrdm_post_transition(NULL);
+
        /* PER */
-       if (per_next_state < PWRDM_POWER_ON) {
+       if (per_next_state < PWRDM_POWER_ON)
                omap2_gpio_resume_after_idle();
-               pwrdm_post_transition(per_pwrdm);
-       }
-
-       if (mpu_next_state < PWRDM_POWER_ON) {
-               pwrdm_post_transition(mpu_pwrdm);
-               pwrdm_post_transition(neon_pwrdm);
-       }
 }
 
 static void omap3_pm_idle(void)
index 9f6b83d1b193348a7af9e628cff41956c8684898..91e71d8f46f0aa731c9678e88423490aa1192cf9 100644 (file)
@@ -56,9 +56,13 @@ ppa_por_params:
  * The restore function pointer is stored at CPUx_WAKEUP_NS_PA_ADDR_OFFSET.
  * It returns to the caller for CPU INACTIVE and ON power states or in case
  * CPU failed to transition to targeted OFF/DORMANT state.
+ *
+ * omap4_finish_suspend() calls v7_flush_dcache_all() which doesn't save
+ * stack frame and it expects the caller to take care of it. Hence the entire
+ * stack frame is saved to avoid possible stack corruption.
  */
 ENTRY(omap4_finish_suspend)
-       stmfd   sp!, {lr}
+       stmfd   sp!, {r4-r12, lr}
        cmp     r0, #0x0
        beq     do_WFI                          @ No lowpower state, jump to WFI
 
@@ -226,7 +230,7 @@ scu_gp_clear:
 skip_scu_gp_clear:
        isb
        dsb
-       ldmfd   sp!, {pc}
+       ldmfd   sp!, {r4-r12, pc}
 ENDPROC(omap4_finish_suspend)
 
 /*
index 2ff6d41ec6c6c004ace041b525ec1821d6389653..2ba4f57dda866df44689834370916395ab9a4c3c 100644 (file)
@@ -260,6 +260,7 @@ static u32 notrace dmtimer_read_sched_clock(void)
        return 0;
 }
 
+#ifdef CONFIG_OMAP_32K_TIMER
 /* Setup free-running counter for clocksource */
 static int __init omap2_sync32k_clocksource_init(void)
 {
@@ -299,6 +300,12 @@ static int __init omap2_sync32k_clocksource_init(void)
 
        return ret;
 }
+#else
+static inline int omap2_sync32k_clocksource_init(void)
+{
+       return -ENODEV;
+}
+#endif
 
 static void __init omap2_gptimer_clocksource_init(int gptimer_id,
                                                const char *fck_source)
index de47f170ba50abf2506c363838d7cd82c70109ee..db5ff664237517562766ffdbc34887c6416c272f 100644 (file)
@@ -67,6 +67,7 @@ void __init omap_pmic_init(int bus, u32 clkrate,
                           const char *pmic_type, int pmic_irq,
                           struct twl4030_platform_data *pmic_data)
 {
+       omap_mux_init_signal("sys_nirq", OMAP_PIN_INPUT_PULLUP | OMAP_PIN_OFF_WAKEUPENABLE);
        strncpy(pmic_i2c_board_info.type, pmic_type,
                sizeof(pmic_i2c_board_info.type));
        pmic_i2c_board_info.irq = pmic_irq;
index ca67e825181da68a375a94c32e827a87355ff1d5..0bafad41a8ef27517049086033b865153f25286c 100644 (file)
@@ -109,7 +109,8 @@ void __init orion5x_eth_init(struct mv643xx_eth_platform_data *eth_data)
 {
        orion_ge00_init(eth_data,
                        ORION5X_ETH_PHYS_BASE, IRQ_ORION5X_ETH_SUM,
-                       IRQ_ORION5X_ETH_ERR);
+                       IRQ_ORION5X_ETH_ERR,
+                       MV643XX_TX_CSUM_DEFAULT_LIMIT);
 }
 
 
@@ -203,6 +204,13 @@ void __init orion5x_wdt_init(void)
 void __init orion5x_init_early(void)
 {
        orion_time_set_base(TIMER_VIRT_BASE);
+
+       /*
+        * Some Orion5x devices allocate their coherent buffers from atomic
+        * context. Increase size of atomic coherent pool to make sure such
+        * the allocations won't fail.
+        */
+       init_dma_coherent_pool_size(SZ_1M);
 }
 
 int orion5x_tclk;
index 454831b66037f9c64d37521bf14e118dcc92bc9a..ee99fd56c0439f5bdc22152fa2c530282424fd70 100644 (file)
@@ -24,7 +24,8 @@
 */
 
 enum dma_ch {
-       DMACH_XD0,
+       DMACH_DT_PROP = -1,     /* not yet supported, do not use */
+       DMACH_XD0 = 0,
        DMACH_XD1,
        DMACH_SDI,
        DMACH_SPI0,
index cf10f92856dcbb905712024b1d6a00e55c77cf51..453a6e50db8be95f5fdb8574672fa00aa1671ecb 100644 (file)
@@ -520,13 +520,14 @@ static struct platform_device hdmi_lcdc_device = {
 };
 
 /* GPIO KEY */
-#define GPIO_KEY(c, g, d) { .code = c, .gpio = g, .desc = d, .active_low = 1 }
+#define GPIO_KEY(c, g, d, ...) \
+       { .code = c, .gpio = g, .desc = d, .active_low = 1, __VA_ARGS__ }
 
 static struct gpio_keys_button gpio_buttons[] = {
-       GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW1"),
-       GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW2"),
-       GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW3"),
-       GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW4"),
+       GPIO_KEY(KEY_POWER,     GPIO_PORT99,    "SW3", .wakeup = 1),
+       GPIO_KEY(KEY_BACK,      GPIO_PORT100,   "SW4"),
+       GPIO_KEY(KEY_MENU,      GPIO_PORT97,    "SW5"),
+       GPIO_KEY(KEY_HOME,      GPIO_PORT98,    "SW6"),
 };
 
 static struct gpio_keys_platform_data gpio_key_info = {
@@ -901,8 +902,8 @@ static struct platform_device *eva_devices[] __initdata = {
        &camera_device,
        &ceu0_device,
        &fsi_device,
-       &fsi_hdmi_device,
        &fsi_wm8978_device,
+       &fsi_hdmi_device,
 };
 
 static void __init eva_clock_init(void)
index 53b7ea92c32c119bcfc6d44a96b92fac915363da..3b8a0171c3cb3e30aa7242afcdc65f13cd5c11de 100644 (file)
@@ -346,11 +346,11 @@ static struct resource sh_mmcif_resources[] = {
                .flags  = IORESOURCE_MEM,
        },
        [1] = {
-               .start  = gic_spi(141),
+               .start  = gic_spi(140),
                .flags  = IORESOURCE_IRQ,
        },
        [2] = {
-               .start  = gic_spi(140),
+               .start  = gic_spi(141),
                .flags  = IORESOURCE_IRQ,
        },
 };
index 7ea2b31e31991355cb9304dfcafcc4ab6db6f628..c129542f6aedf1ee69f99f463eb554d31d13ed2d 100644 (file)
@@ -695,6 +695,7 @@ static struct platform_device usbhs0_device = {
  *  - J30 "open"
  *  - modify usbhs1_get_id() USBHS_HOST -> USBHS_GADGET
  *  - add .get_vbus = usbhs_get_vbus in usbhs1_private
+ *  - check usbhs0_device(pio)/usbhs1_device(irq) order in mackerel_devices.
  */
 #define IRQ8 evt2irq(0x0300)
 #define USB_PHY_MODE           (1 << 4)
@@ -1325,8 +1326,8 @@ static struct platform_device *mackerel_devices[] __initdata = {
        &nor_flash_device,
        &smc911x_device,
        &lcdc_device,
-       &usbhs1_device,
        &usbhs0_device,
+       &usbhs1_device,
        &leds_device,
        &fsi_device,
        &fsi_ak4643_device,
index 3a528cf4366cb6addff63fb9e7032948f71f49e2..fcf5a47f47724ccd2be52005adcef685487671a8 100644 (file)
@@ -67,7 +67,7 @@ static struct smsc911x_platform_config smsc911x_platdata = {
 
 static struct platform_device eth_device = {
        .name           = "smsc911x",
-       .id             = 0,
+       .id             = -1,
        .dev  = {
                .platform_data = &smsc911x_platdata,
        },
index ee447404c857ed5794eaf5cbe1153a9e2e2d5505..588555a67d9c438ffb4d0ea0908923056554f635 100644 (file)
@@ -259,9 +259,9 @@ static int sh73a0_set_wake(struct irq_data *data, unsigned int on)
        return 0; /* always allow wakeup */
 }
 
-#define RELOC_BASE 0x1000
+#define RELOC_BASE 0x1200
 
-/* INTCA IRQ pins at INTCS + 0x1000 to make space for GIC+INTC handling */
+/* INTCA IRQ pins at INTCS + RELOC_BASE to make space for GIC+INTC handling */
 #define INTCS_VECT_RELOC(n, vect) INTCS_VECT((n), (vect) + RELOC_BASE)
 
 INTC_IRQ_PINS_32(intca_irq_pins, 0xe6900000,
index c013bbf79cac0d0eff64edfd5221d7815bb04879..53d3d46dec1290b4265a3c3c26d7ffc0449f223e 100644 (file)
@@ -41,7 +41,6 @@ config MACH_HREFV60
 config MACH_SNOWBALL
        bool "U8500 Snowball platform"
        select MACH_MOP500
-       select LEDS_GPIO
        help
          Include support for the snowball development platform.
 
index 996048038743f777e114ff6a48bc2bb682271a46..df15646036aacd9bec713b7beebb926dafa707fa 100644 (file)
@@ -191,9 +191,9 @@ static struct platform_device *db8500_add_msp_i2s(struct device *parent,
        return pdev;
 }
 
-/* Platform device for ASoC U8500 machine */
-static struct platform_device snd_soc_u8500 = {
-               .name = "snd-soc-u8500",
+/* Platform device for ASoC MOP500 machine */
+static struct platform_device snd_soc_mop500 = {
+               .name = "snd-soc-mop500",
                .id = 0,
                .dev = {
                        .platform_data = NULL,
@@ -227,8 +227,8 @@ int mop500_msp_init(struct device *parent)
 {
        struct platform_device *msp1;
 
-       pr_info("%s: Register platform-device 'snd-soc-u8500'.\n", __func__);
-       platform_device_register(&snd_soc_u8500);
+       pr_info("%s: Register platform-device 'snd-soc-mop500'.\n", __func__);
+       platform_device_register(&snd_soc_mop500);
 
        pr_info("Initialize MSP I2S-devices.\n");
        db8500_add_msp_i2s(parent, 0, U8500_MSP0_BASE, IRQ_DB8500_MSP0,
index 38854d40f779bda8b3e4bd1952cfb6c1865a545d..c243e45fad68c9262a0299e348f209d837822870 100644 (file)
@@ -797,6 +797,7 @@ static void __init u8500_init_machine(void)
                                ARRAY_SIZE(mop500_platform_devs));
 
                mop500_sdi_init(parent);
+               mop500_msp_init(parent);
                i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
                i2c_register_board_info(0, mop500_i2c0_devices, i2c0_devs);
                i2c_register_board_info(2, mop500_i2c2_devices,
@@ -804,6 +805,8 @@ static void __init u8500_init_machine(void)
 
                mop500_uib_init();
 
+       } else if (of_machine_is_compatible("calaosystems,snowball-a9500")) {
+               mop500_msp_init(parent);
        } else if (of_machine_is_compatible("st-ericsson,hrefv60+")) {
                /*
                 * The HREFv60 board removed a GPIO expander and routed
@@ -815,6 +818,7 @@ static void __init u8500_init_machine(void)
                                ARRAY_SIZE(mop500_platform_devs));
 
                hrefv60_sdi_init(parent);
+               mop500_msp_init(parent);
 
                i2c0_devs = ARRAY_SIZE(mop500_i2c0_devices);
                i2c0_devs -= NUM_PRE_V60_I2C0_DEVICES;
index 119bc52ab93ed7675d4528a779e97270d308c70e..4e07eec1270dd3b3fa51860fbc735a5d1fb9e18b 100644 (file)
@@ -63,10 +63,11 @@ static int contextidr_notifier(struct notifier_block *unused, unsigned long cmd,
        pid = task_pid_nr(thread->task) << ASID_BITS;
        asm volatile(
        "       mrc     p15, 0, %0, c13, c0, 1\n"
-       "       bfi     %1, %0, #0, %2\n"
-       "       mcr     p15, 0, %1, c13, c0, 1\n"
+       "       and     %0, %0, %2\n"
+       "       orr     %0, %0, %1\n"
+       "       mcr     p15, 0, %0, c13, c0, 1\n"
        : "=r" (contextidr), "+r" (pid)
-       : "I" (ASID_BITS));
+       : "I" (~ASID_MASK));
        isb();
 
        return NOTIFY_OK;
index 4e7d1182e8a3a59270073b5cb3b348e0bd690ef8..13f555d62491e59fbae0127f89e3f2b2395d3abf 100644 (file)
@@ -267,17 +267,19 @@ static void __dma_free_remap(void *cpu_addr, size_t size)
        vunmap(cpu_addr);
 }
 
+#define DEFAULT_DMA_COHERENT_POOL_SIZE SZ_256K
+
 struct dma_pool {
        size_t size;
        spinlock_t lock;
        unsigned long *bitmap;
        unsigned long nr_pages;
        void *vaddr;
-       struct page *page;
+       struct page **pages;
 };
 
 static struct dma_pool atomic_pool = {
-       .size = SZ_256K,
+       .size = DEFAULT_DMA_COHERENT_POOL_SIZE,
 };
 
 static int __init early_coherent_pool(char *p)
@@ -287,6 +289,21 @@ static int __init early_coherent_pool(char *p)
 }
 early_param("coherent_pool", early_coherent_pool);
 
+void __init init_dma_coherent_pool_size(unsigned long size)
+{
+       /*
+        * Catch any attempt to set the pool size too late.
+        */
+       BUG_ON(atomic_pool.vaddr);
+
+       /*
+        * Set architecture specific coherent pool size only if
+        * it has not been changed by kernel command line parameter.
+        */
+       if (atomic_pool.size == DEFAULT_DMA_COHERENT_POOL_SIZE)
+               atomic_pool.size = size;
+}
+
 /*
  * Initialise the coherent pool for atomic allocations.
  */
@@ -297,6 +314,7 @@ static int __init atomic_pool_init(void)
        unsigned long nr_pages = pool->size >> PAGE_SHIFT;
        unsigned long *bitmap;
        struct page *page;
+       struct page **pages;
        void *ptr;
        int bitmap_size = BITS_TO_LONGS(nr_pages) * sizeof(long);
 
@@ -304,21 +322,33 @@ static int __init atomic_pool_init(void)
        if (!bitmap)
                goto no_bitmap;
 
+       pages = kzalloc(nr_pages * sizeof(struct page *), GFP_KERNEL);
+       if (!pages)
+               goto no_pages;
+
        if (IS_ENABLED(CONFIG_CMA))
                ptr = __alloc_from_contiguous(NULL, pool->size, prot, &page);
        else
                ptr = __alloc_remap_buffer(NULL, pool->size, GFP_KERNEL, prot,
                                           &page, NULL);
        if (ptr) {
+               int i;
+
+               for (i = 0; i < nr_pages; i++)
+                       pages[i] = page + i;
+
                spin_lock_init(&pool->lock);
                pool->vaddr = ptr;
-               pool->page = page;
+               pool->pages = pages;
                pool->bitmap = bitmap;
                pool->nr_pages = nr_pages;
                pr_info("DMA: preallocated %u KiB pool for atomic coherent allocations\n",
                       (unsigned)pool->size / 1024);
                return 0;
        }
+
+       kfree(pages);
+no_pages:
        kfree(bitmap);
 no_bitmap:
        pr_err("DMA: failed to allocate %u KiB pool for atomic coherent allocation\n",
@@ -443,27 +473,45 @@ static void *__alloc_from_pool(size_t size, struct page **ret_page)
        if (pageno < pool->nr_pages) {
                bitmap_set(pool->bitmap, pageno, count);
                ptr = pool->vaddr + PAGE_SIZE * pageno;
-               *ret_page = pool->page + pageno;
+               *ret_page = pool->pages[pageno];
+       } else {
+               pr_err_once("ERROR: %u KiB atomic DMA coherent pool is too small!\n"
+                           "Please increase it with coherent_pool= kernel parameter!\n",
+                           (unsigned)pool->size / 1024);
        }
        spin_unlock_irqrestore(&pool->lock, flags);
 
        return ptr;
 }
 
+static bool __in_atomic_pool(void *start, size_t size)
+{
+       struct dma_pool *pool = &atomic_pool;
+       void *end = start + size;
+       void *pool_start = pool->vaddr;
+       void *pool_end = pool->vaddr + pool->size;
+
+       if (start < pool_start || start >= pool_end)
+               return false;
+
+       if (end <= pool_end)
+               return true;
+
+       WARN(1, "Wrong coherent size(%p-%p) from atomic pool(%p-%p)\n",
+            start, end - 1, pool_start, pool_end - 1);
+
+       return false;
+}
+
 static int __free_from_pool(void *start, size_t size)
 {
        struct dma_pool *pool = &atomic_pool;
        unsigned long pageno, count;
        unsigned long flags;
 
-       if (start < pool->vaddr || start > pool->vaddr + pool->size)
+       if (!__in_atomic_pool(start, size))
                return 0;
 
-       if (start + size > pool->vaddr + pool->size) {
-               WARN(1, "freeing wrong coherent size from pool\n");
-               return 0;
-       }
-
        pageno = (start - pool->vaddr) >> PAGE_SHIFT;
        count = size >> PAGE_SHIFT;
 
@@ -1090,10 +1138,22 @@ static int __iommu_remove_mapping(struct device *dev, dma_addr_t iova, size_t si
        return 0;
 }
 
+static struct page **__atomic_get_pages(void *addr)
+{
+       struct dma_pool *pool = &atomic_pool;
+       struct page **pages = pool->pages;
+       int offs = (addr - pool->vaddr) >> PAGE_SHIFT;
+
+       return pages + offs;
+}
+
 static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
 {
        struct vm_struct *area;
 
+       if (__in_atomic_pool(cpu_addr, PAGE_SIZE))
+               return __atomic_get_pages(cpu_addr);
+
        if (dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs))
                return cpu_addr;
 
@@ -1103,6 +1163,34 @@ static struct page **__iommu_get_pages(void *cpu_addr, struct dma_attrs *attrs)
        return NULL;
 }
 
+static void *__iommu_alloc_atomic(struct device *dev, size_t size,
+                                 dma_addr_t *handle)
+{
+       struct page *page;
+       void *addr;
+
+       addr = __alloc_from_pool(size, &page);
+       if (!addr)
+               return NULL;
+
+       *handle = __iommu_create_mapping(dev, &page, size);
+       if (*handle == DMA_ERROR_CODE)
+               goto err_mapping;
+
+       return addr;
+
+err_mapping:
+       __free_from_pool(addr, size);
+       return NULL;
+}
+
+static void __iommu_free_atomic(struct device *dev, struct page **pages,
+                               dma_addr_t handle, size_t size)
+{
+       __iommu_remove_mapping(dev, handle, size);
+       __free_from_pool(page_address(pages[0]), size);
+}
+
 static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
            dma_addr_t *handle, gfp_t gfp, struct dma_attrs *attrs)
 {
@@ -1113,6 +1201,9 @@ static void *arm_iommu_alloc_attrs(struct device *dev, size_t size,
        *handle = DMA_ERROR_CODE;
        size = PAGE_ALIGN(size);
 
+       if (gfp & GFP_ATOMIC)
+               return __iommu_alloc_atomic(dev, size, handle);
+
        pages = __iommu_alloc_buffer(dev, size, gfp);
        if (!pages)
                return NULL;
@@ -1179,6 +1270,11 @@ void arm_iommu_free_attrs(struct device *dev, size_t size, void *cpu_addr,
                return;
        }
 
+       if (__in_atomic_pool(cpu_addr, size)) {
+               __iommu_free_atomic(dev, pages, handle, size);
+               return;
+       }
+
        if (!dma_get_attr(DMA_ATTR_NO_KERNEL_MAPPING, attrs)) {
                unmap_kernel_range((unsigned long)cpu_addr, size);
                vunmap(cpu_addr);
index 6776160618ef0ede79d07b4f6a0873c30df2a1d0..a8ee92da3544926138f68116fbddbc2c55b64dbf 100644 (file)
@@ -55,6 +55,9 @@ extern void __flush_dcache_page(struct address_space *mapping, struct page *page
 /* permanent static mappings from iotable_init() */
 #define VM_ARM_STATIC_MAPPING  0x40000000
 
+/* empty mapping */
+#define VM_ARM_EMPTY_MAPPING   0x20000000
+
 /* mapping type (attributes) for permanent static mappings */
 #define VM_ARM_MTYPE(mt)               ((mt) << 20)
 #define VM_ARM_MTYPE_MASK      (0x1f << 20)
index 4c2d0451e84af1c2a0347a6fe462dd2e3306db3e..c2fa21d0103e0348f2b1f48c886aa11d63809dad 100644 (file)
@@ -807,7 +807,7 @@ static void __init pmd_empty_section_gap(unsigned long addr)
        vm = early_alloc_aligned(sizeof(*vm), __alignof__(*vm));
        vm->addr = (void *)addr;
        vm->size = SECTION_SIZE;
-       vm->flags = VM_IOREMAP | VM_ARM_STATIC_MAPPING;
+       vm->flags = VM_IOREMAP | VM_ARM_EMPTY_MAPPING;
        vm->caller = pmd_empty_section_gap;
        vm_area_add_early(vm);
 }
@@ -820,7 +820,7 @@ static void __init fill_pmd_gaps(void)
 
        /* we're still single threaded hence no lock needed here */
        for (vm = vmlist; vm; vm = vm->next) {
-               if (!(vm->flags & VM_ARM_STATIC_MAPPING))
+               if (!(vm->flags & (VM_ARM_STATIC_MAPPING | VM_ARM_EMPTY_MAPPING)))
                        continue;
                addr = (unsigned long)vm->addr;
                if (addr < next)
@@ -961,8 +961,8 @@ void __init sanity_check_meminfo(void)
                 * Check whether this memory bank would partially overlap
                 * the vmalloc area.
                 */
-               if (__va(bank->start + bank->size) > vmalloc_min ||
-                   __va(bank->start + bank->size) < __va(bank->start)) {
+               if (__va(bank->start + bank->size - 1) >= vmalloc_min ||
+                   __va(bank->start + bank->size - 1) <= __va(bank->start)) {
                        unsigned long newsize = vmalloc_min - __va(bank->start);
                        printk(KERN_NOTICE "Truncating RAM at %.8llx-%.8llx "
                               "to -%.8llx (vmalloc region overlap).\n",
index cb3e3eef55c0b6dec152d8f0ea75212c6c6754fc..6b46cee2f9cd45ec5d6536ef9cfe5611a5962850 100644 (file)
@@ -15,7 +15,11 @@ config IMX_HAVE_PLATFORM_GPIO_KEYS
 
 config IMX_HAVE_PLATFORM_IMX21_HCD
        bool
-       
+
+config IMX_HAVE_PLATFORM_IMX27_CODA
+       bool
+       default y if SOC_IMX27
+
 config IMX_HAVE_PLATFORM_IMX2_WDT
        bool
 
index c11ac8472bebae264374f13db3bdb8fdf3337c6e..76f3195475d06abd27a9114cf3c64301a2ebdf52 100644 (file)
@@ -4,6 +4,7 @@ obj-$(CONFIG_IMX_HAVE_PLATFORM_FSL_USB2_UDC) += platform-fsl-usb2-udc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_GPIO_KEYS) += platform-gpio_keys.o
 obj-y += platform-gpio-mxc.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX21_HCD) += platform-imx21-hcd.o
+obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX27_CODA) += platform-imx27-coda.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMX2_WDT) += platform-imx2-wdt.o
 obj-$(CONFIG_IMX_HAVE_PLATFORM_IMXDI_RTC) += platform-imxdi_rtc.o
 obj-y += platform-imx-dma.o
diff --git a/arch/arm/plat-mxc/devices/platform-imx27-coda.c b/arch/arm/plat-mxc/devices/platform-imx27-coda.c
new file mode 100644 (file)
index 0000000..8b12aac
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2012 Vista Silicon
+ * Javier Martin <javier.martin@vista-silicon.com>
+ *
+ * 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 <mach/hardware.h>
+#include <mach/devices-common.h>
+
+#ifdef CONFIG_SOC_IMX27
+const struct imx_imx27_coda_data imx27_coda_data __initconst = {
+       .iobase = MX27_VPU_BASE_ADDR,
+       .iosize = SZ_512,
+       .irq = MX27_INT_VPU,
+};
+#endif
+
+struct platform_device *__init imx_add_imx27_coda(
+               const struct imx_imx27_coda_data *data)
+{
+       struct resource res[] = {
+               {
+                       .start = data->iobase,
+                       .end = data->iobase + data->iosize - 1,
+                       .flags = IORESOURCE_MEM,
+               }, {
+                       .start = data->irq,
+                       .end = data->irq,
+                       .flags = IORESOURCE_IRQ,
+               },
+       };
+       return imx_add_platform_device_dmamask("coda-imx27", 0, res, 2, NULL,
+                                       0, DMA_BIT_MASK(32));
+}
index 9e3e3d8ae8c24fd56c6ea45d8783697ce991b50b..eaf79d220c9a42d8c707218a5781073038ec2167 100644 (file)
@@ -83,6 +83,14 @@ struct platform_device *__init imx_add_imx21_hcd(
                const struct imx_imx21_hcd_data *data,
                const struct mx21_usbh_platform_data *pdata);
 
+struct imx_imx27_coda_data {
+       resource_size_t iobase;
+       resource_size_t iosize;
+       resource_size_t irq;
+};
+struct platform_device *__init imx_add_imx27_coda(
+               const struct imx_imx27_coda_data *data);
+
 struct imx_imx2_wdt_data {
        int id;
        resource_size_t iobase;
index 627d94f1b010d32d09091bf4f025fabb617bde03..ec466400a2002943de0ccaf840f25266db6149e0 100644 (file)
@@ -98,6 +98,7 @@
 #define MX25_INT_UART1         (NR_IRQS_LEGACY + 45)
 #define MX25_INT_GPIO2         (NR_IRQS_LEGACY + 51)
 #define MX25_INT_GPIO1         (NR_IRQS_LEGACY + 52)
+#define MX25_INT_GPT1          (NR_IRQS_LEGACY + 54)
 #define MX25_INT_FEC           (NR_IRQS_LEGACY + 57)
 
 #define MX25_DMA_REQ_SSI2_RX1  22
index 626ad8cad7a9486d71408f611b4f99b46c85b995..938b50a33439b092202de715e81267b18b5f73cb 100644 (file)
@@ -189,6 +189,7 @@ struct omap_dm_timer *omap_dm_timer_request(void)
                timer->reserved = 1;
                break;
        }
+       spin_unlock_irqrestore(&dm_timer_lock, flags);
 
        if (timer) {
                ret = omap_dm_timer_prepare(timer);
@@ -197,7 +198,6 @@ struct omap_dm_timer *omap_dm_timer_request(void)
                        timer = NULL;
                }
        }
-       spin_unlock_irqrestore(&dm_timer_lock, flags);
 
        if (!timer)
                pr_debug("%s: timer request failed!\n", __func__);
@@ -220,6 +220,7 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
                        break;
                }
        }
+       spin_unlock_irqrestore(&dm_timer_lock, flags);
 
        if (timer) {
                ret = omap_dm_timer_prepare(timer);
@@ -228,7 +229,6 @@ struct omap_dm_timer *omap_dm_timer_request_specific(int id)
                        timer = NULL;
                }
        }
-       spin_unlock_irqrestore(&dm_timer_lock, flags);
 
        if (!timer)
                pr_debug("%s: timer%d request failed!\n", __func__, id);
@@ -258,7 +258,7 @@ EXPORT_SYMBOL_GPL(omap_dm_timer_enable);
 
 void omap_dm_timer_disable(struct omap_dm_timer *timer)
 {
-       pm_runtime_put(&timer->pdev->dev);
+       pm_runtime_put_sync(&timer->pdev->dev);
 }
 EXPORT_SYMBOL_GPL(omap_dm_timer_disable);
 
index 68b180edcfffd0e05c9256aaa153993500177f84..bb5d08a70dbc64ac961945669655e2c47d380750 100644 (file)
@@ -372,7 +372,8 @@ IS_OMAP_TYPE(3430, 0x3430)
 #define cpu_class_is_omap1()   (cpu_is_omap7xx() || cpu_is_omap15xx() || \
                                cpu_is_omap16xx())
 #define cpu_class_is_omap2()   (cpu_is_omap24xx() || cpu_is_omap34xx() || \
-                               cpu_is_omap44xx() || soc_is_omap54xx())
+                               cpu_is_omap44xx() || soc_is_omap54xx() || \
+                               soc_is_am33xx())
 
 /* Various silicon revisions for omap2 */
 #define OMAP242X_CLASS         0x24200024
index 045e320f1067408abc1ef08e6a3667fe911c63f7..324d31b14852e632d614635e40af358d24a36aab 100644 (file)
 # endif
 #endif
 
+#ifdef CONFIG_SOC_AM33XX
+# ifdef OMAP_NAME
+#  undef  MULTI_OMAP2
+#  define MULTI_OMAP2
+# else
+#  define OMAP_NAME am33xx
+# endif
+#endif
+
 #endif /* __PLAT_OMAP_MULTI_H */
index b8d19a136781e4ba89382cc151ba6fe0190ccbc3..7f7b112acccb897b90066a6b8357a943284c3a14 100644 (file)
@@ -110,7 +110,7 @@ static inline void flush(void)
        _DEBUG_LL_ENTRY(mach, AM33XX_UART##p##_BASE, OMAP_PORT_SHIFT,   \
                AM33XXUART##p)
 
-static inline void __arch_decomp_setup(unsigned long arch_id)
+static inline void arch_decomp_setup(void)
 {
        int port = 0;
 
@@ -198,8 +198,6 @@ static inline void __arch_decomp_setup(unsigned long arch_id)
        } while (0);
 }
 
-#define arch_decomp_setup()    __arch_decomp_setup(arch_id)
-
 /*
  * nothing to do
  */
index 766181cb5c95c277b8495966835571059a36dda5..024f3b08db29b0046a58457120259e7b5366a1ca 100644 (file)
@@ -68,6 +68,7 @@
 
 static unsigned long omap_sram_start;
 static void __iomem *omap_sram_base;
+static unsigned long omap_sram_skip;
 static unsigned long omap_sram_size;
 static void __iomem *omap_sram_ceil;
 
@@ -106,6 +107,7 @@ static int is_sram_locked(void)
  */
 static void __init omap_detect_sram(void)
 {
+       omap_sram_skip = SRAM_BOOTLOADER_SZ;
        if (cpu_class_is_omap2()) {
                if (is_sram_locked()) {
                        if (cpu_is_omap34xx()) {
@@ -113,6 +115,7 @@ static void __init omap_detect_sram(void)
                                if ((omap_type() == OMAP2_DEVICE_TYPE_EMU) ||
                                    (omap_type() == OMAP2_DEVICE_TYPE_SEC)) {
                                        omap_sram_size = 0x7000; /* 28K */
+                                       omap_sram_skip += SZ_16K;
                                } else {
                                        omap_sram_size = 0x8000; /* 32K */
                                }
@@ -175,8 +178,10 @@ static void __init omap_map_sram(void)
                return;
 
 #ifdef CONFIG_OMAP4_ERRATA_I688
+       if (cpu_is_omap44xx()) {
                omap_sram_start += PAGE_SIZE;
                omap_sram_size -= SZ_16K;
+       }
 #endif
        if (cpu_is_omap34xx()) {
                /*
@@ -203,8 +208,8 @@ static void __init omap_map_sram(void)
         * Looks like we need to preserve some bootloader code at the
         * beginning of SRAM for jumping to flash for reboot to work...
         */
-       memset_io(omap_sram_base + SRAM_BOOTLOADER_SZ, 0,
-                 omap_sram_size - SRAM_BOOTLOADER_SZ);
+       memset_io(omap_sram_base + omap_sram_skip, 0,
+                 omap_sram_size - omap_sram_skip);
 }
 
 /*
@@ -218,7 +223,7 @@ void *omap_sram_push_address(unsigned long size)
 {
        unsigned long available, new_ceil = (unsigned long)omap_sram_ceil;
 
-       available = omap_sram_ceil - (omap_sram_base + SRAM_BOOTLOADER_SZ);
+       available = omap_sram_ceil - (omap_sram_base + omap_sram_skip);
 
        if (size > available) {
                pr_err("Not enough space in SRAM\n");
index 9148eb0fe33ae9183128f1f4c541e0e93aaba4d3..87f53caef65555fff70accff483c5815d5c02a00 100644 (file)
@@ -291,10 +291,12 @@ static struct platform_device orion_ge00 = {
 void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
                            unsigned long mapbase,
                            unsigned long irq,
-                           unsigned long irq_err)
+                           unsigned long irq_err,
+                           unsigned int tx_csum_limit)
 {
        fill_resources(&orion_ge00_shared, orion_ge00_shared_resources,
                       mapbase + 0x2000, SZ_16K - 1, irq_err);
+       orion_ge00_shared_data.tx_csum_limit = tx_csum_limit;
        ge_complete(&orion_ge00_shared_data,
                    orion_ge00_resources, irq, &orion_ge00_shared,
                    eth_data, &orion_ge00);
@@ -343,10 +345,12 @@ static struct platform_device orion_ge01 = {
 void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
                            unsigned long mapbase,
                            unsigned long irq,
-                           unsigned long irq_err)
+                           unsigned long irq_err,
+                           unsigned int tx_csum_limit)
 {
        fill_resources(&orion_ge01_shared, orion_ge01_shared_resources,
                       mapbase + 0x2000, SZ_16K - 1, irq_err);
+       orion_ge01_shared_data.tx_csum_limit = tx_csum_limit;
        ge_complete(&orion_ge01_shared_data,
                    orion_ge01_resources, irq, &orion_ge01_shared,
                    eth_data, &orion_ge01);
index e00fdb2136090154ea930c9f224365677644444e..ae2377ef63e5d9c455e07a4c8db7590f8935d4dc 100644 (file)
@@ -39,12 +39,14 @@ void __init orion_rtc_init(unsigned long mapbase,
 void __init orion_ge00_init(struct mv643xx_eth_platform_data *eth_data,
                            unsigned long mapbase,
                            unsigned long irq,
-                           unsigned long irq_err);
+                           unsigned long irq_err,
+                           unsigned int tx_csum_limit);
 
 void __init orion_ge01_init(struct mv643xx_eth_platform_data *eth_data,
                            unsigned long mapbase,
                            unsigned long irq,
-                           unsigned long irq_err);
+                           unsigned long irq_err,
+                           unsigned int tx_csum_limit);
 
 void __init orion_ge10_init(struct mv643xx_eth_platform_data *eth_data,
                            unsigned long mapbase,
index 28f898f75380a8ff39036805afdc5b5d40803df8..db98e7021f0daf7507fe55f91f1e73ef761a6dc3 100644 (file)
@@ -430,7 +430,7 @@ s3c2410_dma_canload(struct s3c2410_dma_chan *chan)
  * when necessary.
 */
 
-int s3c2410_dma_enqueue(unsigned int channel, void *id,
+int s3c2410_dma_enqueue(enum dma_ch channel, void *id,
                        dma_addr_t data, int size)
 {
        struct s3c2410_dma_chan *chan = s3c_dma_lookup_channel(channel);
index 65c5eca475e76ef839a16aaef568173a2dc0ee1c..d1116e2dfbeaf57ccd0c2a1aff9ce413d9b57f2a 100644 (file)
@@ -144,6 +144,7 @@ long clk_round_rate(struct clk *clk, unsigned long rate)
 
 int clk_set_rate(struct clk *clk, unsigned long rate)
 {
+       unsigned long flags;
        int ret;
 
        if (IS_ERR(clk))
@@ -159,9 +160,9 @@ int clk_set_rate(struct clk *clk, unsigned long rate)
        if (clk->ops == NULL || clk->ops->set_rate == NULL)
                return -EINVAL;
 
-       spin_lock(&clocks_lock);
+       spin_lock_irqsave(&clocks_lock, flags);
        ret = (clk->ops->set_rate)(clk, rate);
-       spin_unlock(&clocks_lock);
+       spin_unlock_irqrestore(&clocks_lock, flags);
 
        return ret;
 }
@@ -173,17 +174,18 @@ struct clk *clk_get_parent(struct clk *clk)
 
 int clk_set_parent(struct clk *clk, struct clk *parent)
 {
+       unsigned long flags;
        int ret = 0;
 
        if (IS_ERR(clk))
                return -EINVAL;
 
-       spin_lock(&clocks_lock);
+       spin_lock_irqsave(&clocks_lock, flags);
 
        if (clk->ops && clk->ops->set_parent)
                ret = (clk->ops->set_parent)(clk, parent);
 
-       spin_unlock(&clocks_lock);
+       spin_unlock_irqrestore(&clocks_lock, flags);
 
        return ret;
 }
index 07913acb214e062b92c4f7a3893816faceb8ab33..e380e71dc7b0030099196fde6def4c2469fa5aad 100644 (file)
@@ -32,6 +32,8 @@
 #include <linux/platform_data/s3c-hsudc.h>
 #include <linux/platform_data/s3c-hsotg.h>
 
+#include <media/s5p_hdmi.h>
+
 #include <asm/irq.h>
 #include <asm/pmu.h>
 #include <asm/mach/arch.h>
@@ -748,7 +750,8 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
        if (!pd) {
                pd = &default_i2c_data;
 
-               if (soc_is_exynos4210())
+               if (soc_is_exynos4210() ||
+                   soc_is_exynos4212() || soc_is_exynos4412())
                        pd->bus_num = 8;
                else if (soc_is_s5pv210())
                        pd->bus_num = 3;
@@ -759,6 +762,30 @@ void __init s5p_i2c_hdmiphy_set_platdata(struct s3c2410_platform_i2c *pd)
        npd = s3c_set_platdata(pd, sizeof(struct s3c2410_platform_i2c),
                               &s5p_device_i2c_hdmiphy);
 }
+
+struct s5p_hdmi_platform_data s5p_hdmi_def_platdata;
+
+void __init s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
+                                 struct i2c_board_info *mhl_info, int mhl_bus)
+{
+       struct s5p_hdmi_platform_data *pd = &s5p_hdmi_def_platdata;
+
+       if (soc_is_exynos4210() ||
+           soc_is_exynos4212() || soc_is_exynos4412())
+               pd->hdmiphy_bus = 8;
+       else if (soc_is_s5pv210())
+               pd->hdmiphy_bus = 3;
+       else
+               pd->hdmiphy_bus = 0;
+
+       pd->hdmiphy_info = hdmiphy_info;
+       pd->mhl_info = mhl_info;
+       pd->mhl_bus = mhl_bus;
+
+       s3c_set_platdata(pd, sizeof(struct s5p_hdmi_platform_data),
+                        &s5p_device_hdmi);
+}
+
 #endif /* CONFIG_S5P_DEV_I2C_HDMIPHY */
 
 /* I2S */
diff --git a/arch/arm/plat-samsung/include/plat/hdmi.h b/arch/arm/plat-samsung/include/plat/hdmi.h
new file mode 100644 (file)
index 0000000..331d046
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics Co.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 __PLAT_SAMSUNG_HDMI_H
+#define __PLAT_SAMSUNG_HDMI_H __FILE__
+
+extern void s5p_hdmi_set_platdata(struct i2c_board_info *hdmiphy_info,
+                                 struct i2c_board_info *mhl_info, int mhl_bus);
+
+#endif /* __PLAT_SAMSUNG_HDMI_H */
index 64ab65f0fdbc652cd1e0f165ec13bf5a61cc6377..15070284343ee43070c7130d3f8ce6bff6a0b4ff 100644 (file)
@@ -74,7 +74,7 @@ unsigned char pm_uart_udivslot;
 
 #ifdef CONFIG_SAMSUNG_PM_DEBUG
 
-struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
+static struct pm_uart_save uart_save[CONFIG_SERIAL_SAMSUNG_UARTS];
 
 static void s3c_pm_save_uart(unsigned int uart, struct pm_uart_save *save)
 {
index 683c466c0e6a7242200a5f637a981ef011577bf8..147459327601ce50c85269b9b6143f2d072c60cd 100644 (file)
 #include <linux/spinlock.h>
 #include <mach/regs-clock.h>
 
-static int __s5p_mipi_phy_control(struct platform_device *pdev,
-                                 bool on, u32 reset)
+static int __s5p_mipi_phy_control(int id, bool on, u32 reset)
 {
        static DEFINE_SPINLOCK(lock);
        void __iomem *addr;
        unsigned long flags;
-       int pid;
        u32 cfg;
 
-       if (!pdev)
+       id = max(0, id);
+       if (id > 1)
                return -EINVAL;
 
-       pid = (pdev->id == -1) ? 0 : pdev->id;
-
-       if (pid != 0 && pid != 1)
-               return -EINVAL;
-
-       addr = S5P_MIPI_DPHY_CONTROL(pid);
+       addr = S5P_MIPI_DPHY_CONTROL(id);
 
        spin_lock_irqsave(&lock, flags);
 
@@ -52,12 +46,12 @@ static int __s5p_mipi_phy_control(struct platform_device *pdev,
        return 0;
 }
 
-int s5p_csis_phy_enable(struct platform_device *pdev, bool on)
+int s5p_csis_phy_enable(int id, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_SRESETN);
+       return __s5p_mipi_phy_control(id, on, S5P_MIPI_DPHY_SRESETN);
 }
 
 int s5p_dsim_phy_enable(struct platform_device *pdev, bool on)
 {
-       return __s5p_mipi_phy_control(pdev, on, S5P_MIPI_DPHY_MRESETN);
+       return __s5p_mipi_phy_control(pdev->id, on, S5P_MIPI_DPHY_MRESETN);
 }
index f34861920634d15c9de2b1149aa8562a767e64f1..c7092e6057c56e4fa856362263ed4ac49a95d32e 100644 (file)
@@ -38,6 +38,7 @@ config BLACKFIN
        select GENERIC_ATOMIC64
        select GENERIC_IRQ_PROBE
        select IRQ_PER_CPU if SMP
+       select USE_GENERIC_SMP_HELPERS if SMP
        select HAVE_NMI_WATCHDOG if NMI_WATCHDOG
        select GENERIC_SMP_IDLE_THREAD
        select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS
index d3d7e64ca96dacfa41bc298733ef3ed2076c7d3e..66cf00095b8487210b3187cbf41072bc3d80406b 100644 (file)
@@ -20,7 +20,6 @@ endif
 KBUILD_AFLAGS           += $(call cc-option,-mno-fdpic)
 KBUILD_CFLAGS_MODULE    += -mlong-calls
 LDFLAGS                 += -m elf32bfin
-KALLSYMS         += --symbol-prefix=_
 
 KBUILD_DEFCONFIG := BF537-STAMP_defconfig
 
index dc3d144b4bb5930a396f73d9bce48f67ca1c6365..9631598dcc5d120321febba77a85b6309bbdea7b 100644 (file)
@@ -18,6 +18,8 @@
 #define raw_smp_processor_id()  blackfin_core_id()
 
 extern void bfin_relocate_coreb_l1_mem(void);
+extern void arch_send_call_function_single_ipi(int cpu);
+extern void arch_send_call_function_ipi_mask(const struct cpumask *mask);
 
 #if defined(CONFIG_SMP) && defined(CONFIG_ICACHE_FLUSH_L1)
 asmlinkage void blackfin_icache_flush_range_l1(unsigned long *ptr);
index 00bbe672b3b308433445d39461637f3a0d396573..a40151306b77ff301b9b152b205795a6fece4b9c 100644 (file)
@@ -48,10 +48,13 @@ unsigned long blackfin_iflush_l1_entry[NR_CPUS];
 
 struct blackfin_initial_pda __cpuinitdata initial_pda_coreb;
 
-#define BFIN_IPI_TIMER       0
-#define BFIN_IPI_RESCHEDULE   1
-#define BFIN_IPI_CALL_FUNC    2
-#define BFIN_IPI_CPU_STOP     3
+enum ipi_message_type {
+       BFIN_IPI_TIMER,
+       BFIN_IPI_RESCHEDULE,
+       BFIN_IPI_CALL_FUNC,
+       BFIN_IPI_CALL_FUNC_SINGLE,
+       BFIN_IPI_CPU_STOP,
+};
 
 struct blackfin_flush_data {
        unsigned long start;
@@ -60,35 +63,20 @@ struct blackfin_flush_data {
 
 void *secondary_stack;
 
-
-struct smp_call_struct {
-       void (*func)(void *info);
-       void *info;
-       int wait;
-       cpumask_t *waitmask;
-};
-
 static struct blackfin_flush_data smp_flush_data;
 
 static DEFINE_SPINLOCK(stop_lock);
 
-struct ipi_message {
-       unsigned long type;
-       struct smp_call_struct call_struct;
-};
-
 /* A magic number - stress test shows this is safe for common cases */
 #define BFIN_IPI_MSGQ_LEN 5
 
 /* Simple FIFO buffer, overflow leads to panic */
-struct ipi_message_queue {
-       spinlock_t lock;
+struct ipi_data {
        unsigned long count;
-       unsigned long head; /* head of the queue */
-       struct ipi_message ipi_message[BFIN_IPI_MSGQ_LEN];
+       unsigned long bits;
 };
 
-static DEFINE_PER_CPU(struct ipi_message_queue, ipi_msg_queue);
+static DEFINE_PER_CPU(struct ipi_data, bfin_ipi);
 
 static void ipi_cpu_stop(unsigned int cpu)
 {
@@ -129,28 +117,6 @@ static void ipi_flush_icache(void *info)
        blackfin_icache_flush_range(fdata->start, fdata->end);
 }
 
-static void ipi_call_function(unsigned int cpu, struct ipi_message *msg)
-{
-       int wait;
-       void (*func)(void *info);
-       void *info;
-       func = msg->call_struct.func;
-       info = msg->call_struct.info;
-       wait = msg->call_struct.wait;
-       func(info);
-       if (wait) {
-#ifdef __ARCH_SYNC_CORE_DCACHE
-               /*
-                * 'wait' usually means synchronization between CPUs.
-                * Invalidate D cache in case shared data was changed
-                * by func() to ensure cache coherence.
-                */
-               resync_core_dcache();
-#endif
-               cpumask_clear_cpu(cpu, msg->call_struct.waitmask);
-       }
-}
-
 /* Use IRQ_SUPPLE_0 to request reschedule.
  * When returning from interrupt to user space,
  * there is chance to reschedule */
@@ -172,152 +138,95 @@ void ipi_timer(void)
 
 static irqreturn_t ipi_handler_int1(int irq, void *dev_instance)
 {
-       struct ipi_message *msg;
-       struct ipi_message_queue *msg_queue;
+       struct ipi_data *bfin_ipi_data;
        unsigned int cpu = smp_processor_id();
-       unsigned long flags;
+       unsigned long pending;
+       unsigned long msg;
 
        platform_clear_ipi(cpu, IRQ_SUPPLE_1);
 
-       msg_queue = &__get_cpu_var(ipi_msg_queue);
-
-       spin_lock_irqsave(&msg_queue->lock, flags);
-
-       while (msg_queue->count) {
-               msg = &msg_queue->ipi_message[msg_queue->head];
-               switch (msg->type) {
-               case BFIN_IPI_TIMER:
-                       ipi_timer();
-                       break;
-               case BFIN_IPI_RESCHEDULE:
-                       scheduler_ipi();
-                       break;
-               case BFIN_IPI_CALL_FUNC:
-                       ipi_call_function(cpu, msg);
-                       break;
-               case BFIN_IPI_CPU_STOP:
-                       ipi_cpu_stop(cpu);
-                       break;
-               default:
-                       printk(KERN_CRIT "CPU%u: Unknown IPI message 0x%lx\n",
-                              cpu, msg->type);
-                       break;
-               }
-               msg_queue->head++;
-               msg_queue->head %= BFIN_IPI_MSGQ_LEN;
-               msg_queue->count--;
+       bfin_ipi_data = &__get_cpu_var(bfin_ipi);
+
+       while ((pending = xchg(&bfin_ipi_data->bits, 0)) != 0) {
+               msg = 0;
+               do {
+                       msg = find_next_bit(&pending, BITS_PER_LONG, msg + 1);
+                       switch (msg) {
+                       case BFIN_IPI_TIMER:
+                               ipi_timer();
+                               break;
+                       case BFIN_IPI_RESCHEDULE:
+                               scheduler_ipi();
+                               break;
+                       case BFIN_IPI_CALL_FUNC:
+                               generic_smp_call_function_interrupt();
+                               break;
+
+                       case BFIN_IPI_CALL_FUNC_SINGLE:
+                               generic_smp_call_function_single_interrupt();
+                               break;
+
+                       case BFIN_IPI_CPU_STOP:
+                               ipi_cpu_stop(cpu);
+                               break;
+                       }
+               } while (msg < BITS_PER_LONG);
+
+               smp_mb();
        }
-       spin_unlock_irqrestore(&msg_queue->lock, flags);
        return IRQ_HANDLED;
 }
 
-static void ipi_queue_init(void)
+static void bfin_ipi_init(void)
 {
        unsigned int cpu;
-       struct ipi_message_queue *msg_queue;
+       struct ipi_data *bfin_ipi_data;
        for_each_possible_cpu(cpu) {
-               msg_queue = &per_cpu(ipi_msg_queue, cpu);
-               spin_lock_init(&msg_queue->lock);
-               msg_queue->count = 0;
-               msg_queue->head = 0;
+               bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
+               bfin_ipi_data->bits = 0;
+               bfin_ipi_data->count = 0;
        }
 }
 
-static inline void smp_send_message(cpumask_t callmap, unsigned long type,
-                                       void (*func) (void *info), void *info, int wait)
+void send_ipi(const struct cpumask *cpumask, enum ipi_message_type msg)
 {
        unsigned int cpu;
-       struct ipi_message_queue *msg_queue;
-       struct ipi_message *msg;
-       unsigned long flags, next_msg;
-       cpumask_t waitmask; /* waitmask is shared by all cpus */
-
-       cpumask_copy(&waitmask, &callmap);
-       for_each_cpu(cpu, &callmap) {
-               msg_queue = &per_cpu(ipi_msg_queue, cpu);
-               spin_lock_irqsave(&msg_queue->lock, flags);
-               if (msg_queue->count < BFIN_IPI_MSGQ_LEN) {
-                       next_msg = (msg_queue->head + msg_queue->count)
-                                       % BFIN_IPI_MSGQ_LEN;
-                       msg = &msg_queue->ipi_message[next_msg];
-                       msg->type = type;
-                       if (type == BFIN_IPI_CALL_FUNC) {
-                               msg->call_struct.func = func;
-                               msg->call_struct.info = info;
-                               msg->call_struct.wait = wait;
-                               msg->call_struct.waitmask = &waitmask;
-                       }
-                       msg_queue->count++;
-               } else
-                       panic("IPI message queue overflow\n");
-               spin_unlock_irqrestore(&msg_queue->lock, flags);
+       struct ipi_data *bfin_ipi_data;
+       unsigned long flags;
+
+       local_irq_save(flags);
+
+       for_each_cpu(cpu, cpumask) {
+               bfin_ipi_data = &per_cpu(bfin_ipi, cpu);
+               smp_mb();
+               set_bit(msg, &bfin_ipi_data->bits);
+               bfin_ipi_data->count++;
                platform_send_ipi_cpu(cpu, IRQ_SUPPLE_1);
        }
 
-       if (wait) {
-               while (!cpumask_empty(&waitmask))
-                       blackfin_dcache_invalidate_range(
-                               (unsigned long)(&waitmask),
-                               (unsigned long)(&waitmask));
-#ifdef __ARCH_SYNC_CORE_DCACHE
-               /*
-                * Invalidate D cache in case shared data was changed by
-                * other processors to ensure cache coherence.
-                */
-               resync_core_dcache();
-#endif
-       }
+       local_irq_restore(flags);
 }
 
-int smp_call_function(void (*func)(void *info), void *info, int wait)
+void arch_send_call_function_single_ipi(int cpu)
 {
-       cpumask_t callmap;
-
-       preempt_disable();
-       cpumask_copy(&callmap, cpu_online_mask);
-       cpumask_clear_cpu(smp_processor_id(), &callmap);
-       if (!cpumask_empty(&callmap))
-               smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
-       preempt_enable();
-
-       return 0;
+       send_ipi(cpumask_of(cpu), BFIN_IPI_CALL_FUNC_SINGLE);
 }
-EXPORT_SYMBOL_GPL(smp_call_function);
 
-int smp_call_function_single(int cpuid, void (*func) (void *info), void *info,
-                               int wait)
+void arch_send_call_function_ipi_mask(const struct cpumask *mask)
 {
-       unsigned int cpu = cpuid;
-       cpumask_t callmap;
-
-       if (cpu_is_offline(cpu))
-               return 0;
-       cpumask_clear(&callmap);
-       cpumask_set_cpu(cpu, &callmap);
-
-       smp_send_message(callmap, BFIN_IPI_CALL_FUNC, func, info, wait);
-
-       return 0;
+       send_ipi(mask, BFIN_IPI_CALL_FUNC);
 }
-EXPORT_SYMBOL_GPL(smp_call_function_single);
 
 void smp_send_reschedule(int cpu)
 {
-       cpumask_t callmap;
-       /* simply trigger an ipi */
-
-       cpumask_clear(&callmap);
-       cpumask_set_cpu(cpu, &callmap);
-
-       smp_send_message(callmap, BFIN_IPI_RESCHEDULE, NULL, NULL, 0);
+       send_ipi(cpumask_of(cpu), BFIN_IPI_RESCHEDULE);
 
        return;
 }
 
 void smp_send_msg(const struct cpumask *mask, unsigned long type)
 {
-       smp_send_message(*mask, type, NULL, NULL, 0);
+       send_ipi(mask, type);
 }
 
 void smp_timer_broadcast(const struct cpumask *mask)
@@ -333,7 +242,7 @@ void smp_send_stop(void)
        cpumask_copy(&callmap, cpu_online_mask);
        cpumask_clear_cpu(smp_processor_id(), &callmap);
        if (!cpumask_empty(&callmap))
-               smp_send_message(callmap, BFIN_IPI_CPU_STOP, NULL, NULL, 0);
+               send_ipi(&callmap, BFIN_IPI_CPU_STOP);
 
        preempt_enable();
 
@@ -436,7 +345,7 @@ void __init smp_prepare_boot_cpu(void)
 void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        platform_prepare_cpus(max_cpus);
-       ipi_queue_init();
+       bfin_ipi_init();
        platform_request_ipi(IRQ_SUPPLE_0, ipi_handler_int0);
        platform_request_ipi(IRQ_SUPPLE_1, ipi_handler_int1);
 }
index 3af601e31e66ea5180ee498b04009c431f33e989..f08e89183cda452844fda74bc27a4db8823647d1 100644 (file)
@@ -2,6 +2,7 @@ include include/asm-generic/Kbuild.asm
 
 generic-y += atomic.h
 generic-y += auxvec.h
+generic-y += barrier.h
 generic-y += bitsperlong.h
 generic-y += bugs.h
 generic-y += cputime.h
diff --git a/arch/c6x/include/asm/barrier.h b/arch/c6x/include/asm/barrier.h
deleted file mode 100644 (file)
index 538240e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *  Port on Texas Instruments TMS320C6x architecture
- *
- *  Copyright (C) 2004, 2009, 2010, 2011 Texas Instruments Incorporated
- *  Author: Aurelien Jacquiot (aurelien.jacquiot@jaluna.com)
- *
- *  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.
- */
-#ifndef _ASM_C6X_BARRIER_H
-#define _ASM_C6X_BARRIER_H
-
-#define nop()                    asm("NOP\n");
-
-#define mb()                     barrier()
-#define rmb()                    barrier()
-#define wmb()                    barrier()
-#define set_mb(var, value)       do { var = value;  mb(); } while (0)
-#define set_wmb(var, value)      do { var = value; wmb(); } while (0)
-
-#define smp_mb()                barrier()
-#define smp_rmb()               barrier()
-#define smp_wmb()               barrier()
-#define smp_read_barrier_depends()     do { } while (0)
-
-#endif /* _ASM_C6X_BARRIER_H */
index 75f9ee967ea71cc696c3ed9cc5efb390b4ed209a..9cd13b4ce42ba9eb4367be63010802a632577629 100644 (file)
@@ -146,9 +146,3 @@ struct clk_ops clk_ops1 = {
 };
 #endif /* MCFPM_PPMCR1 */
 #endif /* MCFPM_PPMCR0 */
-
-struct clk *devm_clk_get(struct device *dev, const char *id)
-{
-       return NULL;
-}
-EXPORT_SYMBOL(devm_clk_get);
index 331d574df99c8d86ecdce41c9366164fac63f396..faf65286574e9f28d32d9cf31e1c097afcfc7acb 100644 (file)
@@ -89,6 +89,7 @@ config ATH79
        select CEVT_R4K
        select CSRC_R4K
        select DMA_NONCOHERENT
+       select HAVE_CLK
        select IRQ_CPU
        select MIPS_MACHINE
        select SYS_HAS_CPU_MIPS32_R2
index 99969484c475c7fc7366d12fa50efd495656a9b9..a124c251c0c92a2bbbcc8f86ab2674aa5a8ad6a4 100644 (file)
@@ -228,6 +228,8 @@ static int mtx1_pci_idsel(unsigned int devsel, int assert)
         * adapter on the mtx-1 "singleboard" variant. It triggers a custom
         * logic chip connected to EXT_IO3 (GPIO1) to suppress IDSEL signals.
         */
+       udelay(1);
+
        if (assert && devsel != 0)
                /* Suppress signal to Cardbus */
                alchemy_gpio_set_value(1, 0);   /* set EXT_IO3 OFF */
index 36e9570e7bc4a250fbbc05c6312c5b2bf53adcb5..b2a2311ec85b492d1dbbbd22df5a57db0ba978c4 100644 (file)
@@ -145,6 +145,8 @@ static void __init ar7240_usb_setup(void)
 
        ath79_ohci_resources[0].start = AR7240_OHCI_BASE;
        ath79_ohci_resources[0].end = AR7240_OHCI_BASE + AR7240_OHCI_SIZE - 1;
+       ath79_ohci_resources[1].start = ATH79_CPU_IRQ_USB;
+       ath79_ohci_resources[1].end = ATH79_CPU_IRQ_USB;
        platform_device_register(&ath79_ohci_device);
 }
 
index 29054f211832505d371930d3e13f752af56f69f3..48fe762d2526885908c192545dbc70fa69d4cb9c 100644 (file)
@@ -188,8 +188,10 @@ void __init ath79_gpio_init(void)
 
        if (soc_is_ar71xx())
                ath79_gpio_count = AR71XX_GPIO_COUNT;
-       else if (soc_is_ar724x())
-               ath79_gpio_count = AR724X_GPIO_COUNT;
+       else if (soc_is_ar7240())
+               ath79_gpio_count = AR7240_GPIO_COUNT;
+       else if (soc_is_ar7241() || soc_is_ar7242())
+               ath79_gpio_count = AR7241_GPIO_COUNT;
        else if (soc_is_ar913x())
                ath79_gpio_count = AR913X_GPIO_COUNT;
        else if (soc_is_ar933x())
index e39f73048d4f653c48ba3b52a31976f290699bae..f1c9c3e2f678146e83772f3c7cb05a0989743fce 100644 (file)
@@ -106,11 +106,15 @@ int __init bcm63xx_spi_register(void)
        if (BCMCPU_IS_6338() || BCMCPU_IS_6348()) {
                spi_resources[0].end += BCM_6338_RSET_SPI_SIZE - 1;
                spi_pdata.fifo_size = SPI_6338_MSG_DATA_SIZE;
+               spi_pdata.msg_type_shift = SPI_6338_MSG_TYPE_SHIFT;
+               spi_pdata.msg_ctl_width = SPI_6338_MSG_CTL_WIDTH;
        }
 
        if (BCMCPU_IS_6358() || BCMCPU_IS_6368()) {
                spi_resources[0].end += BCM_6358_RSET_SPI_SIZE - 1;
                spi_pdata.fifo_size = SPI_6358_MSG_DATA_SIZE;
+               spi_pdata.msg_type_shift = SPI_6358_MSG_TYPE_SHIFT;
+               spi_pdata.msg_ctl_width = SPI_6358_MSG_CTL_WIDTH;
        }
 
        bcm63xx_spi_regs_init();
index 7fb1f222b8a538b9b000e99375899f37a0c069a9..274cd4fad30c4810f29a420e2dc1e4b139adba73 100644 (file)
@@ -61,6 +61,12 @@ static void octeon_irq_set_ciu_mapping(int irq, int line, int bit,
        octeon_irq_ciu_to_irq[line][bit] = irq;
 }
 
+static void octeon_irq_force_ciu_mapping(struct irq_domain *domain,
+                                        int irq, int line, int bit)
+{
+       irq_domain_associate(domain, irq, line << 6 | bit);
+}
+
 static int octeon_coreid_for_cpu(int cpu)
 {
 #ifdef CONFIG_SMP
@@ -183,19 +189,9 @@ static void __init octeon_irq_init_core(void)
                mutex_init(&cd->core_irq_mutex);
 
                irq = OCTEON_IRQ_SW0 + i;
-               switch (irq) {
-               case OCTEON_IRQ_TIMER:
-               case OCTEON_IRQ_SW0:
-               case OCTEON_IRQ_SW1:
-               case OCTEON_IRQ_5:
-               case OCTEON_IRQ_PERF:
-                       irq_set_chip_data(irq, cd);
-                       irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
-                                                handle_percpu_irq);
-                       break;
-               default:
-                       break;
-               }
+               irq_set_chip_data(irq, cd);
+               irq_set_chip_and_handler(irq, &octeon_irq_chip_core,
+                                        handle_percpu_irq);
        }
 }
 
@@ -890,7 +886,6 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
        unsigned int type;
        unsigned int pin;
        unsigned int trigger;
-       struct octeon_irq_gpio_domain_data *gpiod;
 
        if (d->of_node != node)
                return -EINVAL;
@@ -925,8 +920,7 @@ static int octeon_irq_gpio_xlat(struct irq_domain *d,
                break;
        }
        *out_type = type;
-       gpiod = d->host_data;
-       *out_hwirq = gpiod->base_hwirq + pin;
+       *out_hwirq = pin;
 
        return 0;
 }
@@ -996,19 +990,21 @@ static int octeon_irq_ciu_map(struct irq_domain *d,
 static int octeon_irq_gpio_map(struct irq_domain *d,
                               unsigned int virq, irq_hw_number_t hw)
 {
-       unsigned int line = hw >> 6;
-       unsigned int bit = hw & 63;
+       struct octeon_irq_gpio_domain_data *gpiod = d->host_data;
+       unsigned int line, bit;
 
        if (!octeon_irq_virq_in_range(virq))
                return -EINVAL;
 
+       hw += gpiod->base_hwirq;
+       line = hw >> 6;
+       bit = hw & 63;
        if (line > 1 || octeon_irq_ciu_to_irq[line][bit] != 0)
                return -EINVAL;
 
        octeon_irq_set_ciu_mapping(virq, line, bit,
                                   octeon_irq_gpio_chip,
                                   octeon_irq_handle_gpio);
-
        return 0;
 }
 
@@ -1149,6 +1145,7 @@ static void __init octeon_irq_init_ciu(void)
        struct irq_chip *chip_wd;
        struct device_node *gpio_node;
        struct device_node *ciu_node;
+       struct irq_domain *ciu_domain = NULL;
 
        octeon_irq_init_ciu_percpu();
        octeon_irq_setup_secondary = octeon_irq_setup_secondary_ciu;
@@ -1177,31 +1174,6 @@ static void __init octeon_irq_init_ciu(void)
        /* Mips internal */
        octeon_irq_init_core();
 
-       /* CIU_0 */
-       for (i = 0; i < 16; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WORKQ0, 0, i + 0, chip, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
-
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_INT0, 0, i + 36, chip, handle_level_irq);
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_PCI_MSI0, 0, i + 40, chip, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_RML, 0, 46, chip, handle_level_irq);
-       for (i = 0; i < 4; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_TIMER0, 0, i + 52, chip, handle_edge_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB0, 0, 56, chip, handle_level_irq);
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_BOOTDMA, 0, 63, chip, handle_level_irq);
-
-       /* CIU_1 */
-       for (i = 0; i < 16; i++)
-               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
-
-       octeon_irq_set_ciu_mapping(OCTEON_IRQ_USB1, 1, 17, chip, handle_level_irq);
-
        gpio_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-gpio");
        if (gpio_node) {
                struct octeon_irq_gpio_domain_data *gpiod;
@@ -1219,10 +1191,35 @@ static void __init octeon_irq_init_ciu(void)
 
        ciu_node = of_find_compatible_node(NULL, NULL, "cavium,octeon-3860-ciu");
        if (ciu_node) {
-               irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
+               ciu_domain = irq_domain_add_tree(ciu_node, &octeon_irq_domain_ciu_ops, NULL);
                of_node_put(ciu_node);
        } else
-               pr_warn("Cannot find device node for cavium,octeon-3860-ciu.\n");
+               panic("Cannot find device node for cavium,octeon-3860-ciu.");
+
+       /* CIU_0 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_WORKQ0, 0, i + 0);
+
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX0, 0, 32, chip_mbox, handle_percpu_irq);
+       octeon_irq_set_ciu_mapping(OCTEON_IRQ_MBOX1, 0, 33, chip_mbox, handle_percpu_irq);
+
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_INT0, 0, i + 36);
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_PCI_MSI0, 0, i + 40);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_RML, 0, 46);
+       for (i = 0; i < 4; i++)
+               octeon_irq_force_ciu_mapping(ciu_domain, i + OCTEON_IRQ_TIMER0, 0, i + 52);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB0, 0, 56);
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_BOOTDMA, 0, 63);
+
+       /* CIU_1 */
+       for (i = 0; i < 16; i++)
+               octeon_irq_set_ciu_mapping(i + OCTEON_IRQ_WDOG0, 1, i + 0, chip_wd, handle_level_irq);
+
+       octeon_irq_force_ciu_mapping(ciu_domain, OCTEON_IRQ_USB1, 1, 17);
 
        /* Enable the CIU lines */
        set_c0_status(STATUSF_IP3 | STATUSF_IP2);
index 1caa78ad06d5833306ee367cd44fbefe5dbd6fe3..dde504477fac1521e95f2fe60b75c7ac2fd8e5aa 100644 (file)
 #define AR71XX_GPIO_REG_FUNC           0x28
 
 #define AR71XX_GPIO_COUNT              16
-#define AR724X_GPIO_COUNT              18
+#define AR7240_GPIO_COUNT              18
+#define AR7241_GPIO_COUNT              20
 #define AR913X_GPIO_COUNT              22
 #define AR933X_GPIO_COUNT              30
 #define AR934X_GPIO_COUNT              23
index 4476fa03bf36d5eee19b26e1443b697eb4c33502..6ddae926bf79717b95a709d71c40a99a888a310a 100644 (file)
@@ -42,7 +42,6 @@
 #define cpu_has_mips64r1       0
 #define cpu_has_mips64r2       0
 
-#define cpu_has_dsp            0
 #define cpu_has_mipsmt         0
 
 #define cpu_has_64bits         0
index 7d98dbe5d4b5ef9de38b25717747436e08e6179e..c9bae1362606aac10d79c921f3c8b7374cfc1ba5 100644 (file)
@@ -9,6 +9,8 @@ int __init bcm63xx_spi_register(void);
 
 struct bcm63xx_spi_pdata {
        unsigned int    fifo_size;
+       unsigned int    msg_type_shift;
+       unsigned int    msg_ctl_width;
        int             bus_num;
        int             num_chipselect;
        u32             speed_hz;
index 4ccc2a748aff2db6913dab0e8b67e1eb6fbceeb8..61f2a2a5099d02ad281290c675604a4e897e9bf9 100644 (file)
 #define SPI_6338_FILL_BYTE             0x07
 #define SPI_6338_MSG_TAIL              0x09
 #define SPI_6338_RX_TAIL               0x0b
-#define SPI_6338_MSG_CTL               0x40
+#define SPI_6338_MSG_CTL               0x40    /* 8-bits register */
+#define SPI_6338_MSG_CTL_WIDTH         8
 #define SPI_6338_MSG_DATA              0x41
 #define SPI_6338_MSG_DATA_SIZE         0x3f
 #define SPI_6338_RX_DATA               0x80
 #define SPI_6348_FILL_BYTE             0x07
 #define SPI_6348_MSG_TAIL              0x09
 #define SPI_6348_RX_TAIL               0x0b
-#define SPI_6348_MSG_CTL               0x40
+#define SPI_6348_MSG_CTL               0x40    /* 8-bits register */
+#define SPI_6348_MSG_CTL_WIDTH         8
 #define SPI_6348_MSG_DATA              0x41
 #define SPI_6348_MSG_DATA_SIZE         0x3f
 #define SPI_6348_RX_DATA               0x80
 
 /* BCM 6358 SPI core */
 #define SPI_6358_MSG_CTL               0x00    /* 16-bits register */
+#define SPI_6358_MSG_CTL_WIDTH         16
 #define SPI_6358_MSG_DATA              0x02
 #define SPI_6358_MSG_DATA_SIZE         0x21e
 #define SPI_6358_RX_DATA               0x400
 
 /* BCM 6358 SPI core */
 #define SPI_6368_MSG_CTL               0x00    /* 16-bits register */
+#define SPI_6368_MSG_CTL_WIDTH         16
 #define SPI_6368_MSG_DATA              0x02
 #define SPI_6368_MSG_DATA_SIZE         0x21e
 #define SPI_6368_RX_DATA               0x400
 #define SPI_HD_W                       0x01
 #define SPI_HD_R                       0x02
 #define SPI_BYTE_CNT_SHIFT             0
-#define SPI_MSG_TYPE_SHIFT             14
+#define SPI_6338_MSG_TYPE_SHIFT                6
+#define SPI_6348_MSG_TYPE_SHIFT                6
+#define SPI_6358_MSG_TYPE_SHIFT                14
+#define SPI_6368_MSG_TYPE_SHIFT                14
 
 /* Command */
 #define SPI_CMD_NOOP                   0x00
index 418992042f6fcbc23f1612a82ee886cd969c5fa5..c22a3078bf11b69f2da21547fc1c337da7b51206 100644 (file)
@@ -21,14 +21,10 @@ enum octeon_irq {
        OCTEON_IRQ_TIMER,
 /* sources in CIU_INTX_EN0 */
        OCTEON_IRQ_WORKQ0,
-       OCTEON_IRQ_GPIO0 = OCTEON_IRQ_WORKQ0 + 16,
-       OCTEON_IRQ_WDOG0 = OCTEON_IRQ_GPIO0 + 16,
+       OCTEON_IRQ_WDOG0 = OCTEON_IRQ_WORKQ0 + 16,
        OCTEON_IRQ_WDOG15 = OCTEON_IRQ_WDOG0 + 15,
        OCTEON_IRQ_MBOX0 = OCTEON_IRQ_WDOG0 + 16,
        OCTEON_IRQ_MBOX1,
-       OCTEON_IRQ_UART0,
-       OCTEON_IRQ_UART1,
-       OCTEON_IRQ_UART2,
        OCTEON_IRQ_PCI_INT0,
        OCTEON_IRQ_PCI_INT1,
        OCTEON_IRQ_PCI_INT2,
@@ -38,8 +34,6 @@ enum octeon_irq {
        OCTEON_IRQ_PCI_MSI2,
        OCTEON_IRQ_PCI_MSI3,
 
-       OCTEON_IRQ_TWSI,
-       OCTEON_IRQ_TWSI2,
        OCTEON_IRQ_RML,
        OCTEON_IRQ_TIMER0,
        OCTEON_IRQ_TIMER1,
@@ -47,8 +41,6 @@ enum octeon_irq {
        OCTEON_IRQ_TIMER3,
        OCTEON_IRQ_USB0,
        OCTEON_IRQ_USB1,
-       OCTEON_IRQ_MII0,
-       OCTEON_IRQ_MII1,
        OCTEON_IRQ_BOOTDMA,
 #ifndef CONFIG_PCI_MSI
        OCTEON_IRQ_LAST = 127
index 7531ecd654d651df630d1d520e71f762c47547e3..dca8bce8c7abbe47473920ca6d9e28eb3c235dc9 100644 (file)
@@ -10,6 +10,7 @@ struct mod_arch_specific {
        struct list_head dbe_list;
        const struct exception_table_entry *dbe_start;
        const struct exception_table_entry *dbe_end;
+       struct mips_hi16 *r_mips_hi16_list;
 };
 
 typedef uint8_t Elf64_Byte;            /* Type for a 8-bit quantity.  */
index a37d12b3b61c0b3c2db45cc6a37f44fc4e6eac52..afe9e0e03fe96c5b7a710abe19075d9cf4a4f87b 100644 (file)
 
 #ifdef CONFIG_SYNC_R4K
 
-extern void synchronise_count_master(void);
-extern void synchronise_count_slave(void);
+extern void synchronise_count_master(int cpu);
+extern void synchronise_count_slave(int cpu);
 
 #else
 
-static inline void synchronise_count_master(void)
+static inline void synchronise_count_master(int cpu)
 {
 }
 
-static inline void synchronise_count_slave(void)
+static inline void synchronise_count_slave(int cpu)
 {
 }
 
index a5066b1c3de37185896fe529839c5133a158ccb0..4f8c3cba8c0c45180cdabe08ac05aa43e652395f 100644 (file)
@@ -39,8 +39,6 @@ struct mips_hi16 {
        Elf_Addr value;
 };
 
-static struct mips_hi16 *mips_hi16_list;
-
 static LIST_HEAD(dbe_list);
 static DEFINE_SPINLOCK(dbe_lock);
 
@@ -128,8 +126,8 @@ static int apply_r_mips_hi16_rel(struct module *me, u32 *location, Elf_Addr v)
 
        n->addr = (Elf_Addr *)location;
        n->value = v;
-       n->next = mips_hi16_list;
-       mips_hi16_list = n;
+       n->next = me->arch.r_mips_hi16_list;
+       me->arch.r_mips_hi16_list = n;
 
        return 0;
 }
@@ -142,18 +140,28 @@ static int apply_r_mips_hi16_rela(struct module *me, u32 *location, Elf_Addr v)
        return 0;
 }
 
+static void free_relocation_chain(struct mips_hi16 *l)
+{
+       struct mips_hi16 *next;
+
+       while (l) {
+               next = l->next;
+               kfree(l);
+               l = next;
+       }
+}
+
 static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
 {
        unsigned long insnlo = *location;
+       struct mips_hi16 *l;
        Elf_Addr val, vallo;
 
        /* Sign extend the addend we extract from the lo insn.  */
        vallo = ((insnlo & 0xffff) ^ 0x8000) - 0x8000;
 
-       if (mips_hi16_list != NULL) {
-               struct mips_hi16 *l;
-
-               l = mips_hi16_list;
+       if (me->arch.r_mips_hi16_list != NULL) {
+               l = me->arch.r_mips_hi16_list;
                while (l != NULL) {
                        struct mips_hi16 *next;
                        unsigned long insn;
@@ -188,7 +196,7 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
                        l = next;
                }
 
-               mips_hi16_list = NULL;
+               me->arch.r_mips_hi16_list = NULL;
        }
 
        /*
@@ -201,6 +209,9 @@ static int apply_r_mips_lo16_rel(struct module *me, u32 *location, Elf_Addr v)
        return 0;
 
 out_danger:
+       free_relocation_chain(l);
+       me->arch.r_mips_hi16_list = NULL;
+
        pr_err("module %s: dangerous R_MIPS_LO16 REL relocation\n", me->name);
 
        return -ENOEXEC;
@@ -273,6 +284,7 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
        pr_debug("Applying relocate section %u to %u\n", relsec,
               sechdrs[relsec].sh_info);
 
+       me->arch.r_mips_hi16_list = NULL;
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
                location = (void *)sechdrs[sechdrs[relsec].sh_info].sh_addr
@@ -296,6 +308,19 @@ int apply_relocate(Elf_Shdr *sechdrs, const char *strtab,
                        return res;
        }
 
+       /*
+        * Normally the hi16 list should be deallocated at this point.  A
+        * malformed binary however could contain a series of R_MIPS_HI16
+        * relocations not followed by a R_MIPS_LO16 relocation.  In that
+        * case, free up the list and return an error.
+        */
+       if (me->arch.r_mips_hi16_list) {
+               free_relocation_chain(me->arch.r_mips_hi16_list);
+               me->arch.r_mips_hi16_list = NULL;
+
+               return -ENOEXEC;
+       }
+
        return 0;
 }
 
index e7e03ecf54959988e029e81783422fa0c5b78554..afc379ca375301f7e916a4fd46447239ad478a38 100644 (file)
@@ -102,7 +102,7 @@ static void cmp_init_secondary(void)
        c->vpe_id = (read_c0_tcbind() >> TCBIND_CURVPE_SHIFT) & TCBIND_CURVPE;
 #endif
 #ifdef CONFIG_MIPS_MT_SMTC
-       c->tc_id  = (read_c0_tcbind() >> TCBIND_CURTC_SHIFT) & TCBIND_CURTC;
+       c->tc_id  = (read_c0_tcbind() & TCBIND_CURTC) >> TCBIND_CURTC_SHIFT;
 #endif
 }
 
index 31637d8c87381f04b02bcae714e8b2165952fc9c..9005bf9fb859552101d7e68638adc73ba4978ee7 100644 (file)
@@ -130,7 +130,7 @@ asmlinkage __cpuinit void start_secondary(void)
 
        cpu_set(cpu, cpu_callin_map);
 
-       synchronise_count_slave();
+       synchronise_count_slave(cpu);
 
        /*
         * irq will be enabled in ->smp_finish(), enabling it too early
@@ -173,7 +173,6 @@ void smp_send_stop(void)
 void __init smp_cpus_done(unsigned int max_cpus)
 {
        mp_ops->cpus_done();
-       synchronise_count_master();
 }
 
 /* called from main before smp_init() */
@@ -206,6 +205,7 @@ int __cpuinit __cpu_up(unsigned int cpu, struct task_struct *tidle)
        while (!cpu_isset(cpu, cpu_callin_map))
                udelay(100);
 
+       synchronise_count_master(cpu);
        return 0;
 }
 
index 842d55e411fd396479b611ba0a1c0c2af2d4cb92..7f1eca3858def1845dc98dd1264206be19159b01 100644 (file)
@@ -28,12 +28,11 @@ static atomic_t __cpuinitdata count_reference = ATOMIC_INIT(0);
 #define COUNTON        100
 #define NR_LOOPS 5
 
-void __cpuinit synchronise_count_master(void)
+void __cpuinit synchronise_count_master(int cpu)
 {
        int i;
        unsigned long flags;
        unsigned int initcount;
-       int nslaves;
 
 #ifdef CONFIG_MIPS_MT_SMTC
        /*
@@ -43,8 +42,7 @@ void __cpuinit synchronise_count_master(void)
        return;
 #endif
 
-       printk(KERN_INFO "Synchronize counters across %u CPUs: ",
-              num_online_cpus());
+       printk(KERN_INFO "Synchronize counters for CPU %u: ", cpu);
 
        local_irq_save(flags);
 
@@ -52,7 +50,7 @@ void __cpuinit synchronise_count_master(void)
         * Notify the slaves that it's time to start
         */
        atomic_set(&count_reference, read_c0_count());
-       atomic_set(&count_start_flag, 1);
+       atomic_set(&count_start_flag, cpu);
        smp_wmb();
 
        /* Count will be initialised to current timer for all CPU's */
@@ -69,10 +67,9 @@ void __cpuinit synchronise_count_master(void)
         * two CPUs.
         */
 
-       nslaves = num_online_cpus()-1;
        for (i = 0; i < NR_LOOPS; i++) {
-               /* slaves loop on '!= ncpus' */
-               while (atomic_read(&count_count_start) != nslaves)
+               /* slaves loop on '!= 2' */
+               while (atomic_read(&count_count_start) != 1)
                        mb();
                atomic_set(&count_count_stop, 0);
                smp_wmb();
@@ -89,7 +86,7 @@ void __cpuinit synchronise_count_master(void)
                /*
                 * Wait for all slaves to leave the synchronization point:
                 */
-               while (atomic_read(&count_count_stop) != nslaves)
+               while (atomic_read(&count_count_stop) != 1)
                        mb();
                atomic_set(&count_count_start, 0);
                smp_wmb();
@@ -97,6 +94,7 @@ void __cpuinit synchronise_count_master(void)
        }
        /* Arrange for an interrupt in a short while */
        write_c0_compare(read_c0_count() + COUNTON);
+       atomic_set(&count_start_flag, 0);
 
        local_irq_restore(flags);
 
@@ -108,11 +106,10 @@ void __cpuinit synchronise_count_master(void)
        printk("done.\n");
 }
 
-void __cpuinit synchronise_count_slave(void)
+void __cpuinit synchronise_count_slave(int cpu)
 {
        int i;
        unsigned int initcount;
-       int ncpus;
 
 #ifdef CONFIG_MIPS_MT_SMTC
        /*
@@ -127,16 +124,15 @@ void __cpuinit synchronise_count_slave(void)
         * so we first wait for the master to say everyone is ready
         */
 
-       while (!atomic_read(&count_start_flag))
+       while (atomic_read(&count_start_flag) != cpu)
                mb();
 
        /* Count will be initialised to next expire for all CPU's */
        initcount = atomic_read(&count_reference);
 
-       ncpus = num_online_cpus();
        for (i = 0; i < NR_LOOPS; i++) {
                atomic_inc(&count_count_start);
-               while (atomic_read(&count_count_start) != ncpus)
+               while (atomic_read(&count_count_start) != 2)
                        mb();
 
                /*
@@ -146,7 +142,7 @@ void __cpuinit synchronise_count_slave(void)
                        write_c0_count(initcount);
 
                atomic_inc(&count_count_stop);
-               while (atomic_read(&count_count_stop) != ncpus)
+               while (atomic_read(&count_count_stop) != 2)
                        mb();
        }
        /* Arrange for an interrupt in a short while */
index 33aadbcf170bb4428020ddb87a17383180719400..dcfd573871c142348c4fa790bfcbd3dcc0c50879 100644 (file)
@@ -152,6 +152,8 @@ static int gup_huge_pud(pud_t pud, unsigned long addr, unsigned long end,
        do {
                VM_BUG_ON(compound_head(page) != head);
                pages[*nr] = page;
+               if (PageTail(page))
+                       get_huge_page_tail(page);
                (*nr)++;
                page++;
                refs++;
index 7b13a4caeea41b6377fb9410fe1397f2dce6aef2..fea823f184794a8a9003ce79afd90cb762a4ed52 100644 (file)
@@ -273,16 +273,19 @@ asmlinkage void plat_irq_dispatch(void)
        unsigned int pending = read_c0_cause() & read_c0_status() & ST0_IM;
        int irq;
 
+       if (unlikely(!pending)) {
+               spurious_interrupt();
+               return;
+       }
+
        irq = irq_ffs(pending);
 
        if (irq == MIPSCPU_INT_I8259A)
                malta_hw0_irqdispatch();
        else if (gic_present && ((1 << irq) & ipi_map[smp_processor_id()]))
                malta_ipi_irqdispatch();
-       else if (irq >= 0)
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
        else
-               spurious_interrupt();
+               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
 }
 
 #ifdef CONFIG_MIPS_MT_SMP
index 284dea54faf5a9f629e9d2cab18121cc5db328c6..2147cb34e705a2dca85355aa529c03ca878744a6 100644 (file)
@@ -252,16 +252,3 @@ void __init mips_pcibios_init(void)
 
        register_pci_controller(controller);
 }
-
-/* Enable PCI 2.1 compatibility in PIIX4 */
-static void __devinit quirk_dlcsetup(struct pci_dev *dev)
-{
-       u8 odlc, ndlc;
-       (void) pci_read_config_byte(dev, 0x82, &odlc);
-       /* Enable passive releases and delayed transaction */
-       ndlc = odlc | 7;
-       (void) pci_write_config_byte(dev, 0x82, ndlc);
-}
-
-DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
-       quirk_dlcsetup);
index 4c35301720e76c04aad4eade1d88310c107ba6fd..80562b81f0f2a2036fbf0a28781601b420c5d872 100644 (file)
@@ -138,11 +138,6 @@ static int __init malta_add_devices(void)
        if (err)
                return err;
 
-       /*
-        * Set RTC to BCD mode to support current alarm code.
-        */
-       CMOS_WRITE(CMOS_READ(RTC_CONTROL) & ~RTC_DM_BINARY, RTC_CONTROL);
-
        return 0;
 }
 
index 414a7459858d4e06b837a08d375eccbc96804dae..86d77a666458bae80c60f94c9fc405dca5f8459c 100644 (file)
 #define AR724X_PCI_MEM_BASE    0x10000000
 #define AR724X_PCI_MEM_SIZE    0x08000000
 
+#define AR724X_PCI_REG_RESET           0x18
 #define AR724X_PCI_REG_INT_STATUS      0x4c
 #define AR724X_PCI_REG_INT_MASK                0x50
 
+#define AR724X_PCI_RESET_LINK_UP       BIT(0)
+
 #define AR724X_PCI_INT_DEV0            BIT(14)
 
 #define AR724X_PCI_IRQ_COUNT           1
@@ -38,6 +41,15 @@ static void __iomem *ar724x_pci_ctrl_base;
 
 static u32 ar724x_pci_bar0_value;
 static bool ar724x_pci_bar0_is_cached;
+static bool ar724x_pci_link_up;
+
+static inline bool ar724x_pci_check_link(void)
+{
+       u32 reset;
+
+       reset = __raw_readl(ar724x_pci_ctrl_base + AR724X_PCI_REG_RESET);
+       return reset & AR724X_PCI_RESET_LINK_UP;
+}
 
 static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
                            int size, uint32_t *value)
@@ -46,6 +58,9 @@ static int ar724x_pci_read(struct pci_bus *bus, unsigned int devfn, int where,
        void __iomem *base;
        u32 data;
 
+       if (!ar724x_pci_link_up)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
        if (devfn)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -96,6 +111,9 @@ static int ar724x_pci_write(struct pci_bus *bus, unsigned int devfn, int where,
        u32 data;
        int s;
 
+       if (!ar724x_pci_link_up)
+               return PCIBIOS_DEVICE_NOT_FOUND;
+
        if (devfn)
                return PCIBIOS_DEVICE_NOT_FOUND;
 
@@ -280,6 +298,10 @@ int __init ar724x_pcibios_init(int irq)
        if (ar724x_pci_ctrl_base == NULL)
                goto err_unmap_devcfg;
 
+       ar724x_pci_link_up = ar724x_pci_check_link();
+       if (!ar724x_pci_link_up)
+               pr_warn("ar724x: PCIe link is down\n");
+
        ar724x_pci_irq_init(irq);
        register_pci_controller(&ar724x_pci_controller);
 
index 6c6defc24619fbab673b6296387c1dead503158b..af9cf30ed47430720ffb4736378336ee04edc9fa 100644 (file)
@@ -141,7 +141,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 
 #define atomic_sub_and_test(i,v)       (atomic_sub_return((i),(v)) == 0)
 
-#define ATOMIC_INIT(i) ((atomic_t) { (i) })
+#define ATOMIC_INIT(i) { (i) }
 
 #define smp_mb__before_atomic_dec()    smp_mb()
 #define smp_mb__after_atomic_dec()     smp_mb()
@@ -150,7 +150,7 @@ static __inline__ int __atomic_add_unless(atomic_t *v, int a, int u)
 
 #ifdef CONFIG_64BIT
 
-#define ATOMIC64_INIT(i) ((atomic64_t) { (i) })
+#define ATOMIC64_INIT(i) { (i) }
 
 static __inline__ s64
 __atomic64_add_return(s64 i, atomic64_t *v)
index d4b94b395c1641f6a3c88bf9b50795b36e86d09f..2c05a9292a81cb1138a28af59216eef1d829c421 100644 (file)
@@ -309,7 +309,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp,
                cregs->ksp = (unsigned long)stack
                        + (pregs->gr[21] & (THREAD_SIZE - 1));
                cregs->gr[30] = usp;
-               if (p->personality == PER_HPUX) {
+               if (personality(p->personality) == PER_HPUX) {
 #ifdef CONFIG_HPUX
                        cregs->kpc = (unsigned long) &hpux_child_return;
 #else
index c9b932260f4713969cc8df8c51a9813110fb622f..7426e40699bdbf08575d0b69722e6594a1535076 100644 (file)
@@ -225,12 +225,12 @@ long parisc_personality(unsigned long personality)
        long err;
 
        if (personality(current->personality) == PER_LINUX32
-           && personality == PER_LINUX)
-               personality = PER_LINUX32;
+           && personality(personality) == PER_LINUX)
+               personality = (personality & ~PER_MASK) | PER_LINUX32;
 
        err = sys_personality(personality);
-       if (err == PER_LINUX32)
-               err = PER_LINUX;
+       if (personality(err) == PER_LINUX32)
+               err = (err & ~PER_MASK) | PER_LINUX;
 
        return err;
 }
index 8d35d2c1f694772ae733fc4d20c0d1fad683948a..4f9c9f682ecfe14b074869b7e93e79fa74326026 100644 (file)
 /include/ "qoriq-duart-1.dtsi"
 /include/ "qoriq-gpio-0.dtsi"
 /include/ "qoriq-usb2-mph-0.dtsi"
+       usb@210000 {
+               compatible = "fsl-usb2-mph-v1.6", "fsl,mpc85xx-usb2-mph", "fsl-usb2-mph";
+               port0;
+       };
 /include/ "qoriq-usb2-dr-0.dtsi"
+       usb@211000 {
+               compatible = "fsl-usb2-dr-v1.6", "fsl,mpc85xx-usb2-dr", "fsl-usb2-dr";
+       };
 /include/ "qoriq-sec4.0-0.dtsi"
 };
index f4337bacd0e7c2692396954a5f51a4ba02e1416b..26e541c4662b27ce2c4429a2325083f8f065bf35 100644 (file)
@@ -6,28 +6,27 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_KALLSYMS_ALL=y
-CONFIG_KALLSYMS_EXTRA_PASS=y
 CONFIG_EMBEDDED=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_P1023_RDS=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_CPM2=y
-CONFIG_GPIO_MPC8XXX=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
@@ -63,11 +62,11 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -80,15 +79,14 @@ CONFIG_SATA_FSL=y
 CONFIG_SATA_SIL24=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
+CONFIG_FS_ENET=y
+CONFIG_FSL_PQ_MDIO=y
+CONFIG_E1000E=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_CICADA_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_FS_ENET=y
-CONFIG_E1000E=y
-CONFIG_FSL_PQ_MDIO=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -98,16 +96,15 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
 CONFIG_SERIAL_QE=m
-CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CPM=m
 CONFIG_I2C_MPC=y
+CONFIG_GPIO_MPC8XXX=y
 # CONFIG_HWMON is not set
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_SOUND=y
@@ -123,7 +120,6 @@ CONFIG_DMADEVICES=y
 CONFIG_FSL_DMA=y
 # CONFIG_NET_DMA is not set
 CONFIG_STAGING=y
-# CONFIG_STAGING_EXCLUDE_BUILD is not set
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
@@ -150,22 +146,15 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_FRAME_WARN=8092
 CONFIG_DEBUG_FS=y
-CONFIG_DEBUG_KERNEL=y
 CONFIG_DETECT_HUNG_TASK=y
 # CONFIG_DEBUG_BUGVERBOSE is not set
 CONFIG_DEBUG_INFO=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index cbb98c1234fdea1040292542a4ec4277e5bf76e2..8b3d57c1ebe81312673642db4765408a7de5c322 100644 (file)
@@ -6,8 +6,8 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
-CONFIG_RCU_TRACE=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -21,23 +21,22 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_P2041_RDB=y
 CONFIG_P3041_DS=y
 CONFIG_P4080_DS=y
 CONFIG_P5020_DS=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_BINFMT_MISC=m
 CONFIG_KEXEC=y
 CONFIG_IRQ_ALL_CPUS=y
 CONFIG_FORCE_MAX_ZONEORDER=13
-CONFIG_FSL_LBC=y
 CONFIG_PCI=y
 CONFIG_PCIEPORTBUS=y
-CONFIG_PCI_MSI=y
 # CONFIG_PCIEASPM is not set
+CONFIG_PCI_MSI=y
 CONFIG_RAPIDIO=y
 CONFIG_FSL_RIO=y
 CONFIG_NET=y
@@ -70,6 +69,7 @@ CONFIG_INET_IPCOMP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
@@ -77,17 +77,14 @@ CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_AMDSTD=y
 CONFIG_MTD_PHYSMAP_OF=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_MTD_NAND_FSL_ELBC=y
-CONFIG_MTD_M25P80=y
+CONFIG_MTD_NAND_FSL_IFC=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -115,11 +112,9 @@ CONFIG_SERIO_LIBPS2=y
 CONFIG_PPC_EPAPR_HV_BYTECHAN=y
 CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
-CONFIG_HW_RANDOM=y
 CONFIG_NVRAM=y
 CONFIG_I2C=y
 CONFIG_I2C_CHARDEV=y
@@ -132,7 +127,6 @@ CONFIG_SPI_FSL_ESPI=y
 CONFIG_VIDEO_OUTPUT_CONTROL=y
 CONFIG_USB_HID=m
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -142,8 +136,6 @@ CONFIG_USB_OHCI_HCD_PPC_OF_LE=y
 CONFIG_USB_STORAGE=y
 CONFIG_MMC=y
 CONFIG_MMC_SDHCI=y
-CONFIG_MMC_SDHCI_OF=y
-CONFIG_MMC_SDHCI_OF_ESDHC=y
 CONFIG_EDAC=y
 CONFIG_EDAC_MM_EDAC=y
 CONFIG_EDAC_MPC85XX=y
@@ -170,19 +162,16 @@ CONFIG_HUGETLBFS=y
 CONFIG_JFFS2_FS=y
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=m
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_UTF8=m
 CONFIG_MAGIC_SYSRQ=y
 CONFIG_DEBUG_SHIRQ=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_RCU_TRACE=y
 CONFIG_CRYPTO_NULL=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_MD4=y
index dd89de8b0b7f59945eb656564d49d19bcf2af121..0516e22ca3de3c16b89cdf0b4d9c7865e2d791c9 100644 (file)
@@ -56,6 +56,7 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
index 15130066e5e24ee15fb2d9442bb1e3c6c36c912a..07b7f2af2dca7ed9e06f7baea8e46f904fcb8aba 100644 (file)
@@ -1,8 +1,10 @@
+CONFIG_PPC64=y
+CONFIG_ALTIVEC=y
+CONFIG_SMP=y
+CONFIG_NR_CPUS=4
 CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_BLK_DEV_INITRD=y
@@ -13,15 +15,16 @@ CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 CONFIG_MODULE_SRCVERSION_ALL=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
-CONFIG_SMP=y
-CONFIG_NR_CPUS=4
-CONFIG_KEXEC=y
-# CONFIG_RELOCATABLE is not set
+# CONFIG_PPC_PSERIES is not set
 CONFIG_CPU_FREQ=y
 CONFIG_CPU_FREQ_GOV_POWERSAVE=y
 CONFIG_CPU_FREQ_GOV_USERSPACE=y
+CONFIG_CPU_FREQ_PMAC64=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
+CONFIG_KEXEC=y
+CONFIG_IRQ_ALL_CPUS=y
+# CONFIG_MIGRATION is not set
 CONFIG_PCI_MSI=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -49,6 +52,7 @@ CONFIG_NF_CT_NETLINK=m
 CONFIG_NF_CONNTRACK_IPV4=m
 CONFIG_IP_NF_QUEUE=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=m
 CONFIG_BLK_DEV_RAM=y
@@ -56,6 +60,8 @@ CONFIG_BLK_DEV_RAM_SIZE=65536
 CONFIG_CDROM_PKTCDVD=m
 CONFIG_IDE=y
 CONFIG_BLK_DEV_IDECD=y
+CONFIG_BLK_DEV_IDE_PMAC=y
+CONFIG_BLK_DEV_IDE_PMAC_ATA100FIRST=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
 CONFIG_BLK_DEV_SR=y
@@ -79,24 +85,33 @@ CONFIG_DM_CRYPT=m
 CONFIG_DM_SNAPSHOT=m
 CONFIG_DM_MIRROR=m
 CONFIG_DM_ZERO=m
-CONFIG_MACINTOSH_DRIVERS=y
+CONFIG_IEEE1394=y
+CONFIG_IEEE1394_OHCI1394=y
+CONFIG_IEEE1394_SBP2=m
+CONFIG_IEEE1394_ETH1394=m
+CONFIG_IEEE1394_RAWIO=y
+CONFIG_IEEE1394_VIDEO1394=m
+CONFIG_IEEE1394_DV1394=m
+CONFIG_ADB_PMU=y
+CONFIG_PMAC_SMU=y
 CONFIG_MAC_EMUMOUSEBTN=y
+CONFIG_THERM_PM72=y
+CONFIG_WINDFARM=y
+CONFIG_WINDFARM_PM81=y
+CONFIG_WINDFARM_PM91=y
+CONFIG_WINDFARM_PM112=y
+CONFIG_WINDFARM_PM121=y
 CONFIG_NETDEVICES=y
-CONFIG_BONDING=m
 CONFIG_DUMMY=m
-CONFIG_MII=y
+CONFIG_BONDING=m
 CONFIG_TUN=m
+CONFIG_NET_ETHERNET=y
+CONFIG_MII=y
+CONFIG_SUNGEM=y
 CONFIG_ACENIC=m
 CONFIG_ACENIC_OMIT_TIGON_I=y
-CONFIG_TIGON3=y
 CONFIG_E1000=y
-CONFIG_SUNGEM=y
-CONFIG_PPP=m
-CONFIG_PPP_BSDCOMP=m
-CONFIG_PPP_DEFLATE=m
-CONFIG_PPPOE=m
-CONFIG_PPP_ASYNC=m
-CONFIG_PPP_SYNC_TTY=m
+CONFIG_TIGON3=y
 CONFIG_USB_CATC=m
 CONFIG_USB_KAWETH=m
 CONFIG_USB_PEGASUS=m
@@ -106,24 +121,36 @@ CONFIG_USB_USBNET=m
 # CONFIG_USB_NET_NET1080 is not set
 # CONFIG_USB_NET_CDC_SUBSET is not set
 # CONFIG_USB_NET_ZAURUS is not set
+CONFIG_PPP=m
+CONFIG_PPP_ASYNC=m
+CONFIG_PPP_SYNC_TTY=m
+CONFIG_PPP_DEFLATE=m
+CONFIG_PPP_BSDCOMP=m
+CONFIG_PPPOE=m
 # CONFIG_INPUT_MOUSEDEV_PSAUX is not set
 CONFIG_INPUT_JOYDEV=m
 CONFIG_INPUT_EVDEV=y
+# CONFIG_KEYBOARD_ATKBD is not set
 # CONFIG_MOUSE_PS2 is not set
+# CONFIG_SERIO_I8042 is not set
 # CONFIG_SERIO_SERPORT is not set
-CONFIG_VT_HW_CONSOLE_BINDING=y
 # CONFIG_HW_RANDOM is not set
 CONFIG_GEN_RTC=y
 CONFIG_RAW_DRIVER=y
 CONFIG_I2C_CHARDEV=y
 # CONFIG_HWMON is not set
-CONFIG_AGP=y
-CONFIG_DRM=y
-CONFIG_DRM_NOUVEAU=y
+CONFIG_AGP=m
+CONFIG_AGP_UNINORTH=m
 CONFIG_VIDEO_OUTPUT_CONTROL=m
+CONFIG_FB=y
 CONFIG_FIRMWARE_EDID=y
 CONFIG_FB_TILEBLITTING=y
+CONFIG_FB_OF=y
+CONFIG_FB_NVIDIA=y
+CONFIG_FB_NVIDIA_I2C=y
 CONFIG_FB_RADEON=y
+# CONFIG_VGA_CONSOLE is not set
+CONFIG_FRAMEBUFFER_CONSOLE=y
 CONFIG_LOGO=y
 CONFIG_SOUND=m
 CONFIG_SND=m
@@ -131,7 +158,15 @@ CONFIG_SND_SEQUENCER=m
 CONFIG_SND_MIXER_OSS=m
 CONFIG_SND_PCM_OSS=m
 CONFIG_SND_SEQUENCER_OSS=y
+CONFIG_SND_POWERMAC=m
+CONFIG_SND_AOA=m
+CONFIG_SND_AOA_FABRIC_LAYOUT=m
+CONFIG_SND_AOA_ONYX=m
+CONFIG_SND_AOA_TAS=m
+CONFIG_SND_AOA_TOONIE=m
 CONFIG_SND_USB_AUDIO=m
+CONFIG_HID_PID=y
+CONFIG_USB_HIDDEV=y
 CONFIG_HID_GYRATION=y
 CONFIG_LOGITECH_FF=y
 CONFIG_HID_PANTHERLORD=y
@@ -139,12 +174,13 @@ CONFIG_HID_PETALYNX=y
 CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
-CONFIG_HID_PID=y
-CONFIG_USB_HIDDEV=y
 CONFIG_USB=y
+CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
+# CONFIG_USB_EHCI_HCD_PPC_OF is not set
 CONFIG_USB_OHCI_HCD=y
+CONFIG_USB_OHCI_HCD_PPC_OF_BE=y
 CONFIG_USB_ACM=m
 CONFIG_USB_PRINTER=y
 CONFIG_USB_STORAGE=y
@@ -208,6 +244,8 @@ CONFIG_REISERFS_FS_POSIX_ACL=y
 CONFIG_REISERFS_FS_SECURITY=y
 CONFIG_XFS_FS=m
 CONFIG_XFS_POSIX_ACL=y
+CONFIG_INOTIFY=y
+CONFIG_AUTOFS_FS=m
 CONFIG_ISO9660_FS=y
 CONFIG_JOLIET=y
 CONFIG_ZISOFS=y
@@ -221,12 +259,14 @@ CONFIG_HFS_FS=m
 CONFIG_HFSPLUS_FS=m
 CONFIG_CRAMFS=y
 CONFIG_NFS_FS=y
+CONFIG_NFS_V3=y
 CONFIG_NFS_V3_ACL=y
 CONFIG_NFS_V4=y
 CONFIG_NFSD=y
 CONFIG_NFSD_V3_ACL=y
 CONFIG_NFSD_V4=y
 CONFIG_CIFS=m
+CONFIG_PARTITION_ADVANCED=y
 CONFIG_NLS_CODEPAGE_437=y
 CONFIG_NLS_CODEPAGE_1250=y
 CONFIG_NLS_CODEPAGE_1251=y
@@ -234,23 +274,29 @@ CONFIG_NLS_ASCII=y
 CONFIG_NLS_ISO8859_1=y
 CONFIG_NLS_ISO8859_15=y
 CONFIG_NLS_UTF8=y
+CONFIG_CRC_T10DIF=y
+CONFIG_LIBCRC32C=m
 CONFIG_MAGIC_SYSRQ=y
-# CONFIG_UNUSED_SYMBOLS is not set
 CONFIG_DEBUG_FS=y
 CONFIG_DEBUG_KERNEL=y
 CONFIG_DEBUG_MUTEXES=y
+# CONFIG_RCU_CPU_STALL_DETECTOR is not set
 CONFIG_LATENCYTOP=y
-CONFIG_STRICT_DEVMEM=y
+CONFIG_SYSCTL_SYSCALL_CHECK=y
+CONFIG_BOOTX_TEXT=y
 CONFIG_CRYPTO_NULL=m
 CONFIG_CRYPTO_TEST=m
+CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_HMAC=y
+CONFIG_CRYPTO_MD4=m
 CONFIG_CRYPTO_MICHAEL_MIC=m
 CONFIG_CRYPTO_SHA256=m
 CONFIG_CRYPTO_SHA512=m
 CONFIG_CRYPTO_WP512=m
 CONFIG_CRYPTO_AES=m
 CONFIG_CRYPTO_ANUBIS=m
+CONFIG_CRYPTO_ARC4=m
 CONFIG_CRYPTO_BLOWFISH=m
 CONFIG_CRYPTO_CAST5=m
 CONFIG_CRYPTO_CAST6=m
@@ -260,6 +306,3 @@ CONFIG_CRYPTO_TEA=m
 CONFIG_CRYPTO_TWOFISH=m
 # CONFIG_CRYPTO_ANSI_CPRNG is not set
 # CONFIG_CRYPTO_HW is not set
-# CONFIG_VIRTUALIZATION is not set
-CONFIG_CRC_T10DIF=y
-CONFIG_LIBCRC32C=m
index 5aac9a8bc53b2294dfbcb64df800d6aea078fdec..9352e4430c3b05419fdff7ee3b3ec91cfeaeee5d 100644 (file)
@@ -2,12 +2,12 @@ CONFIG_EXPERIMENTAL=y
 CONFIG_SYSVIPC=y
 CONFIG_LOG_BUF_SHIFT=14
 CONFIG_BLK_DEV_INITRD=y
-# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set
 CONFIG_EXPERT=y
 CONFIG_SLAB=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
 # CONFIG_PPC_CHRP is not set
 # CONFIG_PPC_PMAC is not set
 CONFIG_PPC_83xx=y
@@ -25,7 +25,6 @@ CONFIG_ASP834x=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_MATH_EMULATION=y
-CONFIG_SPARSE_IRQ=y
 CONFIG_PCI=y
 CONFIG_NET=y
 CONFIG_PACKET=y
@@ -42,10 +41,9 @@ CONFIG_INET_ESP=y
 # CONFIG_INET_LRO is not set
 # CONFIG_IPV6 is not set
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 # CONFIG_FW_LOADER is not set
 CONFIG_MTD=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
 CONFIG_MTD_CFI=y
@@ -64,15 +62,14 @@ CONFIG_ATA=y
 CONFIG_SATA_FSL=y
 CONFIG_SATA_SIL=y
 CONFIG_NETDEVICES=y
+CONFIG_MII=y
+CONFIG_UCC_GETH=y
+CONFIG_GIANFAR=y
 CONFIG_MARVELL_PHY=y
 CONFIG_DAVICOM_PHY=y
 CONFIG_VITESSE_PHY=y
 CONFIG_ICPLUS_PHY=y
 CONFIG_FIXED_PHY=y
-CONFIG_NET_ETHERNET=y
-CONFIG_MII=y
-CONFIG_GIANFAR=y
-CONFIG_UCC_GETH=y
 CONFIG_INPUT_FF_MEMLESS=m
 # CONFIG_INPUT_MOUSEDEV is not set
 # CONFIG_INPUT_KEYBOARD is not set
@@ -112,17 +109,12 @@ CONFIG_RTC_DRV_DS1374=y
 CONFIG_EXT2_FS=y
 CONFIG_EXT3_FS=y
 # CONFIG_EXT3_DEFAULTS_TO_ORDERED is not set
-CONFIG_INOTIFY=y
 CONFIG_PROC_KCORE=y
 CONFIG_TMPFS=y
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
-CONFIG_PARTITION_ADVANCED=y
 CONFIG_CRC_T10DIF=y
-# CONFIG_RCU_CPU_STALL_DETECTOR is not set
-CONFIG_SYSCTL_SYSCALL_CHECK=y
 CONFIG_CRYPTO_ECB=m
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
index 03ee911c45775410c141ab108019b278ae726d17..8b5bda27d248047b43d59ffdd9af22922e599936 100644 (file)
@@ -5,7 +5,9 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -17,6 +19,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_MPC8540_ADS=y
 CONFIG_MPC8560_ADS=y
 CONFIG_MPC85xx_CDS=y
@@ -40,8 +44,6 @@ CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_FORCE_MAX_ZONEORDER=12
@@ -74,36 +76,25 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
 CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -115,6 +106,7 @@ CONFIG_ATA=y
 CONFIG_SATA_AHCI=y
 CONFIG_SATA_FSL=y
 CONFIG_PATA_ALI=y
+CONFIG_PATA_VIA=y
 CONFIG_NETDEVICES=y
 CONFIG_DUMMY=y
 CONFIG_FS_ENET=y
@@ -134,7 +126,6 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
@@ -183,7 +174,6 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -229,18 +219,13 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index fdfa84dc908f21c318f0b0409f0604524f99a2c2..b0974e7e98aefc6f4e7b39a0025c3435e5ebafe1 100644 (file)
@@ -7,7 +7,9 @@ CONFIG_SYSVIPC=y
 CONFIG_POSIX_MQUEUE=y
 CONFIG_BSD_PROCESS_ACCT=y
 CONFIG_AUDIT=y
-CONFIG_SPARSE_IRQ=y
+CONFIG_IRQ_DOMAIN_DEBUG=y
+CONFIG_NO_HZ=y
+CONFIG_HIGH_RES_TIMERS=y
 CONFIG_IKCONFIG=y
 CONFIG_IKCONFIG_PROC=y
 CONFIG_LOG_BUF_SHIFT=14
@@ -19,6 +21,8 @@ CONFIG_MODULE_UNLOAD=y
 CONFIG_MODULE_FORCE_UNLOAD=y
 CONFIG_MODVERSIONS=y
 # CONFIG_BLK_DEV_BSG is not set
+CONFIG_PARTITION_ADVANCED=y
+CONFIG_MAC_PARTITION=y
 CONFIG_MPC8540_ADS=y
 CONFIG_MPC8560_ADS=y
 CONFIG_MPC85xx_CDS=y
@@ -42,8 +46,6 @@ CONFIG_SBC8548=y
 CONFIG_QUICC_ENGINE=y
 CONFIG_QE_GPIO=y
 CONFIG_HIGHMEM=y
-CONFIG_NO_HZ=y
-CONFIG_HIGH_RES_TIMERS=y
 CONFIG_BINFMT_MISC=m
 CONFIG_MATH_EMULATION=y
 CONFIG_IRQ_ALL_CPUS=y
@@ -77,36 +79,25 @@ CONFIG_INET_ESP=y
 CONFIG_IPV6=y
 CONFIG_IP_SCTP=m
 CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug"
+CONFIG_DEVTMPFS=y
 CONFIG_MTD=y
 CONFIG_MTD_CMDLINE_PARTS=y
 CONFIG_MTD_CHAR=y
 CONFIG_MTD_BLOCK=y
-CONFIG_MTD_CFI=y
 CONFIG_FTL=y
-CONFIG_MTD_GEN_PROBE=y
-CONFIG_MTD_MAP_BANK_WIDTH_1=y
-CONFIG_MTD_MAP_BANK_WIDTH_2=y
-CONFIG_MTD_MAP_BANK_WIDTH_4=y
-CONFIG_MTD_CFI_I1=y
-CONFIG_MTD_CFI_I2=y
+CONFIG_MTD_CFI=y
 CONFIG_MTD_CFI_INTELEXT=y
 CONFIG_MTD_CFI_AMDSTD=y
-CONFIG_MTD_CFI_UTIL=y
 CONFIG_MTD_PHYSMAP_OF=y
-CONFIG_MTD_PARTITIONS=y
-CONFIG_MTD_OF_PARTS=y
+CONFIG_MTD_M25P80=y
 CONFIG_MTD_NAND=y
 CONFIG_MTD_NAND_FSL_ELBC=y
 CONFIG_MTD_NAND_FSL_IFC=y
-CONFIG_MTD_NAND_IDS=y
-CONFIG_MTD_NAND_ECC=y
-CONFIG_MTD_M25P80=y
 CONFIG_PROC_DEVICETREE=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_BLK_DEV_NBD=y
 CONFIG_BLK_DEV_RAM=y
 CONFIG_BLK_DEV_RAM_SIZE=131072
-CONFIG_MISC_DEVICES=y
 CONFIG_EEPROM_LEGACY=y
 CONFIG_BLK_DEV_SD=y
 CONFIG_CHR_DEV_ST=y
@@ -137,7 +128,6 @@ CONFIG_SERIAL_8250=y
 CONFIG_SERIAL_8250_CONSOLE=y
 CONFIG_SERIAL_8250_NR_UARTS=2
 CONFIG_SERIAL_8250_RUNTIME_UARTS=2
-CONFIG_SERIAL_8250_EXTENDED=y
 CONFIG_SERIAL_8250_MANY_PORTS=y
 CONFIG_SERIAL_8250_DETECT_IRQ=y
 CONFIG_SERIAL_8250_RSA=y
@@ -186,7 +176,6 @@ CONFIG_HID_SAMSUNG=y
 CONFIG_HID_SONY=y
 CONFIG_HID_SUNPLUS=y
 CONFIG_USB=y
-CONFIG_USB_DEVICEFS=y
 CONFIG_USB_MON=y
 CONFIG_USB_EHCI_HCD=y
 CONFIG_USB_EHCI_FSL=y
@@ -232,18 +221,13 @@ CONFIG_QNX4FS_FS=m
 CONFIG_SYSV_FS=m
 CONFIG_UFS_FS=m
 CONFIG_NFS_FS=y
-CONFIG_NFS_V3=y
 CONFIG_NFS_V4=y
 CONFIG_ROOT_NFS=y
 CONFIG_NFSD=y
-CONFIG_PARTITION_ADVANCED=y
-CONFIG_MAC_PARTITION=y
 CONFIG_CRC_T10DIF=y
 CONFIG_DEBUG_FS=y
 CONFIG_DETECT_HUNG_TASK=y
 CONFIG_DEBUG_INFO=y
-CONFIG_SYSCTL_SYSCALL_CHECK=y
-CONFIG_IRQ_DOMAIN_DEBUG=y
 CONFIG_CRYPTO_PCBC=m
 CONFIG_CRYPTO_SHA256=y
 CONFIG_CRYPTO_SHA512=y
index 50d82c8a037f4cec2903504541b39a6eb2352331..b3c083de17ad5d3d06739eecdde3926df8b1c39c 100644 (file)
@@ -553,9 +553,7 @@ static inline int cpu_has_feature(unsigned long feature)
                & feature);
 }
 
-#ifdef CONFIG_HAVE_HW_BREAKPOINT
 #define HBP_NUM 1
-#endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
 #endif /* !__ASSEMBLY__ */
 
index 50ea12fd7bf5eeab23e6fc1bccafdf4dbe2ad89b..a8bf5c673a3c430c7aa6f45cbfd43e290dd3a95c 100644 (file)
@@ -33,6 +33,7 @@
 #include <asm/kvm_asm.h>
 #include <asm/processor.h>
 #include <asm/page.h>
+#include <asm/cacheflush.h>
 
 #define KVM_MAX_VCPUS          NR_CPUS
 #define KVM_MAX_VCORES         NR_CPUS
index 0124937a23b97e104260f9cd4bbe1c409bdf1ff5..e006f0bdea95f1a9464c688928dc7206690f5c14 100644 (file)
@@ -219,4 +219,16 @@ void kvmppc_claim_lpid(long lpid);
 void kvmppc_free_lpid(long lpid);
 void kvmppc_init_lpid(unsigned long nr_lpids);
 
+static inline void kvmppc_mmu_flush_icache(pfn_t pfn)
+{
+       /* Clear i-cache for new pages */
+       struct page *page;
+       page = pfn_to_page(pfn);
+       if (!test_bit(PG_arch_1, &page->flags)) {
+               flush_dcache_icache_page(page);
+               set_bit(PG_arch_1, &page->flags);
+       }
+}
+
+
 #endif /* __POWERPC_KVM_PPC_H__ */
index 326d33ca55cdc33e8b3cb112f0fefb8117bab3af..d4f471fb10310b75c056345e3094e8180930048a 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/types.h>
 #include <linux/spinlock.h>
 #include <asm/smp.h>
+#include <asm/io.h>
 
 struct mpic_msgr {
        u32 __iomem *base;
index 53b6dfa83344a9f3dbe6b68ef72c6d60948f26ab..54b73a28c20579f4f6923e4f9711b5d7dc062205 100644 (file)
@@ -386,6 +386,7 @@ extern unsigned long cpuidle_disable;
 enum idle_boot_override {IDLE_NO_OVERRIDE = 0, IDLE_POWERSAVE_OFF};
 
 extern int powersave_nap;      /* set if nap mode can be used in idle loop */
+extern void power7_nap(void);
 
 #ifdef CONFIG_PSERIES_IDLE
 extern void update_smt_snooze_delay(int snooze);
index 85b05c463fae9077b4490bacfa80c31050a617fa..e8995727b1c15207757969ca9e4cd5b7990c2d17 100644 (file)
@@ -76,6 +76,7 @@ int main(void)
        DEFINE(SIGSEGV, SIGSEGV);
        DEFINE(NMI_MASK, NMI_MASK);
        DEFINE(THREAD_DSCR, offsetof(struct thread_struct, dscr));
+       DEFINE(THREAD_DSCR_INHERIT, offsetof(struct thread_struct, dscr_inherit));
 #else
        DEFINE(THREAD_INFO, offsetof(struct task_struct, stack));
 #endif /* CONFIG_PPC64 */
index 5b25c8060fd67a8ff1ec2ff290af5ec740b6376f..a892680668d86ce53d3d8e405c807d968c701a92 100644 (file)
@@ -28,6 +28,8 @@ void doorbell_setup_this_cpu(void)
 
 void doorbell_cause_ipi(int cpu, unsigned long data)
 {
+       /* Order previous accesses vs. msgsnd, which is treated as a store */
+       mb();
        ppc_msgsnd(PPC_DBELL, 0, data);
 }
 
index 2d7bb8ced136c1e618d1e25229553a70512dc927..e4897523de41e45476bf002a64a3ab68d3e85e22 100644 (file)
@@ -83,11 +83,10 @@ static int dma_iommu_dma_supported(struct device *dev, u64 mask)
                return 0;
        }
 
-       if ((tbl->it_offset + tbl->it_size) > (mask >> IOMMU_PAGE_SHIFT)) {
-               dev_info(dev, "Warning: IOMMU window too big for device mask\n");
-               dev_info(dev, "mask: 0x%08llx, table end: 0x%08lx\n",
-                               mask, (tbl->it_offset + tbl->it_size) <<
-                               IOMMU_PAGE_SHIFT);
+       if (tbl->it_offset > (mask >> IOMMU_PAGE_SHIFT)) {
+               dev_info(dev, "Warning: IOMMU offset too big for device mask\n");
+               dev_info(dev, "mask: 0x%08llx, table offset: 0x%08lx\n",
+                               mask, tbl->it_offset << IOMMU_PAGE_SHIFT);
                return 0;
        } else
                return 1;
index 4b01a25e29ef61ea5cdeb07a14939142ba1ecdd9..b40e0b4815b3f5297154fa9c6e8a66fa4ce7c574 100644 (file)
@@ -370,6 +370,12 @@ _GLOBAL(ret_from_fork)
        li      r3,0
        b       syscall_exit
 
+       .section        ".toc","aw"
+DSCR_DEFAULT:
+       .tc dscr_default[TC],dscr_default
+
+       .section        ".text"
+
 /*
  * This routine switches between two different tasks.  The process
  * state of one is saved on its kernel stack.  Then the state
@@ -509,9 +515,6 @@ END_MMU_FTR_SECTION_IFSET(MMU_FTR_1T_SEGMENT)
        mr      r1,r8           /* start using new stack pointer */
        std     r7,PACAKSAVE(r13)
 
-       ld      r6,_CCR(r1)
-       mtcrf   0xFF,r6
-
 #ifdef CONFIG_ALTIVEC
 BEGIN_FTR_SECTION
        ld      r0,THREAD_VRSAVE(r4)
@@ -520,14 +523,22 @@ END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC)
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_PPC64
 BEGIN_FTR_SECTION
+       lwz     r6,THREAD_DSCR_INHERIT(r4)
+       ld      r7,DSCR_DEFAULT@toc(2)
        ld      r0,THREAD_DSCR(r4)
-       cmpd    r0,r25
-       beq     1f
+       cmpwi   r6,0
+       bne     1f
+       ld      r0,0(r7)
+1:     cmpd    r0,r25
+       beq     2f
        mtspr   SPRN_DSCR,r0
-1:     
+2:
 END_FTR_SECTION_IFSET(CPU_FTR_DSCR)
 #endif
 
+       ld      r6,_CCR(r1)
+       mtcrf   0xFF,r6
+
        /* r3-r13 are destroyed -- Cort */
        REST_8GPRS(14, r1)
        REST_10GPRS(22, r1)
index e894515e77bbfa950c7d3e00cfbaafa07d0a0075..39aa97d3ff883a2ed5121e1cc11afd5ffae0f898 100644 (file)
@@ -186,7 +186,7 @@ hardware_interrupt_hv:
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0x800)
 
        MASKABLE_EXCEPTION_PSERIES(0x900, 0x900, decrementer)
-       MASKABLE_EXCEPTION_HV(0x980, 0x982, decrementer)
+       STD_EXCEPTION_HV(0x980, 0x982, hdecrementer)
 
        STD_EXCEPTION_PSERIES(0xa00, 0xa00, trap_0a)
        KVM_HANDLER_PR(PACA_EXGEN, EXC_STD, 0xa00)
@@ -486,6 +486,7 @@ machine_check_common:
 
        STD_EXCEPTION_COMMON_ASYNC(0x500, hardware_interrupt, do_IRQ)
        STD_EXCEPTION_COMMON_ASYNC(0x900, decrementer, .timer_interrupt)
+       STD_EXCEPTION_COMMON(0x980, hdecrementer, .hdec_interrupt)
        STD_EXCEPTION_COMMON(0xa00, trap_0a, .unknown_exception)
        STD_EXCEPTION_COMMON(0xb00, trap_0b, .unknown_exception)
        STD_EXCEPTION_COMMON(0xd00, single_step, .single_step_exception)
index f3a82dde61dbfe8b469a63d4874f2de53bf1b476..956a4c496de942d93853f42f2db1067f45cf0085 100644 (file)
@@ -253,7 +253,7 @@ int __kprobes hw_breakpoint_handler(struct die_args *args)
 
        /* Do not emulate user-space instructions, instead single-step them */
        if (user_mode(regs)) {
-               bp->ctx->task->thread.last_hit_ubp = bp;
+               current->thread.last_hit_ubp = bp;
                regs->msr |= MSR_SE;
                goto out;
        }
index 7140d838339e1a9e2ef691ff4079ea022f4d964c..e11863f4e595e2a3302e3ead79b439751ca5d402 100644 (file)
@@ -28,7 +28,9 @@ _GLOBAL(power7_idle)
        lwz     r4,ADDROFF(powersave_nap)(r3)
        cmpwi   0,r4,0
        beqlr
+       /* fall through */
 
+_GLOBAL(power7_nap)
        /* NAP is a state loss, we create a regs frame on the
         * stack, fill it up with the state we care about and
         * stick a pointer to it in PACAR1. We really only
index 782bd0a3c2f0f95496b1b144ebb3ec6e6218e0f8..c470a40b29f5d4937883cfcd8a40dd1c6bbdcfd1 100644 (file)
@@ -25,6 +25,7 @@
 #include <asm/processor.h>
 #include <asm/machdep.h>
 #include <asm/debug.h>
+#include <linux/slab.h>
 
 /*
  * This table contains the mapping between PowerPC hardware trap types, and
@@ -101,6 +102,21 @@ static int computeSignal(unsigned int tt)
        return SIGHUP;          /* default for things we don't know about */
 }
 
+/**
+ *
+ *     kgdb_skipexception - Bail out of KGDB when we've been triggered.
+ *     @exception: Exception vector number
+ *     @regs: Current &struct pt_regs.
+ *
+ *     On some architectures we need to skip a breakpoint exception when
+ *     it occurs after a breakpoint has been removed.
+ *
+ */
+int kgdb_skipexception(int exception, struct pt_regs *regs)
+{
+       return kgdb_isremovedbreak(regs->nip);
+}
+
 static int kgdb_call_nmi_hook(struct pt_regs *regs)
 {
        kgdb_nmicallback(raw_smp_processor_id(), regs);
@@ -138,6 +154,8 @@ static int kgdb_handle_breakpoint(struct pt_regs *regs)
 static int kgdb_singlestep(struct pt_regs *regs)
 {
        struct thread_info *thread_info, *exception_thread_info;
+       struct thread_info *backup_current_thread_info = \
+               (struct thread_info *)kmalloc(sizeof(struct thread_info), GFP_KERNEL);
 
        if (user_mode(regs))
                return 0;
@@ -155,13 +173,17 @@ static int kgdb_singlestep(struct pt_regs *regs)
        thread_info = (struct thread_info *)(regs->gpr[1] & ~(THREAD_SIZE-1));
        exception_thread_info = current_thread_info();
 
-       if (thread_info != exception_thread_info)
+       if (thread_info != exception_thread_info) {
+               /* Save the original current_thread_info. */
+               memcpy(backup_current_thread_info, exception_thread_info, sizeof *thread_info);
                memcpy(exception_thread_info, thread_info, sizeof *thread_info);
+       }
 
        kgdb_handle_exception(0, SIGTRAP, 0, regs);
 
        if (thread_info != exception_thread_info)
-               memcpy(thread_info, exception_thread_info, sizeof *thread_info);
+               /* Restore current_thread_info lastly. */
+               memcpy(exception_thread_info, backup_current_thread_info, sizeof *thread_info);
 
        return 1;
 }
@@ -410,7 +432,6 @@ int kgdb_arch_handle_exception(int vector, int signo, int err_code,
 #else
                        linux_regs->msr |= MSR_SE;
 #endif
-                       kgdb_single_step = 1;
                        atomic_set(&kgdb_cpu_doing_single_step,
                                   raw_smp_processor_id());
                }
index 710f400476deb8461a98a1342c6ee1b669fbe686..1a1f2ddfb581a222fb5fe85a0d8983ef5ad7e2af 100644 (file)
@@ -802,16 +802,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp,
 #endif /* CONFIG_PPC_STD_MMU_64 */
 #ifdef CONFIG_PPC64 
        if (cpu_has_feature(CPU_FTR_DSCR)) {
-               if (current->thread.dscr_inherit) {
-                       p->thread.dscr_inherit = 1;
-                       p->thread.dscr = current->thread.dscr;
-               } else if (0 != dscr_default) {
-                       p->thread.dscr_inherit = 1;
-                       p->thread.dscr = dscr_default;
-               } else {
-                       p->thread.dscr_inherit = 0;
-                       p->thread.dscr = 0;
-               }
+               p->thread.dscr_inherit = current->thread.dscr_inherit;
+               p->thread.dscr = current->thread.dscr;
        }
 #endif
 
index 0321007086f7c499771ad0f71bc1f63969faff7a..8d4214afc21d6934fef8d12b582073c64a6ff7f3 100644 (file)
@@ -198,8 +198,15 @@ void smp_muxed_ipi_message_pass(int cpu, int msg)
        struct cpu_messages *info = &per_cpu(ipi_message, cpu);
        char *message = (char *)&info->messages;
 
+       /*
+        * Order previous accesses before accesses in the IPI handler.
+        */
+       smp_mb();
        message[msg] = 1;
-       mb();
+       /*
+        * cause_ipi functions are required to include a full barrier
+        * before doing whatever causes the IPI.
+        */
        smp_ops->cause_ipi(cpu, info->data);
 }
 
@@ -211,7 +218,7 @@ irqreturn_t smp_ipi_demux(void)
        mb();   /* order any irq clear */
 
        do {
-               all = xchg_local(&info->messages, 0);
+               all = xchg(&info->messages, 0);
 
 #ifdef __BIG_ENDIAN
                if (all & (1 << (24 - 8 * PPC_MSG_CALL_FUNCTION)))
index f2496f2faeccc37231110392363d0914d599e5b5..4e3cc47f26b90e157ebb5c2a1cd156918e655930 100644 (file)
@@ -107,11 +107,11 @@ long ppc64_personality(unsigned long personality)
        long ret;
 
        if (personality(current->personality) == PER_LINUX32
-           && personality == PER_LINUX)
-               personality = PER_LINUX32;
+           && personality(personality) == PER_LINUX)
+               personality = (personality & ~PER_MASK) | PER_LINUX32;
        ret = sys_personality(personality);
-       if (ret == PER_LINUX32)
-               ret = PER_LINUX;
+       if (personality(ret) == PER_LINUX32)
+               ret = (ret & ~PER_MASK) | PER_LINUX;
        return ret;
 }
 #endif
index 3529446c2abd78a407f9b3a7fd9735ed49802656..8302af6492195b77ac8a5b7f5dfbc69dfc7d43b8 100644 (file)
@@ -194,6 +194,14 @@ static ssize_t show_dscr_default(struct device *dev,
        return sprintf(buf, "%lx\n", dscr_default);
 }
 
+static void update_dscr(void *dummy)
+{
+       if (!current->thread.dscr_inherit) {
+               current->thread.dscr = dscr_default;
+               mtspr(SPRN_DSCR, dscr_default);
+       }
+}
+
 static ssize_t __used store_dscr_default(struct device *dev,
                struct device_attribute *attr, const char *buf,
                size_t count)
@@ -206,6 +214,8 @@ static ssize_t __used store_dscr_default(struct device *dev,
                return -EINVAL;
        dscr_default = val;
 
+       on_each_cpu(update_dscr, NULL, 1);
+
        return count;
 }
 
index be171ee73bf8cd3bef83630fbc031ad4f29410e7..e49e93191b69a736332e06cf9be56aad189d0ec3 100644 (file)
@@ -535,6 +535,15 @@ void timer_interrupt(struct pt_regs * regs)
        trace_timer_interrupt_exit(regs);
 }
 
+/*
+ * Hypervisor decrementer interrupts shouldn't occur but are sometimes
+ * left pending on exit from a KVM guest.  We don't need to do anything
+ * to clear them, as they are edge-triggered.
+ */
+void hdec_interrupt(struct pt_regs *regs)
+{
+}
+
 #ifdef CONFIG_SUSPEND
 static void generic_suspend_disable_irqs(void)
 {
index 158972341a2d7a66da48c32878fdc0842b2a4feb..ae0843fa7a61f64540214b2fbf658265d24879df 100644 (file)
@@ -972,8 +972,9 @@ static int emulate_instruction(struct pt_regs *regs)
                        cpu_has_feature(CPU_FTR_DSCR)) {
                PPC_WARN_EMULATED(mtdscr, regs);
                rd = (instword >> 21) & 0x1f;
-               mtspr(SPRN_DSCR, regs->gpr[rd]);
+               current->thread.dscr = regs->gpr[rd];
                current->thread.dscr_inherit = 1;
+               mtspr(SPRN_DSCR, current->thread.dscr);
                return 0;
        }
 #endif
index f922c29bb234d9bc6f2baf44175e934b63de5f86..837f13e7b6bfc1be3f7ed65a1000964f04825ebe 100644 (file)
@@ -211,6 +211,9 @@ next_pteg:
                pteg1 |= PP_RWRX;
        }
 
+       if (orig_pte->may_execute)
+               kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
+
        local_irq_disable();
 
        if (pteg[rr]) {
index 10fc8ec9d2a8b7e1e8e7ad8113e8dce633a5d977..0688b6b3958594fce84a62cfbd2f3564b5650781 100644 (file)
@@ -126,6 +126,8 @@ int kvmppc_mmu_map_page(struct kvm_vcpu *vcpu, struct kvmppc_pte *orig_pte)
 
        if (!orig_pte->may_execute)
                rflags |= HPTE_R_N;
+       else
+               kvmppc_mmu_flush_icache(hpaddr >> PAGE_SHIFT);
 
        hash = hpt_hash(va, PTE_SIZE, MMU_SEGSIZE_256M);
 
index 5a84c8d3d04050b98ab818c9d83cedeb74b8f235..44b72feaff7d9876fad230253be42c1aee6e8af7 100644 (file)
@@ -1421,13 +1421,13 @@ _GLOBAL(kvmppc_h_cede)
        sync                    /* order setting ceded vs. testing prodded */
        lbz     r5,VCPU_PRODDED(r3)
        cmpwi   r5,0
-       bne     1f
+       bne     kvm_cede_prodded
        li      r0,0            /* set trap to 0 to say hcall is handled */
        stw     r0,VCPU_TRAP(r3)
        li      r0,H_SUCCESS
        std     r0,VCPU_GPR(R3)(r3)
 BEGIN_FTR_SECTION
-       b       2f              /* just send it up to host on 970 */
+       b       kvm_cede_exit   /* just send it up to host on 970 */
 END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
 
        /*
@@ -1446,7 +1446,7 @@ END_FTR_SECTION_IFCLR(CPU_FTR_ARCH_206)
        or      r4,r4,r0
        PPC_POPCNTW(R7,R4)
        cmpw    r7,r8
-       bge     2f
+       bge     kvm_cede_exit
        stwcx.  r4,0,r6
        bne     31b
        li      r0,1
@@ -1555,7 +1555,8 @@ kvm_end_cede:
        b       hcall_real_fallback
 
        /* cede when already previously prodded case */
-1:     li      r0,0
+kvm_cede_prodded:
+       li      r0,0
        stb     r0,VCPU_PRODDED(r3)
        sync                    /* order testing prodded vs. clearing ceded */
        stb     r0,VCPU_CEDED(r3)
@@ -1563,7 +1564,8 @@ kvm_end_cede:
        blr
 
        /* we've ceded but we want to give control to the host */
-2:     li      r3,H_TOO_HARD
+kvm_cede_exit:
+       li      r3,H_TOO_HARD
        blr
 
 secondary_too_late:
index c510fc961302c2d1ae1284cc3d1aab1139002fbd..a2b66717813dfef6c43e9bf23864f8766266f0a5 100644 (file)
@@ -322,11 +322,11 @@ static inline void kvmppc_e500_ref_release(struct tlbe_ref *ref)
 static void clear_tlb1_bitmap(struct kvmppc_vcpu_e500 *vcpu_e500)
 {
        if (vcpu_e500->g2h_tlb1_map)
-               memset(vcpu_e500->g2h_tlb1_map,
-                      sizeof(u64) * vcpu_e500->gtlb_params[1].entries, 0);
+               memset(vcpu_e500->g2h_tlb1_map, 0,
+                      sizeof(u64) * vcpu_e500->gtlb_params[1].entries);
        if (vcpu_e500->h2g_tlb1_rmap)
-               memset(vcpu_e500->h2g_tlb1_rmap,
-                      sizeof(unsigned int) * host_tlb_params[1].entries, 0);
+               memset(vcpu_e500->h2g_tlb1_rmap, 0,
+                      sizeof(unsigned int) * host_tlb_params[1].entries);
 }
 
 static void clear_tlb_privs(struct kvmppc_vcpu_e500 *vcpu_e500)
@@ -539,6 +539,9 @@ static inline void kvmppc_e500_shadow_map(struct kvmppc_vcpu_e500 *vcpu_e500,
 
        kvmppc_e500_setup_stlbe(&vcpu_e500->vcpu, gtlbe, tsize,
                                ref, gvaddr, stlbe);
+
+       /* Clear i-cache for new pages */
+       kvmppc_mmu_flush_icache(pfn);
 }
 
 /* XXX only map the one-one case, for now use TLB0 */
index dd223b3eb333ac3446725f0768d5da412000ba75..17e5b23643124347febe56a05f5deb7e1a2e361e 100644 (file)
@@ -20,7 +20,7 @@ int patch_instruction(unsigned int *addr, unsigned int instr)
 {
        int err;
 
-       err = __put_user(instr, addr);
+       __put_user_size(instr, addr, 4, err);
        if (err)
                return err;
        asm ("dcbst 0, %0; sync; icbi 0,%0; sync; isync" : : "r" (addr));
index f9ede7c6606e54d36f4b54fddc5b3101085ee5ef..0d24ff15f5f6fb197af85a4d9e537eb8880f099c 100644 (file)
@@ -288,7 +288,7 @@ err1;       stb     r0,0(r3)
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
        bl      .enter_vmx_usercopy
-       cmpwi   r3,0
+       cmpwi   cr1,r3,0
        ld      r0,STACKFRAMESIZE+16(r1)
        ld      r3,STACKFRAMESIZE+48(r1)
        ld      r4,STACKFRAMESIZE+56(r1)
@@ -326,38 +326,7 @@ err1;      stb     r0,0(r3)
        dcbt    r0,r8,0b01010   /* GO */
 .machine pop
 
-       /*
-        * We prefetch both the source and destination using enhanced touch
-        * instructions. We use a stream ID of 0 for the load side and
-        * 1 for the store side.
-        */
-       clrrdi  r6,r4,7
-       clrrdi  r9,r3,7
-       ori     r9,r9,1         /* stream=1 */
-
-       srdi    r7,r5,7         /* length in cachelines, capped at 0x3FF */
-       cmpldi  cr1,r7,0x3FF
-       ble     cr1,1f
-       li      r7,0x3FF
-1:     lis     r0,0x0E00       /* depth=7 */
-       sldi    r7,r7,7
-       or      r7,r7,r0
-       ori     r10,r7,1        /* stream=1 */
-
-       lis     r8,0x8000       /* GO=1 */
-       clrldi  r8,r8,32
-
-.machine push
-.machine "power4"
-       dcbt    r0,r6,0b01000
-       dcbt    r0,r7,0b01010
-       dcbtst  r0,r9,0b01000
-       dcbtst  r0,r10,0b01010
-       eieio
-       dcbt    r0,r8,0b01010   /* GO */
-.machine pop
-
-       beq     .Lunwind_stack_nonvmx_copy
+       beq     cr1,.Lunwind_stack_nonvmx_copy
 
        /*
         * If source and destination are not relatively aligned we use a
index 0efdc51bc7164cf9a1089189a8c6fc64e35002a4..7ba6c96de77856e426fe5cf83ff360280e239194 100644 (file)
@@ -222,7 +222,7 @@ _GLOBAL(memcpy_power7)
        std     r0,16(r1)
        stdu    r1,-STACKFRAMESIZE(r1)
        bl      .enter_vmx_copy
-       cmpwi   r3,0
+       cmpwi   cr1,r3,0
        ld      r0,STACKFRAMESIZE+16(r1)
        ld      r3,STACKFRAMESIZE+48(r1)
        ld      r4,STACKFRAMESIZE+56(r1)
@@ -260,7 +260,7 @@ _GLOBAL(memcpy_power7)
        dcbt    r0,r8,0b01010   /* GO */
 .machine pop
 
-       beq     .Lunwind_stack_nonvmx_copy
+       beq     cr1,.Lunwind_stack_nonvmx_copy
 
        /*
         * If source and destination are not relatively aligned we use a
index baaafde7d13596af850a9d7452e596d84a52935a..fbdad0e3929a8ddfbcb0f714a6480f0ca33ba6f6 100644 (file)
@@ -469,6 +469,7 @@ void flush_dcache_icache_page(struct page *page)
        __flush_dcache_icache_phys(page_to_pfn(page) << PAGE_SHIFT);
 #endif
 }
+EXPORT_SYMBOL(flush_dcache_icache_page);
 
 void clear_user_page(void *page, unsigned long vaddr, struct page *pg)
 {
index 39b159751c35ab17d5e3df0dd48282abe5228700..59213cfaeca9f868143261b2a246834c115b6542 100644 (file)
@@ -1436,11 +1436,11 @@ static long vphn_get_associativity(unsigned long cpu,
 
 /*
  * Update the node maps and sysfs entries for each cpu whose home node
- * has changed.
+ * has changed. Returns 1 when the topology has changed, and 0 otherwise.
  */
 int arch_update_cpu_topology(void)
 {
-       int cpu, nid, old_nid;
+       int cpu, nid, old_nid, changed = 0;
        unsigned int associativity[VPHN_ASSOC_BUFSIZE] = {0};
        struct device *dev;
 
@@ -1466,9 +1466,10 @@ int arch_update_cpu_topology(void)
                dev = get_cpu_device(cpu);
                if (dev)
                        kobject_uevent(&dev->kobj, KOBJ_CHANGE);
+               changed = 1;
        }
 
-       return 1;
+       return changed;
 }
 
 static void topology_work_fn(struct work_struct *work)
index 77b49ddda9d3675ed816d65af7f8c242578c01a0..7cd2dbd6e4c4fa615ae4442c5d00af106f3e17dd 100644 (file)
@@ -1431,7 +1431,7 @@ static void perf_event_interrupt(struct pt_regs *regs)
                if (!event->hw.idx || is_limited_pmc(event->hw.idx))
                        continue;
                val = read_pmc(event->hw.idx);
-               if ((int)val < 0) {
+               if (pmc_overflow(val)) {
                        /* event has overflowed */
                        found = 1;
                        record_and_restart(event, val, regs);
index 3ef46254c35ba907dfd9329f9164db3176a9d7a4..7698b6e13c57f6312a7505a3610fbf6b27271991 100644 (file)
@@ -106,14 +106,6 @@ static void pnv_smp_cpu_kill_self(void)
 {
        unsigned int cpu;
 
-       /* If powersave_nap is enabled, use NAP mode, else just
-        * spin aimlessly
-        */
-       if (!powersave_nap) {
-               generic_mach_cpu_die();
-               return;
-       }
-
        /* Standard hot unplug procedure */
        local_irq_disable();
        idle_task_exit();
@@ -128,7 +120,7 @@ static void pnv_smp_cpu_kill_self(void)
         */
        mtspr(SPRN_LPCR, mfspr(SPRN_LPCR) & ~(u64)LPCR_PECE1);
        while (!generic_check_cpu_restart(cpu)) {
-               power7_idle();
+               power7_nap();
                if (!generic_check_cpu_restart(cpu)) {
                        DBG("CPU%d Unexpected exit while offline !\n", cpu);
                        /* We may be getting an IPI, so we re-enable
index a7b2a600d0a4d0aa7878a633eb3549f0a0d3a373..c37f46136321272465327a106383fb440e48fa75 100644 (file)
@@ -465,7 +465,7 @@ int __init fsl_add_bridge(struct device_node *dev, int is_primary)
                        iounmap(hose->cfg_data);
                iounmap(hose->cfg_addr);
                pcibios_free_controller(hose);
-               return 0;
+               return -ENODEV;
        }
 
        setup_pci_cmd(hose);
@@ -827,6 +827,7 @@ struct device_node *fsl_pci_primary;
 
 void __devinit fsl_pci_init(void)
 {
+       int ret;
        struct device_node *node;
        struct pci_controller *hose;
        dma_addr_t max = 0xffffffff;
@@ -855,10 +856,12 @@ void __devinit fsl_pci_init(void)
                        if (!fsl_pci_primary)
                                fsl_pci_primary = node;
 
-                       fsl_add_bridge(node, fsl_pci_primary == node);
-                       hose = pci_find_hose_for_OF_device(node);
-                       max = min(max, hose->dma_window_base_cur +
-                                       hose->dma_window_size);
+                       ret = fsl_add_bridge(node, fsl_pci_primary == node);
+                       if (ret == 0) {
+                               hose = pci_find_hose_for_OF_device(node);
+                               max = min(max, hose->dma_window_base_cur +
+                                               hose->dma_window_size);
+                       }
                }
        }
 
index 483d8fa72e8ba3bc6bca736faf2f007399282e13..e961f8c4a8f070f341c2b80bbd8a18456a323ade 100644 (file)
@@ -14,6 +14,9 @@
 #include <linux/list.h>
 #include <linux/of_platform.h>
 #include <linux/errno.h>
+#include <linux/err.h>
+#include <linux/export.h>
+#include <linux/slab.h>
 #include <asm/prom.h>
 #include <asm/hw_irq.h>
 #include <asm/ppc-pci.h>
index 14469cf9df68dc8497408a8953cbbbcf7b360ea1..df0fc58214697623b429f55555d494e8ccf56c52 100644 (file)
@@ -65,7 +65,11 @@ static inline void icp_hv_set_xirr(unsigned int value)
 static inline void icp_hv_set_qirr(int n_cpu , u8 value)
 {
        int hw_cpu = get_hard_smp_processor_id(n_cpu);
-       long rc = plpar_hcall_norets(H_IPI, hw_cpu, value);
+       long rc;
+
+       /* Make sure all previous accesses are ordered before IPI sending */
+       mb();
+       rc = plpar_hcall_norets(H_IPI, hw_cpu, value);
        if (rc != H_SUCCESS) {
                pr_err("%s: bad return code qirr cpu=%d hw_cpu=%d mfrr=0x%x "
                        "returned %ld\n", __func__, n_cpu, hw_cpu, value, rc);
index eab3492a45c5c5244eca42d58354cf6d8a092836..9b49c65ee7a42f6f9d0b8dc436628c34bafb262b 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/reboot.h>
 #include <linux/delay.h>
 #include <linux/kallsyms.h>
+#include <linux/kmsg_dump.h>
 #include <linux/cpumask.h>
 #include <linux/export.h>
 #include <linux/sysrq.h>
@@ -894,13 +895,13 @@ cmds(struct pt_regs *excp)
 #endif
                default:
                        printf("Unrecognized command: ");
-                       do {
+                       do {
                                if (' ' < cmd && cmd <= '~')
                                        putchar(cmd);
                                else
                                        printf("\\x%x", cmd);
                                cmd = inchar();
-                       } while (cmd != '\n'); 
+                       } while (cmd != '\n');
                        printf(" (type ? for help)\n");
                        break;
                }
@@ -1097,7 +1098,7 @@ static long check_bp_loc(unsigned long addr)
        return 1;
 }
 
-static char *breakpoint_help_string = 
+static char *breakpoint_help_string =
     "Breakpoint command usage:\n"
     "b                show breakpoints\n"
     "b <addr> [cnt]   set breakpoint at given instr addr\n"
@@ -1193,7 +1194,7 @@ bpt_cmds(void)
 
        default:
                termch = cmd;
-               cmd = skipbl();
+               cmd = skipbl();
                if (cmd == '?') {
                        printf(breakpoint_help_string);
                        break;
@@ -1359,7 +1360,7 @@ static void xmon_show_stack(unsigned long sp, unsigned long lr,
                                       sp + REGS_OFFSET);
                                break;
                        }
-                        printf("--- Exception: %lx %s at ", regs.trap,
+                       printf("--- Exception: %lx %s at ", regs.trap,
                               getvecname(TRAP(&regs)));
                        pc = regs.nip;
                        lr = regs.link;
@@ -1623,14 +1624,14 @@ static void super_regs(void)
 
        cmd = skipbl();
        if (cmd == '\n') {
-               unsigned long sp, toc;
+               unsigned long sp, toc;
                asm("mr %0,1" : "=r" (sp) :);
                asm("mr %0,2" : "=r" (toc) :);
 
                printf("msr  = "REG"  sprg0= "REG"\n",
                       mfmsr(), mfspr(SPRN_SPRG0));
                printf("pvr  = "REG"  sprg1= "REG"\n",
-                      mfspr(SPRN_PVR), mfspr(SPRN_SPRG1)); 
+                      mfspr(SPRN_PVR), mfspr(SPRN_SPRG1));
                printf("dec  = "REG"  sprg2= "REG"\n",
                       mfspr(SPRN_DEC), mfspr(SPRN_SPRG2));
                printf("sp   = "REG"  sprg3= "REG"\n", sp, mfspr(SPRN_SPRG3));
@@ -1783,7 +1784,7 @@ byterev(unsigned char *val, int size)
 static int brev;
 static int mnoread;
 
-static char *memex_help_string = 
+static char *memex_help_string =
     "Memory examine command usage:\n"
     "m [addr] [flags] examine/change memory\n"
     "  addr is optional.  will start where left off.\n"
@@ -1798,7 +1799,7 @@ static char *memex_help_string =
     "NOTE: flags are saved as defaults\n"
     "";
 
-static char *memex_subcmd_help_string = 
+static char *memex_subcmd_help_string =
     "Memory examine subcommands:\n"
     "  hexval   write this val to current location\n"
     "  'string' write chars from string to this location\n"
@@ -2064,7 +2065,7 @@ prdump(unsigned long adrs, long ndump)
                nr = mread(adrs, temp, r);
                adrs += nr;
                for (m = 0; m < r; ++m) {
-                       if ((m & (sizeof(long) - 1)) == 0 && m > 0)
+                       if ((m & (sizeof(long) - 1)) == 0 && m > 0)
                                putchar(' ');
                        if (m < nr)
                                printf("%.2x", temp[m]);
@@ -2072,7 +2073,7 @@ prdump(unsigned long adrs, long ndump)
                                printf("%s", fault_chars[fault_type]);
                }
                for (; m < 16; ++m) {
-                       if ((m & (sizeof(long) - 1)) == 0)
+                       if ((m & (sizeof(long) - 1)) == 0)
                                putchar(' ');
                        printf("  ");
                }
@@ -2148,45 +2149,28 @@ print_address(unsigned long addr)
 void
 dump_log_buf(void)
 {
-        const unsigned long size = 128;
-        unsigned long end, addr;
-        unsigned char buf[size + 1];
-
-        addr = 0;
-        buf[size] = '\0';
-
-        if (setjmp(bus_error_jmp) != 0) {
-                printf("Unable to lookup symbol __log_buf!\n");
-                return;
-        }
-
-        catch_memory_errors = 1;
-        sync();
-        addr = kallsyms_lookup_name("__log_buf");
-
-        if (! addr)
-                printf("Symbol __log_buf not found!\n");
-        else {
-                end = addr + (1 << CONFIG_LOG_BUF_SHIFT);
-                while (addr < end) {
-                        if (! mread(addr, buf, size)) {
-                                printf("Can't read memory at address 0x%lx\n", addr);
-                                break;
-                        }
-
-                        printf("%s", buf);
-
-                        if (strlen(buf) < size)
-                                break;
-
-                        addr += size;
-                }
-        }
-
-        sync();
-        /* wait a little while to see if we get a machine check */
-        __delay(200);
-        catch_memory_errors = 0;
+       struct kmsg_dumper dumper = { .active = 1 };
+       unsigned char buf[128];
+       size_t len;
+
+       if (setjmp(bus_error_jmp) != 0) {
+               printf("Error dumping printk buffer!\n");
+               return;
+       }
+
+       catch_memory_errors = 1;
+       sync();
+
+       kmsg_dump_rewind_nolock(&dumper);
+       while (kmsg_dump_get_line_nolock(&dumper, false, buf, sizeof(buf), &len)) {
+               buf[len] = '\0';
+               printf("%s", buf);
+       }
+
+       sync();
+       /* wait a little while to see if we get a machine check */
+       __delay(200);
+       catch_memory_errors = 0;
 }
 
 /*
index 32e8449640facbef375b0a5cb1d33610290c3a7e..9b94a160fe7f06399222ead8530e5a2da2b94f78 100644 (file)
@@ -180,7 +180,8 @@ extern char elf_platform[];
 #define ELF_PLATFORM (elf_platform)
 
 #ifndef CONFIG_64BIT
-#define SET_PERSONALITY(ex) set_personality(PER_LINUX)
+#define SET_PERSONALITY(ex) \
+       set_personality(PER_LINUX | (current->personality & (~PER_MASK)))
 #else /* CONFIG_64BIT */
 #define SET_PERSONALITY(ex)                                    \
 do {                                                           \
index 799ed0f1643d135c843f3a1cdc41204063289f0f..2d6e6e3805641bbc79ce1ee11aa639f48f5e2933 100644 (file)
@@ -66,16 +66,6 @@ static inline pte_t huge_ptep_get(pte_t *ptep)
        return pte;
 }
 
-static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
-                                           unsigned long addr, pte_t *ptep)
-{
-       pte_t pte = huge_ptep_get(ptep);
-
-       mm->context.flush_mm = 1;
-       pmd_clear((pmd_t *) ptep);
-       return pte;
-}
-
 static inline void __pmd_csp(pmd_t *pmdp)
 {
        register unsigned long reg2 asm("2") = pmd_val(*pmdp);
@@ -117,6 +107,15 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
                __pmd_csp(pmdp);
 }
 
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+                                           unsigned long addr, pte_t *ptep)
+{
+       pte_t pte = huge_ptep_get(ptep);
+
+       huge_ptep_invalidate(mm, addr, ptep);
+       return pte;
+}
+
 #define huge_ptep_set_access_flags(__vma, __addr, __ptep, __entry, __dirty) \
 ({                                                                         \
        int __changed = !pte_same(huge_ptep_get(__ptep), __entry);          \
@@ -131,10 +130,7 @@ static inline void huge_ptep_invalidate(struct mm_struct *mm,
 ({                                                                     \
        pte_t __pte = huge_ptep_get(__ptep);                            \
        if (pte_write(__pte)) {                                         \
-               (__mm)->context.flush_mm = 1;                           \
-               if (atomic_read(&(__mm)->context.attach_count) > 1 ||   \
-                   (__mm) != current->active_mm)                       \
-                       huge_ptep_invalidate(__mm, __addr, __ptep);     \
+               huge_ptep_invalidate(__mm, __addr, __ptep);             \
                set_huge_pte_at(__mm, __addr, __ptep,                   \
                                huge_pte_wrprotect(__pte));             \
        }                                                               \
index 7bcc14e395f0a2fd1d85ded571010e05c5c0392e..bf2a2ad2f8004ab36e98d49fccb084a67fba0049 100644 (file)
@@ -13,6 +13,7 @@
  */
 
 typedef unsigned long   __kernel_size_t;
+typedef long            __kernel_ssize_t;
 #define __kernel_size_t __kernel_size_t
 
 typedef unsigned short __kernel_old_dev_t;
@@ -25,7 +26,6 @@ typedef unsigned short  __kernel_mode_t;
 typedef unsigned short  __kernel_ipc_pid_t;
 typedef unsigned short  __kernel_uid_t;
 typedef unsigned short  __kernel_gid_t;
-typedef int             __kernel_ssize_t;
 typedef int             __kernel_ptrdiff_t;
 
 #else /* __s390x__ */
@@ -35,7 +35,6 @@ typedef unsigned int    __kernel_mode_t;
 typedef int             __kernel_ipc_pid_t;
 typedef unsigned int    __kernel_uid_t;
 typedef unsigned int    __kernel_gid_t;
-typedef long            __kernel_ssize_t;
 typedef long            __kernel_ptrdiff_t;
 typedef unsigned long   __kernel_sigset_t;      /* at least 32 bits */
 
index a0a8340daafafb90ad25c822949b6ace5a84a595..ce26ac3cb162899a285e5812a39ea9b1b6ec0484 100644 (file)
@@ -44,6 +44,7 @@ static inline void smp_call_online_cpu(void (*func)(void *), void *data)
 }
 
 static inline int smp_find_processor_id(int address) { return 0; }
+static inline int smp_store_status(int cpu) { return 0; }
 static inline int smp_vcpu_scheduled(int cpu) { return 1; }
 static inline void smp_yield_cpu(int cpu) { }
 static inline void smp_yield(void) { }
index 9fde315f3a7cd42184a54f2174584258076e6a60..1d8fe2b17ef6f1d0069c0e3cc8ff70c7d9cc402a 100644 (file)
@@ -90,12 +90,10 @@ static inline void __tlb_flush_mm(struct mm_struct * mm)
 
 static inline void __tlb_flush_mm_cond(struct mm_struct * mm)
 {
-       spin_lock(&mm->page_table_lock);
        if (mm->context.flush_mm) {
                __tlb_flush_mm(mm);
                mm->context.flush_mm = 0;
        }
-       spin_unlock(&mm->page_table_lock);
 }
 
 /*
index f86c81e13c374be484f591faead417a7fb3ee572..40b57693de389b24a5b08decae1dbb1fedd47e6c 100644 (file)
@@ -974,11 +974,13 @@ static void __init setup_hwcaps(void)
        if (MACHINE_HAS_HPAGE)
                elf_hwcap |= HWCAP_S390_HPAGE;
 
+#if defined(CONFIG_64BIT)
        /*
         * 64-bit register support for 31-bit processes
         * HWCAP_S390_HIGH_GPRS is bit 9.
         */
        elf_hwcap |= HWCAP_S390_HIGH_GPRS;
+#endif
 
        get_cpu_id(&cpu_id);
        switch (cpu_id.machine) {
index 60ee2b8837972c27d8bfb3d95dd9fc3b0b4d0091..2d37bb861faf69cf43e30971881fae771322158a 100644 (file)
@@ -2,69 +2,82 @@
  *  User access functions based on page table walks for enhanced
  *  system layout without hardware support.
  *
- *    Copyright IBM Corp. 2006
+ *    Copyright IBM Corp. 2006, 2012
  *    Author(s): Gerald Schaefer (gerald.schaefer@de.ibm.com)
  */
 
 #include <linux/errno.h>
 #include <linux/hardirq.h>
 #include <linux/mm.h>
+#include <linux/hugetlb.h>
 #include <asm/uaccess.h>
 #include <asm/futex.h>
 #include "uaccess.h"
 
-static inline pte_t *follow_table(struct mm_struct *mm, unsigned long addr)
+
+/*
+ * Returns kernel address for user virtual address. If the returned address is
+ * >= -4095 (IS_ERR_VALUE(x) returns true), a fault has occured and the address
+ * contains the (negative) exception code.
+ */
+static __always_inline unsigned long follow_table(struct mm_struct *mm,
+                                                 unsigned long addr, int write)
 {
        pgd_t *pgd;
        pud_t *pud;
        pmd_t *pmd;
+       pte_t *ptep;
 
        pgd = pgd_offset(mm, addr);
        if (pgd_none(*pgd) || unlikely(pgd_bad(*pgd)))
-               return (pte_t *) 0x3a;
+               return -0x3aUL;
 
        pud = pud_offset(pgd, addr);
        if (pud_none(*pud) || unlikely(pud_bad(*pud)))
-               return (pte_t *) 0x3b;
+               return -0x3bUL;
 
        pmd = pmd_offset(pud, addr);
-       if (pmd_none(*pmd) || unlikely(pmd_bad(*pmd)))
-               return (pte_t *) 0x10;
+       if (pmd_none(*pmd))
+               return -0x10UL;
+       if (pmd_huge(*pmd)) {
+               if (write && (pmd_val(*pmd) & _SEGMENT_ENTRY_RO))
+                       return -0x04UL;
+               return (pmd_val(*pmd) & HPAGE_MASK) + (addr & ~HPAGE_MASK);
+       }
+       if (unlikely(pmd_bad(*pmd)))
+               return -0x10UL;
+
+       ptep = pte_offset_map(pmd, addr);
+       if (!pte_present(*ptep))
+               return -0x11UL;
+       if (write && !pte_write(*ptep))
+               return -0x04UL;
 
-       return pte_offset_map(pmd, addr);
+       return (pte_val(*ptep) & PAGE_MASK) + (addr & ~PAGE_MASK);
 }
 
 static __always_inline size_t __user_copy_pt(unsigned long uaddr, void *kptr,
                                             size_t n, int write_user)
 {
        struct mm_struct *mm = current->mm;
-       unsigned long offset, pfn, done, size;
-       pte_t *pte;
+       unsigned long offset, done, size, kaddr;
        void *from, *to;
 
        done = 0;
 retry:
        spin_lock(&mm->page_table_lock);
        do {
-               pte = follow_table(mm, uaddr);
-               if ((unsigned long) pte < 0x1000)
+               kaddr = follow_table(mm, uaddr, write_user);
+               if (IS_ERR_VALUE(kaddr))
                        goto fault;
-               if (!pte_present(*pte)) {
-                       pte = (pte_t *) 0x11;
-                       goto fault;
-               } else if (write_user && !pte_write(*pte)) {
-                       pte = (pte_t *) 0x04;
-                       goto fault;
-               }
 
-               pfn = pte_pfn(*pte);
-               offset = uaddr & (PAGE_SIZE - 1);
+               offset = uaddr & ~PAGE_MASK;
                size = min(n - done, PAGE_SIZE - offset);
                if (write_user) {
-                       to = (void *)((pfn << PAGE_SHIFT) + offset);
+                       to = (void *) kaddr;
                        from = kptr + done;
                } else {
-                       from = (void *)((pfn << PAGE_SHIFT) + offset);
+                       from = (void *) kaddr;
                        to = kptr + done;
                }
                memcpy(to, from, size);
@@ -75,7 +88,7 @@ retry:
        return n - done;
 fault:
        spin_unlock(&mm->page_table_lock);
-       if (__handle_fault(uaddr, (unsigned long) pte, write_user))
+       if (__handle_fault(uaddr, -kaddr, write_user))
                return n - done;
        goto retry;
 }
@@ -84,27 +97,22 @@ fault:
  * Do DAT for user address by page table walk, return kernel address.
  * This function needs to be called with current->mm->page_table_lock held.
  */
-static __always_inline unsigned long __dat_user_addr(unsigned long uaddr)
+static __always_inline unsigned long __dat_user_addr(unsigned long uaddr,
+                                                    int write)
 {
        struct mm_struct *mm = current->mm;
-       unsigned long pfn;
-       pte_t *pte;
+       unsigned long kaddr;
        int rc;
 
 retry:
-       pte = follow_table(mm, uaddr);
-       if ((unsigned long) pte < 0x1000)
-               goto fault;
-       if (!pte_present(*pte)) {
-               pte = (pte_t *) 0x11;
+       kaddr = follow_table(mm, uaddr, write);
+       if (IS_ERR_VALUE(kaddr))
                goto fault;
-       }
 
-       pfn = pte_pfn(*pte);
-       return (pfn << PAGE_SHIFT) + (uaddr & (PAGE_SIZE - 1));
+       return kaddr;
 fault:
        spin_unlock(&mm->page_table_lock);
-       rc = __handle_fault(uaddr, (unsigned long) pte, 0);
+       rc = __handle_fault(uaddr, -kaddr, write);
        spin_lock(&mm->page_table_lock);
        if (!rc)
                goto retry;
@@ -159,11 +167,9 @@ static size_t clear_user_pt(size_t n, void __user *to)
 
 static size_t strnlen_user_pt(size_t count, const char __user *src)
 {
-       char *addr;
        unsigned long uaddr = (unsigned long) src;
        struct mm_struct *mm = current->mm;
-       unsigned long offset, pfn, done, len;
-       pte_t *pte;
+       unsigned long offset, done, len, kaddr;
        size_t len_str;
 
        if (segment_eq(get_fs(), KERNEL_DS))
@@ -172,19 +178,13 @@ static size_t strnlen_user_pt(size_t count, const char __user *src)
 retry:
        spin_lock(&mm->page_table_lock);
        do {
-               pte = follow_table(mm, uaddr);
-               if ((unsigned long) pte < 0x1000)
-                       goto fault;
-               if (!pte_present(*pte)) {
-                       pte = (pte_t *) 0x11;
+               kaddr = follow_table(mm, uaddr, 0);
+               if (IS_ERR_VALUE(kaddr))
                        goto fault;
-               }
 
-               pfn = pte_pfn(*pte);
-               offset = uaddr & (PAGE_SIZE-1);
-               addr = (char *)(pfn << PAGE_SHIFT) + offset;
+               offset = uaddr & ~PAGE_MASK;
                len = min(count - done, PAGE_SIZE - offset);
-               len_str = strnlen(addr, len);
+               len_str = strnlen((char *) kaddr, len);
                done += len_str;
                uaddr += len_str;
        } while ((len_str == len) && (done < count));
@@ -192,7 +192,7 @@ retry:
        return done + 1;
 fault:
        spin_unlock(&mm->page_table_lock);
-       if (__handle_fault(uaddr, (unsigned long) pte, 0))
+       if (__handle_fault(uaddr, -kaddr, 0))
                return 0;
        goto retry;
 }
@@ -225,11 +225,10 @@ static size_t copy_in_user_pt(size_t n, void __user *to,
                              const void __user *from)
 {
        struct mm_struct *mm = current->mm;
-       unsigned long offset_from, offset_to, offset_max, pfn_from, pfn_to,
-                     uaddr, done, size, error_code;
+       unsigned long offset_max, uaddr, done, size, error_code;
        unsigned long uaddr_from = (unsigned long) from;
        unsigned long uaddr_to = (unsigned long) to;
-       pte_t *pte_from, *pte_to;
+       unsigned long kaddr_to, kaddr_from;
        int write_user;
 
        if (segment_eq(get_fs(), KERNEL_DS)) {
@@ -242,38 +241,23 @@ retry:
        do {
                write_user = 0;
                uaddr = uaddr_from;
-               pte_from = follow_table(mm, uaddr_from);
-               error_code = (unsigned long) pte_from;
-               if (error_code < 0x1000)
-                       goto fault;
-               if (!pte_present(*pte_from)) {
-                       error_code = 0x11;
+               kaddr_from = follow_table(mm, uaddr_from, 0);
+               error_code = kaddr_from;
+               if (IS_ERR_VALUE(error_code))
                        goto fault;
-               }
 
                write_user = 1;
                uaddr = uaddr_to;
-               pte_to = follow_table(mm, uaddr_to);
-               error_code = (unsigned long) pte_to;
-               if (error_code < 0x1000)
-                       goto fault;
-               if (!pte_present(*pte_to)) {
-                       error_code = 0x11;
+               kaddr_to = follow_table(mm, uaddr_to, 1);
+               error_code = (unsigned long) kaddr_to;
+               if (IS_ERR_VALUE(error_code))
                        goto fault;
-               } else if (!pte_write(*pte_to)) {
-                       error_code = 0x04;
-                       goto fault;
-               }
 
-               pfn_from = pte_pfn(*pte_from);
-               pfn_to = pte_pfn(*pte_to);
-               offset_from = uaddr_from & (PAGE_SIZE-1);
-               offset_to = uaddr_from & (PAGE_SIZE-1);
-               offset_max = max(offset_from, offset_to);
+               offset_max = max(uaddr_from & ~PAGE_MASK,
+                                uaddr_to & ~PAGE_MASK);
                size = min(n - done, PAGE_SIZE - offset_max);
 
-               memcpy((void *)(pfn_to << PAGE_SHIFT) + offset_to,
-                      (void *)(pfn_from << PAGE_SHIFT) + offset_from, size);
+               memcpy((void *) kaddr_to, (void *) kaddr_from, size);
                done += size;
                uaddr_from += size;
                uaddr_to += size;
@@ -282,7 +266,7 @@ retry:
        return n - done;
 fault:
        spin_unlock(&mm->page_table_lock);
-       if (__handle_fault(uaddr, error_code, write_user))
+       if (__handle_fault(uaddr, -error_code, write_user))
                return n - done;
        goto retry;
 }
@@ -341,7 +325,7 @@ int futex_atomic_op_pt(int op, u32 __user *uaddr, int oparg, int *old)
                return __futex_atomic_op_pt(op, uaddr, oparg, old);
        spin_lock(&current->mm->page_table_lock);
        uaddr = (u32 __force __user *)
-               __dat_user_addr((__force unsigned long) uaddr);
+               __dat_user_addr((__force unsigned long) uaddr, 1);
        if (!uaddr) {
                spin_unlock(&current->mm->page_table_lock);
                return -EFAULT;
@@ -378,7 +362,7 @@ int futex_atomic_cmpxchg_pt(u32 *uval, u32 __user *uaddr,
                return __futex_atomic_cmpxchg_pt(uval, uaddr, oldval, newval);
        spin_lock(&current->mm->page_table_lock);
        uaddr = (u32 __force __user *)
-               __dat_user_addr((__force unsigned long) uaddr);
+               __dat_user_addr((__force unsigned long) uaddr, 1);
        if (!uaddr) {
                spin_unlock(&current->mm->page_table_lock);
                return -EFAULT;
index a1e9d69a9c90e579c2f68cea8869ae6ec26d05c4..584b93674ea43bceea2259142081ef81a02ad9aa 100644 (file)
@@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf,
        if (*offset)
                return -EINVAL;
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
        if (val < oprofile_min_interval)
                oprofile_hw_interval = oprofile_min_interval;
@@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
        if (val != 0)
                return -EINVAL;
@@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
@@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
@@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf,
                return -EINVAL;
 
        retval = oprofilefs_ulong_from_user(&val, buf, count);
-       if (retval)
+       if (retval <= 0)
                return retval;
 
        if (val != 0 && val != 1)
index b7cf6a547f117c5eeae4b69f6b1ccbcdb41b37c8..7e605b95592aea7ac767b817df3a7a61af8d4f20 100644 (file)
@@ -933,7 +933,7 @@ ret_with_reschedule:
 
        pta     restore_all, tr1
 
-       movi    _TIF_SIGPENDING, r8
+       movi    (_TIF_SIGPENDING|_TIF_NOTIFY_RESUME), r8
        and     r8, r7, r8
        pta     work_notifysig, tr0
        bne     r8, ZERO, tr0
index f67601cb3f1f47da13a49ae4948021800b9a2f4d..b96489d8b27dde9e38630d51de4e9d7f04115c08 100644 (file)
@@ -139,7 +139,7 @@ work_pending:
        ! r8: current_thread_info
        ! t:  result of "tst    #_TIF_NEED_RESCHED, r0"
        bf/s    work_resched
-        tst    #_TIF_SIGPENDING, r0
+        tst    #(_TIF_SIGPENDING | _TIF_NOTIFY_RESUME), r0
 work_notifysig:
        bt/s    __restore_all
         mov    r15, r4
index 15e0a16939765148efd633663c131390daaa9893..f1ddc0d2367947d850e863aa4d0a897705074574 100644 (file)
@@ -48,9 +48,7 @@ void *module_alloc(unsigned long size)
                return NULL;
 
        ret = module_map(size);
-       if (!ret)
-               ret = ERR_PTR(-ENOMEM);
-       else
+       if (ret)
                memset(ret, 0, size);
 
        return ret;
@@ -116,6 +114,10 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                v = sym->st_value + rel[i].r_addend;
 
                switch (ELF_R_TYPE(rel[i].r_info) & 0xff) {
+               case R_SPARC_DISP32:
+                       v -= (Elf_Addr) location;
+                       *loc32 = v;
+                       break;
 #ifdef CONFIG_SPARC64
                case R_SPARC_64:
                        location[0] = v >> 56;
@@ -128,11 +130,6 @@ int apply_relocate_add(Elf_Shdr *sechdrs,
                        location[7] = v >>  0;
                        break;
 
-               case R_SPARC_DISP32:
-                       v -= (Elf_Addr) location;
-                       *loc32 = v;
-                       break;
-
                case R_SPARC_WDISP19:
                        v -= (Elf_Addr) location;
                        *loc32 = (*loc32 & ~0x7ffff) |
index 15fb779920831eb38b110ec5530b1562d647171b..58105c31228b3b6643783e926b2db7886739ba01 100644 (file)
 #include <linux/module.h>
 #include <asm/pgtable.h>
 
-#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_DEALLOC_ASID      IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1400)
+#define GXIO_TRIO_OP_ALLOC_ASIDS       IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1401)
 
-#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1402)
+#define GXIO_TRIO_OP_ALLOC_MEMORY_MAPS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1404)
 
-#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140e)
-#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x140f)
+#define GXIO_TRIO_OP_ALLOC_PIO_REGIONS IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1412)
 
-#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1417)
-#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1418)
-#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1419)
-#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x141a)
+#define GXIO_TRIO_OP_INIT_PIO_REGION_AUX IORPC_OPCODE(IORPC_FORMAT_NONE, 0x1414)
 
-#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141c)
-#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141d)
-#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_INIT_MEMORY_MAP_MMU_AUX IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141e)
+#define GXIO_TRIO_OP_GET_PORT_PROPERTY IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x141f)
+#define GXIO_TRIO_OP_CONFIG_LEGACY_INTR IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1420)
+#define GXIO_TRIO_OP_CONFIG_MSI_INTR   IORPC_OPCODE(IORPC_FORMAT_KERNEL_INTERRUPT, 0x1421)
+
+#define GXIO_TRIO_OP_SET_MPS_MRS       IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1423)
+#define GXIO_TRIO_OP_FORCE_RC_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1424)
+#define GXIO_TRIO_OP_FORCE_EP_LINK_UP  IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x1425)
 #define GXIO_TRIO_OP_GET_MMIO_BASE     IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8000)
 #define GXIO_TRIO_OP_CHECK_MMIO_OFFSET IORPC_OPCODE(IORPC_FORMAT_NONE_NOUSER, 0x8001)
 
index 69f1c57a8d0dc895c727b74e1a53f8acd6c94a4c..33a6a2423bd25638a2b93f20fdc77bcf6e0f1737 100644 (file)
@@ -20,14 +20,6 @@ struct mm_struct;
 
 struct thread_struct {
        struct task_struct *saved_task;
-       /*
-        * This flag is set to 1 before calling do_fork (and analyzed in
-        * copy_thread) to mark that we are begin called from userspace (fork /
-        * vfork / clone), and reset to 0 after. It is left to 0 when called
-        * from kernelspace (i.e. kernel_thread() or fork_idle(),
-        * as of 2.6.11).
-        */
-       int forking;
        struct pt_regs regs;
        int singlestep_syscall;
        void *fault_addr;
@@ -58,7 +50,6 @@ struct thread_struct {
 
 #define INIT_THREAD \
 { \
-       .forking                = 0, \
        .regs                   = EMPTY_REGS,   \
        .fault_addr             = NULL, \
        .prev_sched             = NULL, \
index 40db8f71deaef4eb19c10a09e4f01d51078d3c8d..2df313b6a586c82b6e1dec743d174b0ddd190a9e 100644 (file)
@@ -7,16 +7,6 @@ DEFINE(UM_KERN_PAGE_MASK, PAGE_MASK);
 DEFINE(UM_KERN_PAGE_SHIFT, PAGE_SHIFT);
 DEFINE(UM_NSEC_PER_SEC, NSEC_PER_SEC);
 
-DEFINE_STR(UM_KERN_EMERG, KERN_EMERG);
-DEFINE_STR(UM_KERN_ALERT, KERN_ALERT);
-DEFINE_STR(UM_KERN_CRIT, KERN_CRIT);
-DEFINE_STR(UM_KERN_ERR, KERN_ERR);
-DEFINE_STR(UM_KERN_WARNING, KERN_WARNING);
-DEFINE_STR(UM_KERN_NOTICE, KERN_NOTICE);
-DEFINE_STR(UM_KERN_INFO, KERN_INFO);
-DEFINE_STR(UM_KERN_DEBUG, KERN_DEBUG);
-DEFINE_STR(UM_KERN_CONT, KERN_CONT);
-
 DEFINE(UM_ELF_CLASS, ELF_CLASS);
 DEFINE(UM_ELFCLASS32, ELFCLASS32);
 DEFINE(UM_ELFCLASS64, ELFCLASS64);
index 4fa82c055aab8d53576b06787aa1033644a16697..cef0685633369c05b6020f6071ae1a2ff094173a 100644 (file)
 extern void panic(const char *fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
 
+/* Requires preincluding include/linux/kern_levels.h */
+#define UM_KERN_EMERG  KERN_EMERG
+#define UM_KERN_ALERT  KERN_ALERT
+#define UM_KERN_CRIT   KERN_CRIT
+#define UM_KERN_ERR    KERN_ERR
+#define UM_KERN_WARNING        KERN_WARNING
+#define UM_KERN_NOTICE KERN_NOTICE
+#define UM_KERN_INFO   KERN_INFO
+#define UM_KERN_DEBUG  KERN_DEBUG
+#define UM_KERN_CONT   KERN_CONT
+
 #ifdef UML_CONFIG_PRINTK
 extern int printk(const char *fmt, ...)
        __attribute__ ((format (printf, 1, 2)));
index 6cade9366364d03f2fd58e2cee85336ffdea56e5..8c82786da823df2cdf53ad9361b9b950d85018c7 100644 (file)
@@ -39,34 +39,21 @@ void flush_thread(void)
 
 void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp)
 {
+       get_safe_registers(regs->regs.gp, regs->regs.fp);
        PT_REGS_IP(regs) = eip;
        PT_REGS_SP(regs) = esp;
-}
-EXPORT_SYMBOL(start_thread);
-
-static long execve1(const char *file,
-                   const char __user *const __user *argv,
-                   const char __user *const __user *env)
-{
-       long error;
-
-       error = do_execve(file, argv, env, &current->thread.regs);
-       if (error == 0) {
-               task_lock(current);
-               current->ptrace &= ~PT_DTRACE;
+       current->ptrace &= ~PT_DTRACE;
 #ifdef SUBARCH_EXECVE1
-               SUBARCH_EXECVE1(&current->thread.regs.regs);
+       SUBARCH_EXECVE1(regs->regs);
 #endif
-               task_unlock(current);
-       }
-       return error;
 }
+EXPORT_SYMBOL(start_thread);
 
 long um_execve(const char *file, const char __user *const __user *argv, const char __user *const __user *env)
 {
        long err;
 
-       err = execve1(file, argv, env);
+       err = do_execve(file, argv, env, &current->thread.regs);
        if (!err)
                UML_LONGJMP(current->thread.exec_buf, 1);
        return err;
@@ -81,7 +68,7 @@ long sys_execve(const char __user *file, const char __user *const __user *argv,
        filename = getname(file);
        error = PTR_ERR(filename);
        if (IS_ERR(filename)) goto out;
-       error = execve1(filename, argv, env);
+       error = do_execve(filename, argv, env, &current->thread.regs);
        putname(filename);
  out:
        return error;
index 57fc7028714a51af6fc19952d0947a913523ccec..c5f5afa5074571c2b5872bc157c9f199a80c9f5b 100644 (file)
@@ -181,11 +181,12 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                struct pt_regs *regs)
 {
        void (*handler)(void);
+       int kthread = current->flags & PF_KTHREAD;
        int ret = 0;
 
        p->thread = (struct thread_struct) INIT_THREAD;
 
-       if (current->thread.forking) {
+       if (!kthread) {
                memcpy(&p->thread.regs.regs, &regs->regs,
                       sizeof(p->thread.regs.regs));
                PT_REGS_SET_SYSCALL_RETURN(&p->thread.regs, 0);
@@ -195,8 +196,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
                handler = fork_handler;
 
                arch_copy_thread(&current->thread.arch, &p->thread.arch);
-       }
-       else {
+       } else {
                get_safe_registers(p->thread.regs.regs.gp, p->thread.regs.regs.fp);
                p->thread.request.u.thread = current->thread.request.u.thread;
                handler = new_thread_handler;
@@ -204,7 +204,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
 
        new_thread(task_stack_page(p), &p->thread.switch_buf, handler);
 
-       if (current->thread.forking) {
+       if (!kthread) {
                clear_flushed_tls(p);
 
                /*
index 7362d58efc29612c1ffaad64558b3a986b820515..cc9c2350e41741647f074cc4f43d6c4e3599123f 100644 (file)
@@ -22,9 +22,13 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
                         struct k_sigaction *ka, siginfo_t *info)
 {
        sigset_t *oldset = sigmask_to_save();
+       int singlestep = 0;
        unsigned long sp;
        int err;
 
+       if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
+               singlestep = 1;
+
        /* Did we come from a system call? */
        if (PT_REGS_SYSCALL_NR(regs) >= 0) {
                /* If so, check system call restarting.. */
@@ -61,7 +65,7 @@ static void handle_signal(struct pt_regs *regs, unsigned long signr,
        if (err)
                force_sigsegv(signr, current);
        else
-               signal_delivered(signr, info, ka, regs, 0);
+               signal_delivered(signr, info, ka, regs, singlestep);
 }
 
 static int kern_do_signal(struct pt_regs *regs)
index f958cb876ee3d3e47ddff71094e8026c0a110f5d..a4c6d8eee74c702999cc26955e250f40db30f553 100644 (file)
 
 long sys_fork(void)
 {
-       long ret;
-
-       current->thread.forking = 1;
-       ret = do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
+       return do_fork(SIGCHLD, UPT_SP(&current->thread.regs.regs),
                      &current->thread.regs, 0, NULL, NULL);
-       current->thread.forking = 0;
-       return ret;
 }
 
 long sys_vfork(void)
 {
-       long ret;
-
-       current->thread.forking = 1;
-       ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
+       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,
                      UPT_SP(&current->thread.regs.regs),
                      &current->thread.regs, 0, NULL, NULL);
-       current->thread.forking = 0;
-       return ret;
+}
+
+long sys_clone(unsigned long clone_flags, unsigned long newsp,
+              void __user *parent_tid, void __user *child_tid)
+{
+       if (!newsp)
+               newsp = UPT_SP(&current->thread.regs.regs);
+
+       return do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
+                     child_tid);
 }
 
 long old_mmap(unsigned long addr, unsigned long len,
index f60238559af309e00b031eedb17ad02ec77516d8..0748fe0c8a73dfa07aad69af8db1e4dcf5194550 100644 (file)
@@ -114,7 +114,7 @@ static void deliver_alarm(void)
        skew += this_tick - last_tick;
 
        while (skew >= one_tick) {
-               alarm_handler(SIGVTALRM, NULL);
+               alarm_handler(SIGVTALRM, NULL, NULL);
                skew -= one_tick;
        }
 
index d50270d26b427ace5d5f7c8777094298859a54c3..15889df9b4663771ccddc00f7e0275645ceceb0f 100644 (file)
@@ -8,7 +8,7 @@ USER_OBJS += $(filter %_user.o,$(obj-y) $(obj-m)  $(USER_SINGLE_OBJS))
 USER_OBJS := $(foreach file,$(USER_OBJS),$(obj)/$(file))
 
 $(USER_OBJS:.o=.%): \
-       c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include user.h $(CFLAGS_$(basetarget).o)
+       c_flags = -Wp,-MD,$(depfile) $(USER_CFLAGS) -include $(srctree)/include/linux/kern_levels.h -include user.h $(CFLAGS_$(basetarget).o)
 
 # These are like USER_OBJS but filter USER_CFLAGS through unprofile instead of
 # using it directly.
index 8ec3a1aa4abd3f612df4a5da31f30c67554d5182..50a1d1f9b6d3ac28c6b2294cd579d71cda2e75c1 100644 (file)
@@ -746,10 +746,10 @@ config SWIOTLB
        def_bool y if X86_64
        ---help---
          Support for software bounce buffers used on x86-64 systems
-         which don't have a hardware IOMMU (e.g. the current generation
-         of Intel's x86-64 CPUs). Using this PCI devices which can only
-         access 32-bits of memory can be used on systems with more than
-         3 GB of memory. If unsure, say Y.
+         which don't have a hardware IOMMU. Using this PCI devices
+         which can only access 32-bits of memory can be used on systems
+         with more than 3 GB of memory.
+         If unsure, say Y.
 
 config IOMMU_HELPER
        def_bool (CALGARY_IOMMU || GART_IOMMU || SWIOTLB || AMD_IOMMU)
index 682e9c210baacb99b86817adbd45ebbd17a30955..474ca35b1bce342356b27ac4118f133135d8c249 100644 (file)
@@ -142,7 +142,7 @@ KBUILD_CFLAGS += $(call cc-option,-mno-avx,)
 KBUILD_CFLAGS += $(mflags-y)
 KBUILD_AFLAGS += $(mflags-y)
 
-archscripts:
+archscripts: scripts_basic
        $(Q)$(MAKE) $(build)=arch/x86/tools relocs
 
 ###
index b315a33867f25963808ebe9fc81ec9889a8deca7..33692eaabab58619c7481cbfc7c6f01be929e5e9 100644 (file)
@@ -12,8 +12,7 @@
  * Simple spin lock operations.  There are two variants, one clears IRQ's
  * on the local processor, one does not.
  *
- * These are fair FIFO ticket locks, which are currently limited to 256
- * CPUs.
+ * These are fair FIFO ticket locks, which support up to 2^16 CPUs.
  *
  * (the type definitions are in asm/spinlock_types.h)
  */
index 93971e841dd5e7eaa032f5f4a8d5542040900a6d..472b9b783019a2e2f7c7b273ab7b13b96ec257b9 100644 (file)
@@ -51,7 +51,8 @@ extern unsigned long set_phys_range_identity(unsigned long pfn_s,
 
 extern int m2p_add_override(unsigned long mfn, struct page *page,
                            struct gnttab_map_grant_ref *kmap_op);
-extern int m2p_remove_override(struct page *page, bool clear_pte);
+extern int m2p_remove_override(struct page *page,
+                               struct gnttab_map_grant_ref *kmap_op);
 extern struct page *m2p_find_override(unsigned long mfn);
 extern unsigned long m2p_find_override_pfn(unsigned long mfn, unsigned long pfn);
 
index afb7ff79a29fbb33c6578c9240c7e5b550417b88..ced4534baed574f7596b014f979748b1eedc2653 100644 (file)
@@ -165,7 +165,7 @@ static const unsigned char * const k7_nops[ASM_NOP_MAX+2] =
 #endif
 
 #ifdef P6_NOP1
-static const unsigned char  __initconst_or_module p6nops[] =
+static const unsigned char p6nops[] =
 {
        P6_NOP1,
        P6_NOP2,
index 6605a81ba3399fb8c1c9044b0e7aa8c2e22ff882..8b6defe7eefc5e6de1538984622f109c4223528d 100644 (file)
@@ -586,6 +586,8 @@ extern struct event_constraint intel_westmere_pebs_event_constraints[];
 
 extern struct event_constraint intel_snb_pebs_event_constraints[];
 
+extern struct event_constraint intel_ivb_pebs_event_constraints[];
+
 struct event_constraint *intel_pebs_constraints(struct perf_event *event);
 
 void intel_pmu_pebs_enable(struct perf_event *event);
index 7bfb5bec8630ada6580dd446e8a62de847d12288..eebd5ffe1bba0b922f9ef8481fd141f2ba9668da 100644 (file)
@@ -209,6 +209,15 @@ static int perf_ibs_precise_event(struct perf_event *event, u64 *config)
        return -EOPNOTSUPP;
 }
 
+static const struct perf_event_attr ibs_notsupp = {
+       .exclude_user   = 1,
+       .exclude_kernel = 1,
+       .exclude_hv     = 1,
+       .exclude_idle   = 1,
+       .exclude_host   = 1,
+       .exclude_guest  = 1,
+};
+
 static int perf_ibs_init(struct perf_event *event)
 {
        struct hw_perf_event *hwc = &event->hw;
@@ -229,6 +238,9 @@ static int perf_ibs_init(struct perf_event *event)
        if (event->pmu != &perf_ibs->pmu)
                return -ENOENT;
 
+       if (perf_flags(&event->attr) & perf_flags(&ibs_notsupp))
+               return -EINVAL;
+
        if (config & ~perf_ibs->config_mask)
                return -EINVAL;
 
index 7f2739e03e79a80fc1baaf203cf3a22eccec54dc..6bca492b85475bc8eab5577447ce1fa9a5133223 100644 (file)
@@ -2008,6 +2008,7 @@ __init int intel_pmu_init(void)
                break;
 
        case 28: /* Atom */
+       case 54: /* Cedariew */
                memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
 
@@ -2047,7 +2048,6 @@ __init int intel_pmu_init(void)
        case 42: /* SandyBridge */
        case 45: /* SandyBridge, "Romely-EP" */
                x86_add_quirk(intel_sandybridge_quirk);
-       case 58: /* IvyBridge */
                memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
                       sizeof(hw_cache_event_ids));
                memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
@@ -2072,6 +2072,29 @@ __init int intel_pmu_init(void)
 
                pr_cont("SandyBridge events, ");
                break;
+       case 58: /* IvyBridge */
+               memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
+                      sizeof(hw_cache_event_ids));
+               memcpy(hw_cache_extra_regs, snb_hw_cache_extra_regs,
+                      sizeof(hw_cache_extra_regs));
+
+               intel_pmu_lbr_init_snb();
+
+               x86_pmu.event_constraints = intel_snb_event_constraints;
+               x86_pmu.pebs_constraints = intel_ivb_pebs_event_constraints;
+               x86_pmu.pebs_aliases = intel_pebs_aliases_snb;
+               x86_pmu.extra_regs = intel_snb_extra_regs;
+               /* all extra regs are per-cpu when HT is on */
+               x86_pmu.er_flags |= ERF_HAS_RSP_1;
+               x86_pmu.er_flags |= ERF_NO_HT_SHARING;
+
+               /* UOPS_ISSUED.ANY,c=1,i=1 to count stall cycles */
+               intel_perfmon_event_map[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =
+                       X86_CONFIG(.event=0x0e, .umask=0x01, .inv=1, .cmask=1);
+
+               pr_cont("IvyBridge events, ");
+               break;
+
 
        default:
                switch (x86_pmu.version) {
index e38d97bf4259fc579f2b070fef85980ae7aaab7a..826054a4f2ee4c54ea4cfb9d29ab117db35e7fc5 100644 (file)
@@ -407,6 +407,20 @@ struct event_constraint intel_snb_pebs_event_constraints[] = {
        EVENT_CONSTRAINT_END
 };
 
+struct event_constraint intel_ivb_pebs_event_constraints[] = {
+        INTEL_UEVENT_CONSTRAINT(0x01c0, 0x2), /* INST_RETIRED.PRECDIST */
+        INTEL_UEVENT_CONSTRAINT(0x01c2, 0xf), /* UOPS_RETIRED.ALL */
+        INTEL_UEVENT_CONSTRAINT(0x02c2, 0xf), /* UOPS_RETIRED.RETIRE_SLOTS */
+        INTEL_EVENT_CONSTRAINT(0xc4, 0xf),    /* BR_INST_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xc5, 0xf),    /* BR_MISP_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xcd, 0x8),    /* MEM_TRANS_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xd0, 0xf),    /* MEM_UOP_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xd1, 0xf),    /* MEM_LOAD_UOPS_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xd2, 0xf),    /* MEM_LOAD_UOPS_LLC_HIT_RETIRED.* */
+        INTEL_EVENT_CONSTRAINT(0xd3, 0xf),    /* MEM_LOAD_UOPS_LLC_MISS_RETIRED.* */
+        EVENT_CONSTRAINT_END
+};
+
 struct event_constraint *intel_pebs_constraints(struct perf_event *event)
 {
        struct event_constraint *c;
index 520b4265fcd215ee5afe240fe11c944dd6bc06aa..da02e9cc3754b4a2c1a37c1edb44865143f7f723 100644 (file)
@@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void)
         * to have an operational LBR which can freeze
         * on PMU interrupt
         */
-       if (boot_cpu_data.x86_mask < 10) {
+       if (boot_cpu_data.x86_model == 28
+           && boot_cpu_data.x86_mask < 10) {
                pr_cont("LBR disabled due to erratum");
                return;
        }
index 0a5571080e7453bc9d602061ffbe2c6ad81647a2..38e4894165b9cdc096e038de65fc4ee04bdb0690 100644 (file)
@@ -661,6 +661,11 @@ static void snb_uncore_msr_init_box(struct intel_uncore_box *box)
        }
 }
 
+static struct uncore_event_desc snb_uncore_events[] = {
+       INTEL_UNCORE_EVENT_DESC(clockticks, "event=0xff,umask=0x00"),
+       { /* end: all zeroes */ },
+};
+
 static struct attribute *snb_uncore_formats_attr[] = {
        &format_attr_event.attr,
        &format_attr_umask.attr,
@@ -704,6 +709,7 @@ static struct intel_uncore_type snb_uncore_cbox = {
        .constraints    = snb_uncore_cbox_constraints,
        .ops            = &snb_uncore_msr_ops,
        .format_group   = &snb_uncore_format_group,
+       .event_descs    = snb_uncore_events,
 };
 
 static struct intel_uncore_type *snb_msr_uncores[] = {
index 7ad683d78645c1b8eed3a816e6fca23de94541f3..d44f7829968e801cf6b32d41be0c5f297971900d 100644 (file)
@@ -270,7 +270,7 @@ void fixup_irqs(void)
 
                if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
                        break_affinity = 1;
-                       affinity = cpu_all_mask;
+                       affinity = cpu_online_mask;
                }
 
                chip = irq_data_get_irq_chip(data);
index 8a2ce8fd41c0e68bbedc6fce685fb52c95502d24..82746f942cd8db4d59a32631049a79146564052e 100644 (file)
@@ -143,11 +143,12 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr,
                                  unsigned int *current_size)
 {
        struct microcode_header_amd *mc_hdr;
-       unsigned int actual_size;
+       unsigned int actual_size, patch_size;
        u16 equiv_cpu_id;
 
        /* size of the current patch we're staring at */
-       *current_size = *(u32 *)(ucode_ptr + 4) + SECTION_HDR_SIZE;
+       patch_size = *(u32 *)(ucode_ptr + 4);
+       *current_size = patch_size + SECTION_HDR_SIZE;
 
        equiv_cpu_id = find_equiv_id();
        if (!equiv_cpu_id)
@@ -174,7 +175,7 @@ static int get_matching_microcode(int cpu, const u8 *ucode_ptr,
        /*
         * now that the header looks sane, verify its size
         */
-       actual_size = verify_ucode_size(cpu, *current_size, leftover_size);
+       actual_size = verify_ucode_size(cpu, patch_size, leftover_size);
        if (!actual_size)
                return 0;
 
index 4873e62db6a18468b23736c5f4adfd2de8b3b85b..9e5bcf1e2376e9713adc8841df162293c859c97c 100644 (file)
@@ -225,6 +225,9 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
        if (do_microcode_update(buf, len) == 0)
                ret = (ssize_t)len;
 
+       if (ret > 0)
+               perf_check_microcode();
+
        mutex_unlock(&microcode_mutex);
        put_online_cpus();
 
index 97d9a9914ba8d772e522911252261110cfa58677..a3b57a27be880649ac7b0ae4144bc62faf105cbc 100644 (file)
@@ -475,13 +475,26 @@ register_address(struct x86_emulate_ctxt *ctxt, unsigned long reg)
        return address_mask(ctxt, reg);
 }
 
+static void masked_increment(ulong *reg, ulong mask, int inc)
+{
+       assign_masked(reg, *reg + inc, mask);
+}
+
 static inline void
 register_address_increment(struct x86_emulate_ctxt *ctxt, unsigned long *reg, int inc)
 {
+       ulong mask;
+
        if (ctxt->ad_bytes == sizeof(unsigned long))
-               *reg += inc;
+               mask = ~0UL;
        else
-               *reg = (*reg & ~ad_mask(ctxt)) | ((*reg + inc) & ad_mask(ctxt));
+               mask = ad_mask(ctxt);
+       masked_increment(reg, mask, inc);
+}
+
+static void rsp_increment(struct x86_emulate_ctxt *ctxt, int inc)
+{
+       masked_increment(&ctxt->regs[VCPU_REGS_RSP], stack_mask(ctxt), inc);
 }
 
 static inline void jmp_rel(struct x86_emulate_ctxt *ctxt, int rel)
@@ -1522,8 +1535,8 @@ static int push(struct x86_emulate_ctxt *ctxt, void *data, int bytes)
 {
        struct segmented_address addr;
 
-       register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], -bytes);
-       addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
+       rsp_increment(ctxt, -bytes);
+       addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
        addr.seg = VCPU_SREG_SS;
 
        return segmented_write(ctxt, addr, data, bytes);
@@ -1542,13 +1555,13 @@ static int emulate_pop(struct x86_emulate_ctxt *ctxt,
        int rc;
        struct segmented_address addr;
 
-       addr.ea = register_address(ctxt, ctxt->regs[VCPU_REGS_RSP]);
+       addr.ea = ctxt->regs[VCPU_REGS_RSP] & stack_mask(ctxt);
        addr.seg = VCPU_SREG_SS;
        rc = segmented_read(ctxt, addr, dest, len);
        if (rc != X86EMUL_CONTINUE)
                return rc;
 
-       register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], len);
+       rsp_increment(ctxt, len);
        return rc;
 }
 
@@ -1688,8 +1701,7 @@ static int em_popa(struct x86_emulate_ctxt *ctxt)
 
        while (reg >= VCPU_REGS_RAX) {
                if (reg == VCPU_REGS_RSP) {
-                       register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP],
-                                                       ctxt->op_bytes);
+                       rsp_increment(ctxt, ctxt->op_bytes);
                        --reg;
                }
 
@@ -2825,7 +2837,7 @@ static int em_ret_near_imm(struct x86_emulate_ctxt *ctxt)
        rc = emulate_pop(ctxt, &ctxt->dst.val, ctxt->op_bytes);
        if (rc != X86EMUL_CONTINUE)
                return rc;
-       register_address_increment(ctxt, &ctxt->regs[VCPU_REGS_RSP], ctxt->src.val);
+       rsp_increment(ctxt, ctxt->src.val);
        return X86EMUL_CONTINUE;
 }
 
index e498b18f010c7b97480ccf1f1018c87a5f07daa1..9fc9aa7ac7034c64dc8cdb59f27f5ac80e1d77ab 100644 (file)
@@ -318,7 +318,7 @@ static void pic_ioport_write(void *opaque, u32 addr, u32 val)
                if (val & 0x10) {
                        u8 edge_irr = s->irr & ~s->elcr;
                        int i;
-                       bool found;
+                       bool found = false;
                        struct kvm_vcpu *vcpu;
 
                        s->init4 = val & 1;
index 01ca00423938515cfe43781403e90bfb84929fc3..7fbd0d273ea83dbec4a330fcb6d14a8ab46462b0 100644 (file)
@@ -4112,17 +4112,22 @@ static int mmu_shrink(struct shrinker *shrink, struct shrink_control *sc)
                int idx;
                LIST_HEAD(invalid_list);
 
+               /*
+                * Never scan more than sc->nr_to_scan VM instances.
+                * Will not hit this condition practically since we do not try
+                * to shrink more than one VM and it is very unlikely to see
+                * !n_used_mmu_pages so many times.
+                */
+               if (!nr_to_scan--)
+                       break;
                /*
                 * n_used_mmu_pages is accessed without holding kvm->mmu_lock
                 * here. We may skip a VM instance errorneosly, but we do not
                 * want to shrink a VM that only started to populate its MMU
                 * anyway.
                 */
-               if (kvm->arch.n_used_mmu_pages > 0) {
-                       if (!nr_to_scan--)
-                               break;
+               if (!kvm->arch.n_used_mmu_pages)
                        continue;
-               }
 
                idx = srcu_read_lock(&kvm->srcu);
                spin_lock(&kvm->mmu_lock);
index c00f03de1b794af8fe65387747813d57ed2885a2..b1eb202ee76a9265d920ca1b02d57aa1ff803d9a 100644 (file)
@@ -3619,6 +3619,7 @@ static void seg_setup(int seg)
 
 static int alloc_apic_access_page(struct kvm *kvm)
 {
+       struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
@@ -3633,7 +3634,13 @@ static int alloc_apic_access_page(struct kvm *kvm)
        if (r)
                goto out;
 
-       kvm->arch.apic_access_page = gfn_to_page(kvm, 0xfee00);
+       page = gfn_to_page(kvm, 0xfee00);
+       if (is_error_page(page)) {
+               r = -EFAULT;
+               goto out;
+       }
+
+       kvm->arch.apic_access_page = page;
 out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@ -3641,6 +3648,7 @@ out:
 
 static int alloc_identity_pagetable(struct kvm *kvm)
 {
+       struct page *page;
        struct kvm_userspace_memory_region kvm_userspace_mem;
        int r = 0;
 
@@ -3656,8 +3664,13 @@ static int alloc_identity_pagetable(struct kvm *kvm)
        if (r)
                goto out;
 
-       kvm->arch.ept_identity_pagetable = gfn_to_page(kvm,
-                       kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
+       page = gfn_to_page(kvm, kvm->arch.ept_identity_map_addr >> PAGE_SHIFT);
+       if (is_error_page(page)) {
+               r = -EFAULT;
+               goto out;
+       }
+
+       kvm->arch.ept_identity_pagetable = page;
 out:
        mutex_unlock(&kvm->slots_lock);
        return r;
@@ -6575,7 +6588,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
        /* Exposing INVPCID only when PCID is exposed */
        best = kvm_find_cpuid_entry(vcpu, 0x7, 0);
        if (vmx_invpcid_supported() &&
-           best && (best->ecx & bit(X86_FEATURE_INVPCID)) &&
+           best && (best->ebx & bit(X86_FEATURE_INVPCID)) &&
            guest_cpuid_has_pcid(vcpu)) {
                exec_control |= SECONDARY_EXEC_ENABLE_INVPCID;
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
@@ -6585,7 +6598,7 @@ static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
                vmcs_write32(SECONDARY_VM_EXEC_CONTROL,
                             exec_control);
                if (best)
-                       best->ecx &= ~bit(X86_FEATURE_INVPCID);
+                       best->ebx &= ~bit(X86_FEATURE_INVPCID);
        }
 }
 
index 42bce48f692850cf3cadf96e83c86e5f8bf760ee..2966c847d489d84f1f2b3cb8450daf4bcce1d568 100644 (file)
@@ -806,7 +806,7 @@ EXPORT_SYMBOL_GPL(kvm_rdpmc);
  * kvm-specific. Those are put in the beginning of the list.
  */
 
-#define KVM_SAVE_MSRS_BEGIN    9
+#define KVM_SAVE_MSRS_BEGIN    10
 static u32 msrs_to_save[] = {
        MSR_KVM_SYSTEM_TIME, MSR_KVM_WALL_CLOCK,
        MSR_KVM_SYSTEM_TIME_NEW, MSR_KVM_WALL_CLOCK_NEW,
@@ -2000,6 +2000,9 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, u32 msr, u64 *pdata)
        case MSR_KVM_STEAL_TIME:
                data = vcpu->arch.st.msr_val;
                break;
+       case MSR_KVM_PV_EOI_EN:
+               data = vcpu->arch.pv_eoi.msr_val;
+               break;
        case MSR_IA32_P5_MC_ADDR:
        case MSR_IA32_P5_MC_TYPE:
        case MSR_IA32_MCG_CAP:
@@ -5110,17 +5113,20 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
                        !kvm_event_needs_reinjection(vcpu);
 }
 
-static void vapic_enter(struct kvm_vcpu *vcpu)
+static int vapic_enter(struct kvm_vcpu *vcpu)
 {
        struct kvm_lapic *apic = vcpu->arch.apic;
        struct page *page;
 
        if (!apic || !apic->vapic_addr)
-               return;
+               return 0;
 
        page = gfn_to_page(vcpu->kvm, apic->vapic_addr >> PAGE_SHIFT);
+       if (is_error_page(page))
+               return -EFAULT;
 
        vcpu->arch.apic->vapic_page = page;
+       return 0;
 }
 
 static void vapic_exit(struct kvm_vcpu *vcpu)
@@ -5427,7 +5433,11 @@ static int __vcpu_run(struct kvm_vcpu *vcpu)
        }
 
        vcpu->srcu_idx = srcu_read_lock(&kvm->srcu);
-       vapic_enter(vcpu);
+       r = vapic_enter(vcpu);
+       if (r) {
+               srcu_read_unlock(&kvm->srcu, vcpu->srcu_idx);
+               return r;
+       }
 
        r = 1;
        while (r > 0) {
index e0e6990723e982e12f425f2fdd26113725f2d52a..ab1f6a93b527c9bd50acc12a52e9ce157f2cc48b 100644 (file)
@@ -319,7 +319,7 @@ unsigned long __init_refok init_memory_mapping(unsigned long start,
  */
 int devmem_is_allowed(unsigned long pagenr)
 {
-       if (pagenr <= 256)
+       if (pagenr < 256)
                return 1;
        if (iomem_is_exclusive(pagenr << PAGE_SHIFT))
                return 0;
index 9926e11a772dbe9b5417fa204407c2ec9ee58878..aeaff8bef2f162642ef4ad31603a301384f4b1fe 100644 (file)
@@ -21,6 +21,7 @@ config 64BIT
 config X86_32
        def_bool !64BIT
        select HAVE_AOUT
+       select ARCH_WANT_IPC_PARSE_VERSION
 
 config X86_64
        def_bool 64BIT
index 5868526b5eefa3017b784ad1a48c45b6be7ceacf..46a9df99f3c5c952601d7f153adf6bf8c1e3e937 100644 (file)
@@ -7,9 +7,6 @@
 #define DEFINE(sym, val) \
        asm volatile("\n->" #sym " %0 " #val : : "i" (val))
 
-#define STR(x) #x
-#define DEFINE_STR(sym, val) asm volatile("\n->" #sym " " STR(val) " " #val: : )
-
 #define BLANK() asm volatile("\n->" : : )
 
 #define OFFSET(sym, str, mem) \
index bd9a89b67e41f20bdd17b2f38f5c9543ef28c7b1..ca255a805ed936ea059312b0990e884bb2b07e1b 100644 (file)
@@ -1,3 +1,5 @@
+extern long sys_clone(unsigned long clone_flags, unsigned long newsp,
+              void __user *parent_tid, void __user *child_tid);
 #ifdef __i386__
 #include "syscalls_32.h"
 #else
index a508cea135033eba3c1c7facba8aebd04a1a0983..ba7363ecf896598c21534af5d09ef1c32e275668 100644 (file)
@@ -416,9 +416,6 @@ int setup_signal_stack_sc(unsigned long stack_top, int sig,
        PT_REGS_AX(regs) = (unsigned long) sig;
        PT_REGS_DX(regs) = (unsigned long) 0;
        PT_REGS_CX(regs) = (unsigned long) 0;
-
-       if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-               ptrace_notify(SIGTRAP);
        return 0;
 }
 
@@ -466,9 +463,6 @@ int setup_signal_stack_si(unsigned long stack_top, int sig,
        PT_REGS_AX(regs) = (unsigned long) sig;
        PT_REGS_DX(regs) = (unsigned long) &frame->info;
        PT_REGS_CX(regs) = (unsigned long) &frame->uc;
-
-       if ((current->ptrace & PT_DTRACE) && (current->ptrace & PT_PTRACED))
-               ptrace_notify(SIGTRAP);
        return 0;
 }
 
index 68d1dc91b37badeaeff9fe517a06df2be6484f8a..b5408cecac6cd68f5f649b0a45749c1fdab40d77 100644 (file)
@@ -28,7 +28,7 @@
 #define ptregs_execve sys_execve
 #define ptregs_iopl sys_iopl
 #define ptregs_vm86old sys_vm86old
-#define ptregs_clone sys_clone
+#define ptregs_clone i386_clone
 #define ptregs_vm86 sys_vm86
 #define ptregs_sigaltstack sys_sigaltstack
 #define ptregs_vfork sys_vfork
index b853e8600b9dc1d00e74151a7e16b8af61a8bfda..db444c7218fe53bcabf105b5e2303b7d21a5fd15 100644 (file)
@@ -3,37 +3,24 @@
  * Licensed under the GPL
  */
 
-#include "linux/sched.h"
-#include "linux/shm.h"
-#include "linux/ipc.h"
-#include "linux/syscalls.h"
-#include "asm/mman.h"
-#include "asm/uaccess.h"
-#include "asm/unistd.h"
+#include <linux/syscalls.h>
+#include <sysdep/syscalls.h>
 
 /*
  * The prototype on i386 is:
  *
- *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls, int * child_tidptr)
+ *     int clone(int flags, void * child_stack, int * parent_tidptr, struct user_desc * newtls
  *
  * and the "newtls" arg. on i386 is read by copy_thread directly from the
  * register saved on the stack.
  */
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-              int __user *parent_tid, void *newtls, int __user *child_tid)
+long i386_clone(unsigned long clone_flags, unsigned long newsp,
+               int __user *parent_tid, void *newtls, int __user *child_tid)
 {
-       long ret;
-
-       if (!newsp)
-               newsp = UPT_SP(&current->thread.regs.regs);
-
-       current->thread.forking = 1;
-       ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-                     child_tid);
-       current->thread.forking = 0;
-       return ret;
+       return sys_clone(clone_flags, newsp, parent_tid, child_tid);
 }
 
+
 long sys_sigaction(int sig, const struct old_sigaction __user *act,
                         struct old_sigaction __user *oact)
 {
index f3d82bb6e15a410b5e706617526efe9d56a42243..adb08eb5c22a38710299d3e1a05b3b55e2ee7e63 100644 (file)
@@ -5,12 +5,9 @@
  * Licensed under the GPL
  */
 
-#include "linux/linkage.h"
-#include "linux/personality.h"
-#include "linux/utsname.h"
-#include "asm/prctl.h" /* XXX This should get the constants from libc */
-#include "asm/uaccess.h"
-#include "os.h"
+#include <linux/sched.h>
+#include <asm/prctl.h> /* XXX This should get the constants from libc */
+#include <os.h>
 
 long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr)
 {
@@ -79,20 +76,6 @@ long sys_arch_prctl(int code, unsigned long addr)
        return arch_prctl(current, code, (unsigned long __user *) addr);
 }
 
-long sys_clone(unsigned long clone_flags, unsigned long newsp,
-              void __user *parent_tid, void __user *child_tid)
-{
-       long ret;
-
-       if (!newsp)
-               newsp = UPT_SP(&current->thread.regs.regs);
-       current->thread.forking = 1;
-       ret = do_fork(clone_flags, newsp, &current->thread.regs, 0, parent_tid,
-                     child_tid);
-       current->thread.forking = 0;
-       return ret;
-}
-
 void arch_switch_to(struct task_struct *to)
 {
        if ((to->thread.arch.fs == 0) || (to->mm == NULL))
index bf4bda6d3e9ad66f19af6e4669063a12739c78db..1fbe75a95f15953d3d0ed6cd0dd7c911a88eac0b 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/pci.h>
 #include <linux/gfp.h>
 #include <linux/memblock.h>
-#include <linux/syscore_ops.h>
 
 #include <xen/xen.h>
 #include <xen/interface/xen.h>
@@ -1453,6 +1452,10 @@ asmlinkage void __init xen_start_kernel(void)
                pci_request_acs();
 
                xen_acpi_sleep_register();
+
+               /* Avoid searching for BIOS MP tables */
+               x86_init.mpparse.find_smp_config = x86_init_noop;
+               x86_init.mpparse.get_smp_config = x86_init_uint_noop;
        }
 #ifdef CONFIG_PCI
        /* PCI BIOS service won't work from a PV guest. */
@@ -1470,130 +1473,38 @@ asmlinkage void __init xen_start_kernel(void)
 #endif
 }
 
-#ifdef CONFIG_XEN_PVHVM
-/*
- * The pfn containing the shared_info is located somewhere in RAM. This
- * will cause trouble if the current kernel is doing a kexec boot into a
- * new kernel. The new kernel (and its startup code) can not know where
- * the pfn is, so it can not reserve the page. The hypervisor will
- * continue to update the pfn, and as a result memory corruption occours
- * in the new kernel.
- *
- * One way to work around this issue is to allocate a page in the
- * xen-platform pci device's BAR memory range. But pci init is done very
- * late and the shared_info page is already in use very early to read
- * the pvclock. So moving the pfn from RAM to MMIO is racy because some
- * code paths on other vcpus could access the pfn during the small
- * window when the old pfn is moved to the new pfn. There is even a
- * small window were the old pfn is not backed by a mfn, and during that
- * time all reads return -1.
- *
- * Because it is not known upfront where the MMIO region is located it
- * can not be used right from the start in xen_hvm_init_shared_info.
- *
- * To minimise trouble the move of the pfn is done shortly before kexec.
- * This does not eliminate the race because all vcpus are still online
- * when the syscore_ops will be called. But hopefully there is no work
- * pending at this point in time. Also the syscore_op is run last which
- * reduces the risk further.
- */
-
-static struct shared_info *xen_hvm_shared_info;
-
-static void xen_hvm_connect_shared_info(unsigned long pfn)
+void __ref xen_hvm_init_shared_info(void)
 {
+       int cpu;
        struct xen_add_to_physmap xatp;
+       static struct shared_info *shared_info_page = 0;
 
+       if (!shared_info_page)
+               shared_info_page = (struct shared_info *)
+                       extend_brk(PAGE_SIZE, PAGE_SIZE);
        xatp.domid = DOMID_SELF;
        xatp.idx = 0;
        xatp.space = XENMAPSPACE_shared_info;
-       xatp.gpfn = pfn;
+       xatp.gpfn = __pa(shared_info_page) >> PAGE_SHIFT;
        if (HYPERVISOR_memory_op(XENMEM_add_to_physmap, &xatp))
                BUG();
 
-}
-static void xen_hvm_set_shared_info(struct shared_info *sip)
-{
-       int cpu;
-
-       HYPERVISOR_shared_info = sip;
+       HYPERVISOR_shared_info = (struct shared_info *)shared_info_page;
 
        /* xen_vcpu is a pointer to the vcpu_info struct in the shared_info
         * page, we use it in the event channel upcall and in some pvclock
         * related functions. We don't need the vcpu_info placement
         * optimizations because we don't use any pv_mmu or pv_irq op on
         * HVM.
-        * When xen_hvm_set_shared_info is run at boot time only vcpu 0 is
-        * online but xen_hvm_set_shared_info is run at resume time too and
+        * When xen_hvm_init_shared_info is run at boot time only vcpu 0 is
+        * online but xen_hvm_init_shared_info is run at resume time too and
         * in that case multiple vcpus might be online. */
        for_each_online_cpu(cpu) {
                per_cpu(xen_vcpu, cpu) = &HYPERVISOR_shared_info->vcpu_info[cpu];
        }
 }
 
-/* Reconnect the shared_info pfn to a mfn */
-void xen_hvm_resume_shared_info(void)
-{
-       xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT);
-}
-
-#ifdef CONFIG_KEXEC
-static struct shared_info *xen_hvm_shared_info_kexec;
-static unsigned long xen_hvm_shared_info_pfn_kexec;
-
-/* Remember a pfn in MMIO space for kexec reboot */
-void __devinit xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn)
-{
-       xen_hvm_shared_info_kexec = sip;
-       xen_hvm_shared_info_pfn_kexec = pfn;
-}
-
-static void xen_hvm_syscore_shutdown(void)
-{
-       struct xen_memory_reservation reservation = {
-               .domid = DOMID_SELF,
-               .nr_extents = 1,
-       };
-       unsigned long prev_pfn;
-       int rc;
-
-       if (!xen_hvm_shared_info_kexec)
-               return;
-
-       prev_pfn = __pa(xen_hvm_shared_info) >> PAGE_SHIFT;
-       set_xen_guest_handle(reservation.extent_start, &prev_pfn);
-
-       /* Move pfn to MMIO, disconnects previous pfn from mfn */
-       xen_hvm_connect_shared_info(xen_hvm_shared_info_pfn_kexec);
-
-       /* Update pointers, following hypercall is also a memory barrier */
-       xen_hvm_set_shared_info(xen_hvm_shared_info_kexec);
-
-       /* Allocate new mfn for previous pfn */
-       do {
-               rc = HYPERVISOR_memory_op(XENMEM_populate_physmap, &reservation);
-               if (rc == 0)
-                       msleep(123);
-       } while (rc == 0);
-
-       /* Make sure the previous pfn is really connected to a (new) mfn */
-       BUG_ON(rc != 1);
-}
-
-static struct syscore_ops xen_hvm_syscore_ops = {
-       .shutdown = xen_hvm_syscore_shutdown,
-};
-#endif
-
-/* Use a pfn in RAM, may move to MMIO before kexec. */
-static void __init xen_hvm_init_shared_info(void)
-{
-       /* Remember pointer for resume */
-       xen_hvm_shared_info = extend_brk(PAGE_SIZE, PAGE_SIZE);
-       xen_hvm_connect_shared_info(__pa(xen_hvm_shared_info) >> PAGE_SHIFT);
-       xen_hvm_set_shared_info(xen_hvm_shared_info);
-}
-
+#ifdef CONFIG_XEN_PVHVM
 static void __init init_hvm_pv_info(void)
 {
        int major, minor;
@@ -1644,9 +1555,6 @@ static void __init xen_hvm_guest_init(void)
        init_hvm_pv_info();
 
        xen_hvm_init_shared_info();
-#ifdef CONFIG_KEXEC
-       register_syscore_ops(&xen_hvm_syscore_ops);
-#endif
 
        if (xen_feature(XENFEAT_hvm_callback_vector))
                xen_have_vector_callback = 1;
index b65a76133f4f9b4f51dc426021975d7a5427191e..5141d808e7519d8f38ca8c001e4e5c6c7b318956 100644 (file)
@@ -1283,7 +1283,7 @@ static void xen_flush_tlb_others(const struct cpumask *cpus,
        cpumask_clear_cpu(smp_processor_id(), to_cpumask(args->mask));
 
        args->op.cmd = MMUEXT_TLB_FLUSH_MULTI;
-       if (start != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
+       if (end != TLB_FLUSH_ALL && (end - start) <= PAGE_SIZE) {
                args->op.cmd = MMUEXT_INVLPG_MULTI;
                args->op.arg1.linear_addr = start;
        }
index b2e91d40a4cb32a851006d6194d70f3465ec26f3..72213da605f50c07f3684ca07d351a8bbd7435ef 100644 (file)
@@ -196,9 +196,11 @@ RESERVE_BRK(p2m_mid_identity, PAGE_SIZE * 2 * 3);
 
 /* When we populate back during bootup, the amount of pages can vary. The
  * max we have is seen is 395979, but that does not mean it can't be more.
- * But some machines can have 3GB I/O holes even. So lets reserve enough
- * for 4GB of I/O and E820 holes. */
-RESERVE_BRK(p2m_populated, PMD_SIZE * 4);
+ * Some machines can have 3GB I/O holes even. With early_can_reuse_p2m_middle
+ * it can re-use Xen provided mfn_list array, so we only need to allocate at
+ * most three P2M top nodes. */
+RESERVE_BRK(p2m_populated, PAGE_SIZE * 3);
+
 static inline unsigned p2m_top_index(unsigned long pfn)
 {
        BUG_ON(pfn >= MAX_P2M_PFN);
@@ -575,12 +577,99 @@ static bool __init early_alloc_p2m(unsigned long pfn)
        }
        return true;
 }
+
+/*
+ * Skim over the P2M tree looking at pages that are either filled with
+ * INVALID_P2M_ENTRY or with 1:1 PFNs. If found, re-use that page and
+ * replace the P2M leaf with a p2m_missing or p2m_identity.
+ * Stick the old page in the new P2M tree location.
+ */
+bool __init early_can_reuse_p2m_middle(unsigned long set_pfn, unsigned long set_mfn)
+{
+       unsigned topidx;
+       unsigned mididx;
+       unsigned ident_pfns;
+       unsigned inv_pfns;
+       unsigned long *p2m;
+       unsigned long *mid_mfn_p;
+       unsigned idx;
+       unsigned long pfn;
+
+       /* We only look when this entails a P2M middle layer */
+       if (p2m_index(set_pfn))
+               return false;
+
+       for (pfn = 0; pfn < MAX_DOMAIN_PAGES; pfn += P2M_PER_PAGE) {
+               topidx = p2m_top_index(pfn);
+
+               if (!p2m_top[topidx])
+                       continue;
+
+               if (p2m_top[topidx] == p2m_mid_missing)
+                       continue;
+
+               mididx = p2m_mid_index(pfn);
+               p2m = p2m_top[topidx][mididx];
+               if (!p2m)
+                       continue;
+
+               if ((p2m == p2m_missing) || (p2m == p2m_identity))
+                       continue;
+
+               if ((unsigned long)p2m == INVALID_P2M_ENTRY)
+                       continue;
+
+               ident_pfns = 0;
+               inv_pfns = 0;
+               for (idx = 0; idx < P2M_PER_PAGE; idx++) {
+                       /* IDENTITY_PFNs are 1:1 */
+                       if (p2m[idx] == IDENTITY_FRAME(pfn + idx))
+                               ident_pfns++;
+                       else if (p2m[idx] == INVALID_P2M_ENTRY)
+                               inv_pfns++;
+                       else
+                               break;
+               }
+               if ((ident_pfns == P2M_PER_PAGE) || (inv_pfns == P2M_PER_PAGE))
+                       goto found;
+       }
+       return false;
+found:
+       /* Found one, replace old with p2m_identity or p2m_missing */
+       p2m_top[topidx][mididx] = (ident_pfns ? p2m_identity : p2m_missing);
+       /* And the other for save/restore.. */
+       mid_mfn_p = p2m_top_mfn_p[topidx];
+       /* NOTE: Even if it is a p2m_identity it should still be point to
+        * a page filled with INVALID_P2M_ENTRY entries. */
+       mid_mfn_p[mididx] = virt_to_mfn(p2m_missing);
+
+       /* Reset where we want to stick the old page in. */
+       topidx = p2m_top_index(set_pfn);
+       mididx = p2m_mid_index(set_pfn);
+
+       /* This shouldn't happen */
+       if (WARN_ON(p2m_top[topidx] == p2m_mid_missing))
+               early_alloc_p2m(set_pfn);
+
+       if (WARN_ON(p2m_top[topidx][mididx] != p2m_missing))
+               return false;
+
+       p2m_init(p2m);
+       p2m_top[topidx][mididx] = p2m;
+       mid_mfn_p = p2m_top_mfn_p[topidx];
+       mid_mfn_p[mididx] = virt_to_mfn(p2m);
+
+       return true;
+}
 bool __init early_set_phys_to_machine(unsigned long pfn, unsigned long mfn)
 {
        if (unlikely(!__set_phys_to_machine(pfn, mfn)))  {
                if (!early_alloc_p2m(pfn))
                        return false;
 
+               if (early_can_reuse_p2m_middle(pfn, mfn))
+                       return __set_phys_to_machine(pfn, mfn);
+
                if (!early_alloc_p2m_middle(pfn, false /* boundary crossover OK!*/))
                        return false;
 
@@ -739,9 +828,6 @@ int m2p_add_override(unsigned long mfn, struct page *page,
 
                        xen_mc_issue(PARAVIRT_LAZY_MMU);
                }
-               /* let's use dev_bus_addr to record the old mfn instead */
-               kmap_op->dev_bus_addr = page->index;
-               page->index = (unsigned long) kmap_op;
        }
        spin_lock_irqsave(&m2p_override_lock, flags);
        list_add(&page->lru,  &m2p_overrides[mfn_hash(mfn)]);
@@ -768,7 +854,8 @@ int m2p_add_override(unsigned long mfn, struct page *page,
        return 0;
 }
 EXPORT_SYMBOL_GPL(m2p_add_override);
-int m2p_remove_override(struct page *page, bool clear_pte)
+int m2p_remove_override(struct page *page,
+               struct gnttab_map_grant_ref *kmap_op)
 {
        unsigned long flags;
        unsigned long mfn;
@@ -798,10 +885,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
        WARN_ON(!PagePrivate(page));
        ClearPagePrivate(page);
 
-       if (clear_pte) {
-               struct gnttab_map_grant_ref *map_op =
-                       (struct gnttab_map_grant_ref *) page->index;
-               set_phys_to_machine(pfn, map_op->dev_bus_addr);
+       set_phys_to_machine(pfn, page->index);
+       if (kmap_op != NULL) {
                if (!PageHighMem(page)) {
                        struct multicall_space mcs;
                        struct gnttab_unmap_grant_ref *unmap_op;
@@ -813,13 +898,13 @@ int m2p_remove_override(struct page *page, bool clear_pte)
                         * issued. In this case handle is going to -1 because
                         * it hasn't been modified yet.
                         */
-                       if (map_op->handle == -1)
+                       if (kmap_op->handle == -1)
                                xen_mc_flush();
                        /*
-                        * Now if map_op->handle is negative it means that the
+                        * Now if kmap_op->handle is negative it means that the
                         * hypercall actually returned an error.
                         */
-                       if (map_op->handle == GNTST_general_error) {
+                       if (kmap_op->handle == GNTST_general_error) {
                                printk(KERN_WARNING "m2p_remove_override: "
                                                "pfn %lx mfn %lx, failed to modify kernel mappings",
                                                pfn, mfn);
@@ -829,8 +914,8 @@ int m2p_remove_override(struct page *page, bool clear_pte)
                        mcs = xen_mc_entry(
                                        sizeof(struct gnttab_unmap_grant_ref));
                        unmap_op = mcs.args;
-                       unmap_op->host_addr = map_op->host_addr;
-                       unmap_op->handle = map_op->handle;
+                       unmap_op->host_addr = kmap_op->host_addr;
+                       unmap_op->handle = kmap_op->handle;
                        unmap_op->dev_bus_addr = 0;
 
                        MULTI_grant_table_op(mcs.mc,
@@ -841,10 +926,9 @@ int m2p_remove_override(struct page *page, bool clear_pte)
                        set_pte_at(&init_mm, address, ptep,
                                        pfn_pte(pfn, PAGE_KERNEL));
                        __flush_tlb_single(address);
-                       map_op->host_addr = 0;
+                       kmap_op->host_addr = 0;
                }
-       } else
-               set_phys_to_machine(pfn, page->index);
+       }
 
        /* p2m(m2p(mfn)) == FOREIGN_FRAME(mfn): the mfn is already present
         * somewhere in this domain, even before being added to the
index ead85576d54a6c097f10b9a9d55e2057575e2168..e2d62d697b5dffc60ad6ea53e2ad3f1ce33282a3 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/e820.h>
 #include <asm/setup.h>
 #include <asm/acpi.h>
+#include <asm/numa.h>
 #include <asm/xen/hypervisor.h>
 #include <asm/xen/hypercall.h>
 
@@ -78,9 +79,16 @@ static void __init xen_add_extra_mem(u64 start, u64 size)
        memblock_reserve(start, size);
 
        xen_max_p2m_pfn = PFN_DOWN(start + size);
+       for (pfn = PFN_DOWN(start); pfn < xen_max_p2m_pfn; pfn++) {
+               unsigned long mfn = pfn_to_mfn(pfn);
+
+               if (WARN(mfn == pfn, "Trying to over-write 1-1 mapping (pfn: %lx)\n", pfn))
+                       continue;
+               WARN(mfn != INVALID_P2M_ENTRY, "Trying to remove %lx which has %lx mfn!\n",
+                       pfn, mfn);
 
-       for (pfn = PFN_DOWN(start); pfn <= xen_max_p2m_pfn; pfn++)
                __set_phys_to_machine(pfn, INVALID_P2M_ENTRY);
+       }
 }
 
 static unsigned long __init xen_do_chunk(unsigned long start,
@@ -537,4 +545,7 @@ void __init xen_arch_setup(void)
        disable_cpufreq();
        WARN_ON(set_pm_idle_to_default());
        fiddle_vdso();
+#ifdef CONFIG_NUMA
+       numa_off = 1;
+#endif
 }
index ae8a00c39de4b0d02cfad0722715d0fbd159a1cb..45329c8c226e4c4070f16a791b300265a0bf472b 100644 (file)
@@ -30,7 +30,7 @@ void xen_arch_hvm_post_suspend(int suspend_cancelled)
 {
 #ifdef CONFIG_XEN_PVHVM
        int cpu;
-       xen_hvm_resume_shared_info();
+       xen_hvm_init_shared_info();
        xen_callback_vector();
        xen_unplug_emulated_devices();
        if (xen_feature(XENFEAT_hvm_safe_pvclock)) {
index 1e4329e04e0fbf105467f18b009183c9dcebd2a8..202d4c150154fb31ddb03da8f8144a45f21c02a7 100644 (file)
@@ -41,7 +41,7 @@ void xen_enable_syscall(void);
 void xen_vcpu_restore(void);
 
 void xen_callback_vector(void);
-void xen_hvm_resume_shared_info(void);
+void xen_hvm_init_shared_info(void);
 void xen_unplug_emulated_devices(void);
 
 void __init xen_build_dynamic_phys_to_machine(void);
index 4b4dbdfbca89fe5769fd4b2f6826f305fca18e26..ee3cb3a5e2782292bba4807c0d9cc887de48a31e 100644 (file)
@@ -2254,9 +2254,11 @@ bool blk_update_request(struct request *req, int error, unsigned int nr_bytes)
                        error_type = "I/O";
                        break;
                }
-               printk(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
-                      error_type, req->rq_disk ? req->rq_disk->disk_name : "?",
-                      (unsigned long long)blk_rq_pos(req));
+               printk_ratelimited(KERN_ERR "end_request: %s error, dev %s, sector %llu\n",
+                                  error_type, req->rq_disk ?
+                                  req->rq_disk->disk_name : "?",
+                                  (unsigned long long)blk_rq_pos(req));
+
        }
 
        blk_account_io_completion(req, nr_bytes);
index 2b461b496a788c11d00616efaf16df121e620160..19cc761cacb2a4b71fe9d4579226025324ffddf5 100644 (file)
@@ -44,6 +44,7 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        struct request_queue *q = bdev_get_queue(bdev);
        int type = REQ_WRITE | REQ_DISCARD;
        unsigned int max_discard_sectors;
+       unsigned int granularity, alignment, mask;
        struct bio_batch bb;
        struct bio *bio;
        int ret = 0;
@@ -54,18 +55,20 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        if (!blk_queue_discard(q))
                return -EOPNOTSUPP;
 
+       /* Zero-sector (unknown) and one-sector granularities are the same.  */
+       granularity = max(q->limits.discard_granularity >> 9, 1U);
+       mask = granularity - 1;
+       alignment = (bdev_discard_alignment(bdev) >> 9) & mask;
+
        /*
         * Ensure that max_discard_sectors is of the proper
-        * granularity
+        * granularity, so that requests stay aligned after a split.
         */
        max_discard_sectors = min(q->limits.max_discard_sectors, UINT_MAX >> 9);
+       max_discard_sectors = round_down(max_discard_sectors, granularity);
        if (unlikely(!max_discard_sectors)) {
                /* Avoid infinite loop below. Being cautious never hurts. */
                return -EOPNOTSUPP;
-       } else if (q->limits.discard_granularity) {
-               unsigned int disc_sects = q->limits.discard_granularity >> 9;
-
-               max_discard_sectors &= ~(disc_sects - 1);
        }
 
        if (flags & BLKDEV_DISCARD_SECURE) {
@@ -79,25 +82,37 @@ int blkdev_issue_discard(struct block_device *bdev, sector_t sector,
        bb.wait = &wait;
 
        while (nr_sects) {
+               unsigned int req_sects;
+               sector_t end_sect;
+
                bio = bio_alloc(gfp_mask, 1);
                if (!bio) {
                        ret = -ENOMEM;
                        break;
                }
 
+               req_sects = min_t(sector_t, nr_sects, max_discard_sectors);
+
+               /*
+                * If splitting a request, and the next starting sector would be
+                * misaligned, stop the discard at the previous aligned sector.
+                */
+               end_sect = sector + req_sects;
+               if (req_sects < nr_sects && (end_sect & mask) != alignment) {
+                       end_sect =
+                               round_down(end_sect - alignment, granularity)
+                               + alignment;
+                       req_sects = end_sect - sector;
+               }
+
                bio->bi_sector = sector;
                bio->bi_end_io = bio_batch_end_io;
                bio->bi_bdev = bdev;
                bio->bi_private = &bb;
 
-               if (nr_sects > max_discard_sectors) {
-                       bio->bi_size = max_discard_sectors << 9;
-                       nr_sects -= max_discard_sectors;
-                       sector += max_discard_sectors;
-               } else {
-                       bio->bi_size = nr_sects << 9;
-                       nr_sects = 0;
-               }
+               bio->bi_size = req_sects << 9;
+               nr_sects -= req_sects;
+               sector = end_sect;
 
                atomic_inc(&bb.done);
                submit_bio(type, bio);
index 160035f548823482968bcd58298fcf9c309e7d62..e76279e411622519eebb54d4802eb11b796788db 100644 (file)
@@ -110,6 +110,49 @@ static int blk_phys_contig_segment(struct request_queue *q, struct bio *bio,
        return 0;
 }
 
+static void
+__blk_segment_map_sg(struct request_queue *q, struct bio_vec *bvec,
+                    struct scatterlist *sglist, struct bio_vec **bvprv,
+                    struct scatterlist **sg, int *nsegs, int *cluster)
+{
+
+       int nbytes = bvec->bv_len;
+
+       if (*bvprv && *cluster) {
+               if ((*sg)->length + nbytes > queue_max_segment_size(q))
+                       goto new_segment;
+
+               if (!BIOVEC_PHYS_MERGEABLE(*bvprv, bvec))
+                       goto new_segment;
+               if (!BIOVEC_SEG_BOUNDARY(q, *bvprv, bvec))
+                       goto new_segment;
+
+               (*sg)->length += nbytes;
+       } else {
+new_segment:
+               if (!*sg)
+                       *sg = sglist;
+               else {
+                       /*
+                        * If the driver previously mapped a shorter
+                        * list, we could see a termination bit
+                        * prematurely unless it fully inits the sg
+                        * table on each mapping. We KNOW that there
+                        * must be more entries here or the driver
+                        * would be buggy, so force clear the
+                        * termination bit to avoid doing a full
+                        * sg_init_table() in drivers for each command.
+                        */
+                       (*sg)->page_link &= ~0x02;
+                       *sg = sg_next(*sg);
+               }
+
+               sg_set_page(*sg, bvec->bv_page, nbytes, bvec->bv_offset);
+               (*nsegs)++;
+       }
+       *bvprv = bvec;
+}
+
 /*
  * map a request to scatterlist, return number of sg entries setup. Caller
  * must make sure sg can hold rq->nr_phys_segments entries
@@ -131,41 +174,8 @@ int blk_rq_map_sg(struct request_queue *q, struct request *rq,
        bvprv = NULL;
        sg = NULL;
        rq_for_each_segment(bvec, rq, iter) {
-               int nbytes = bvec->bv_len;
-
-               if (bvprv && cluster) {
-                       if (sg->length + nbytes > queue_max_segment_size(q))
-                               goto new_segment;
-
-                       if (!BIOVEC_PHYS_MERGEABLE(bvprv, bvec))
-                               goto new_segment;
-                       if (!BIOVEC_SEG_BOUNDARY(q, bvprv, bvec))
-                               goto new_segment;
-
-                       sg->length += nbytes;
-               } else {
-new_segment:
-                       if (!sg)
-                               sg = sglist;
-                       else {
-                               /*
-                                * If the driver previously mapped a shorter
-                                * list, we could see a termination bit
-                                * prematurely unless it fully inits the sg
-                                * table on each mapping. We KNOW that there
-                                * must be more entries here or the driver
-                                * would be buggy, so force clear the
-                                * termination bit to avoid doing a full
-                                * sg_init_table() in drivers for each command.
-                                */
-                               sg->page_link &= ~0x02;
-                               sg = sg_next(sg);
-                       }
-
-                       sg_set_page(sg, bvec->bv_page, nbytes, bvec->bv_offset);
-                       nsegs++;
-               }
-               bvprv = bvec;
+               __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+                                    &nsegs, &cluster);
        } /* segments in rq */
 
 
@@ -199,6 +209,43 @@ new_segment:
 }
 EXPORT_SYMBOL(blk_rq_map_sg);
 
+/**
+ * blk_bio_map_sg - map a bio to a scatterlist
+ * @q: request_queue in question
+ * @bio: bio being mapped
+ * @sglist: scatterlist being mapped
+ *
+ * Note:
+ *    Caller must make sure sg can hold bio->bi_phys_segments entries
+ *
+ * Will return the number of sg entries setup
+ */
+int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
+                  struct scatterlist *sglist)
+{
+       struct bio_vec *bvec, *bvprv;
+       struct scatterlist *sg;
+       int nsegs, cluster;
+       unsigned long i;
+
+       nsegs = 0;
+       cluster = blk_queue_cluster(q);
+
+       bvprv = NULL;
+       sg = NULL;
+       bio_for_each_segment(bvec, bio, i) {
+               __blk_segment_map_sg(q, bvec, sglist, &bvprv, &sg,
+                                    &nsegs, &cluster);
+       } /* segments in bio */
+
+       if (sg)
+               sg_mark_end(sg);
+
+       BUG_ON(bio->bi_phys_segments && nsegs > bio->bi_phys_segments);
+       return nsegs;
+}
+EXPORT_SYMBOL(blk_bio_map_sg);
+
 static inline int ll_new_hw_segment(struct request_queue *q,
                                    struct request *req,
                                    struct bio *bio)
index cac7366957c376cedb2341753520e6f32516572c..d839723303c856ae221bdf54ec1de93544698d95 100644 (file)
@@ -835,7 +835,7 @@ static void disk_seqf_stop(struct seq_file *seqf, void *v)
 
 static void *show_partition_start(struct seq_file *seqf, loff_t *pos)
 {
-       static void *p;
+       void *p;
 
        p = disk_seqf_start(seqf, pos);
        if (!IS_ERR_OR_NULL(p) && !*pos)
index 4476e0e85d1687c08b31f81e7f633ae802b14814..4a85096f5410adde92d01cd58ecba30373c808f1 100644 (file)
@@ -41,7 +41,7 @@ static int blkpg_ioctl(struct block_device *bdev, struct blkpg_ioctl_arg __user
                            sizeof(long long) > sizeof(long)) {
                                long pstart = start, plength = length;
                                if (pstart != start || plength != length
-                                   || pstart < 0 || plength < 0)
+                                   || pstart < 0 || plength < 0 || partno > 65535)
                                        return -EINVAL;
                        }
 
index 5ef7ba6b6a76a3251956329ffd9ebcfe85ce66b9..d0583a4489e60ee59a6cc0950d7342594a4d5780 100644 (file)
@@ -336,7 +336,7 @@ static int crypto_authenc_genicv(struct aead_request *req, u8 *iv,
                cryptlen += ivsize;
        }
 
-       if (sg_is_last(assoc)) {
+       if (req->assoclen && sg_is_last(assoc)) {
                authenc_ahash_fn = crypto_authenc_ahash;
                sg_init_table(asg, 2);
                sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
@@ -490,7 +490,7 @@ static int crypto_authenc_iverify(struct aead_request *req, u8 *iv,
                cryptlen += ivsize;
        }
 
-       if (sg_is_last(assoc)) {
+       if (req->assoclen && sg_is_last(assoc)) {
                authenc_ahash_fn = crypto_authenc_ahash;
                sg_init_table(asg, 2);
                sg_set_page(asg, sg_page(assoc), assoc->length, assoc->offset);
index 9628652e080c590fb3f6e01dedc655584c12737b..e0596954290b8e33e20791effc0227b80fb4a0c9 100644 (file)
@@ -237,6 +237,16 @@ static int __acpi_bus_get_power(struct acpi_device *device, int *state)
        } else if (result == ACPI_STATE_D3_HOT) {
                result = ACPI_STATE_D3;
        }
+
+       /*
+        * If we were unsure about the device parent's power state up to this
+        * point, the fact that the device is in D0 implies that the parent has
+        * to be in D0 too.
+        */
+       if (device->parent && device->parent->power.state == ACPI_STATE_UNKNOWN
+           && result == ACPI_STATE_D0)
+               device->parent->power.state = ACPI_STATE_D0;
+
        *state = result;
 
  out:
index fc1803414629d8233b0d6f11819efd166838952e..40e38a06ba854fc04751ec2386ca334d01998eb8 100644 (file)
@@ -107,6 +107,7 @@ struct acpi_power_resource {
 
        /* List of devices relying on this power resource */
        struct acpi_power_resource_device *devices;
+       struct mutex devices_lock;
 };
 
 static struct list_head acpi_power_resource_list;
@@ -225,7 +226,6 @@ static void acpi_power_on_device(struct acpi_power_managed_device *device)
 
 static int __acpi_power_on(struct acpi_power_resource *resource)
 {
-       struct acpi_power_resource_device *device_list = resource->devices;
        acpi_status status = AE_OK;
 
        status = acpi_evaluate_object(resource->device->handle, "_ON", NULL, NULL);
@@ -238,19 +238,15 @@ static int __acpi_power_on(struct acpi_power_resource *resource)
        ACPI_DEBUG_PRINT((ACPI_DB_INFO, "Power resource [%s] turned on\n",
                          resource->name));
 
-       while (device_list) {
-               acpi_power_on_device(device_list->device);
-
-               device_list = device_list->next;
-       }
-
        return 0;
 }
 
 static int acpi_power_on(acpi_handle handle)
 {
        int result = 0;
+       bool resume_device = false;
        struct acpi_power_resource *resource = NULL;
+       struct acpi_power_resource_device *device_list;
 
        result = acpi_power_get_context(handle, &resource);
        if (result)
@@ -266,10 +262,25 @@ static int acpi_power_on(acpi_handle handle)
                result = __acpi_power_on(resource);
                if (result)
                        resource->ref_count--;
+               else
+                       resume_device = true;
        }
 
        mutex_unlock(&resource->resource_lock);
 
+       if (!resume_device)
+               return result;
+
+       mutex_lock(&resource->devices_lock);
+
+       device_list = resource->devices;
+       while (device_list) {
+               acpi_power_on_device(device_list->device);
+               device_list = device_list->next;
+       }
+
+       mutex_unlock(&resource->devices_lock);
+
        return result;
 }
 
@@ -355,7 +366,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
        if (acpi_power_get_context(res_handle, &resource))
                return;
 
-       mutex_lock(&resource->resource_lock);
+       mutex_lock(&resource->devices_lock);
        prev = NULL;
        curr = resource->devices;
        while (curr) {
@@ -372,7 +383,7 @@ static void __acpi_power_resource_unregister_device(struct device *dev,
                prev = curr;
                curr = curr->next;
        }
-       mutex_unlock(&resource->resource_lock);
+       mutex_unlock(&resource->devices_lock);
 }
 
 /* Unlink dev from all power resources in _PR0 */
@@ -414,10 +425,10 @@ static int __acpi_power_resource_register_device(
 
        power_resource_device->device = powered_device;
 
-       mutex_lock(&resource->resource_lock);
+       mutex_lock(&resource->devices_lock);
        power_resource_device->next = resource->devices;
        resource->devices = power_resource_device;
-       mutex_unlock(&resource->resource_lock);
+       mutex_unlock(&resource->devices_lock);
 
        return 0;
 }
@@ -462,7 +473,7 @@ int acpi_power_resource_register_device(struct device *dev, acpi_handle handle)
        return ret;
 
 no_power_resource:
-       printk(KERN_WARNING PREFIX "Invalid Power Resource to register!");
+       printk(KERN_DEBUG PREFIX "Invalid Power Resource to register!");
        return -ENODEV;
 }
 EXPORT_SYMBOL_GPL(acpi_power_resource_register_device);
@@ -721,6 +732,7 @@ static int acpi_power_add(struct acpi_device *device)
 
        resource->device = device;
        mutex_init(&resource->resource_lock);
+       mutex_init(&resource->devices_lock);
        strcpy(resource->name, device->pnp.bus_id);
        strcpy(acpi_device_name(device), ACPI_POWER_DEVICE_NAME);
        strcpy(acpi_device_class(device), ACPI_POWER_CLASS);
index 2be8ef1d30935af81a9b7ac3b721750fdda6b3cd..27cecd313e7588386960244548b391bfddac2a55 100644 (file)
@@ -115,7 +115,7 @@ config SATA_SIL24
          If unsure, say N.
 
 config ATA_SFF
-       bool "ATA SFF support"
+       bool "ATA SFF support (for legacy IDE and PATA)"
        default y
        help
          This option adds support for ATA controllers with SFF
index 062e6a1a248fe97b69cd2047017a88ded3f2164d..7862d17976b7532f48204cbf4210ffb6d4984f97 100644 (file)
@@ -256,10 +256,21 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(INTEL, 0x8c07), board_ahci }, /* Lynx Point RAID */
        { PCI_VDEVICE(INTEL, 0x8c0e), board_ahci }, /* Lynx Point RAID */
        { PCI_VDEVICE(INTEL, 0x8c0f), board_ahci }, /* Lynx Point RAID */
+       { PCI_VDEVICE(INTEL, 0x9c02), board_ahci }, /* Lynx Point-LP AHCI */
+       { PCI_VDEVICE(INTEL, 0x9c03), board_ahci }, /* Lynx Point-LP AHCI */
+       { PCI_VDEVICE(INTEL, 0x9c04), board_ahci }, /* Lynx Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9c05), board_ahci }, /* Lynx Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9c06), board_ahci }, /* Lynx Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9c07), board_ahci }, /* Lynx Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9c0e), board_ahci }, /* Lynx Point-LP RAID */
+       { PCI_VDEVICE(INTEL, 0x9c0f), board_ahci }, /* Lynx Point-LP RAID */
 
        /* JMicron 360/1/3/5/6, match class to avoid IDE function */
        { PCI_VENDOR_ID_JMICRON, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
          PCI_CLASS_STORAGE_SATA_AHCI, 0xffffff, board_ahci_ign_iferr },
+       /* JMicron 362B and 362C have an AHCI function with IDE class code */
+       { PCI_VDEVICE(JMICRON, 0x2362), board_ahci_ign_iferr },
+       { PCI_VDEVICE(JMICRON, 0x236f), board_ahci_ign_iferr },
 
        /* ATI */
        { PCI_VDEVICE(ATI, 0x4380), board_ahci_sb600 }, /* ATI SB600 */
@@ -385,6 +396,8 @@ static const struct pci_device_id ahci_pci_tbl[] = {
          .driver_data = board_ahci_yes_fbs },                  /* 88se9125 */
        { PCI_DEVICE(0x1b4b, 0x917a),
          .driver_data = board_ahci_yes_fbs },                  /* 88se9172 */
+       { PCI_DEVICE(0x1b4b, 0x9192),
+         .driver_data = board_ahci_yes_fbs },                  /* 88se9172 on some Gigabyte */
        { PCI_DEVICE(0x1b4b, 0x91a3),
          .driver_data = board_ahci_yes_fbs },
 
@@ -392,7 +405,10 @@ static const struct pci_device_id ahci_pci_tbl[] = {
        { PCI_VDEVICE(PROMISE, 0x3f20), board_ahci },   /* PDC42819 */
 
        /* Asmedia */
-       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1061 */
+       { PCI_VDEVICE(ASMEDIA, 0x0601), board_ahci },   /* ASM1060 */
+       { PCI_VDEVICE(ASMEDIA, 0x0602), board_ahci },   /* ASM1060 */
+       { PCI_VDEVICE(ASMEDIA, 0x0611), board_ahci },   /* ASM1061 */
+       { PCI_VDEVICE(ASMEDIA, 0x0612), board_ahci },   /* ASM1062 */
 
        /* Generic, PCI class code for AHCI */
        { PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID, PCI_ANY_ID,
index c2594ddf25b00f54d22b51c66f23db5d54d47222..57eb1c212a4ce8ee267d36b3f920d3011f96b832 100644 (file)
@@ -320,6 +320,7 @@ extern struct device_attribute *ahci_sdev_attrs[];
 extern struct ata_port_operations ahci_ops;
 extern struct ata_port_operations ahci_pmp_retry_srst_ops;
 
+unsigned int ahci_dev_classify(struct ata_port *ap);
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
                        u32 opts);
 void ahci_save_initial_config(struct device *dev,
index 3c809bfbccf58a2af573be99719a4fda77bd3815..ef773e12af79d2c931e37852e7c31b716a00e51e 100644 (file)
@@ -329,6 +329,14 @@ static const struct pci_device_id piix_pci_tbl[] = {
        { 0x8086, 0x8c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (Lynx Point) */
        { 0x8086, 0x8c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Lynx Point-LP) */
+       { 0x8086, 0x9c00, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+       /* SATA Controller IDE (Lynx Point-LP) */
+       { 0x8086, 0x9c01, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_sata_snb },
+       /* SATA Controller IDE (Lynx Point-LP) */
+       { 0x8086, 0x9c08, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
+       /* SATA Controller IDE (Lynx Point-LP) */
+       { 0x8086, 0x9c09, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        /* SATA Controller IDE (DH89xxCC) */
        { 0x8086, 0x2326, PCI_ANY_ID, PCI_ANY_ID, 0, 0, ich8_2port_sata },
        { }     /* terminate list */
index f9eaa82311a9a191dd56fe06881dd318d5c518eb..555c07afa05bc6f82d6cc0357684f1f8e8b9f8da 100644 (file)
@@ -1139,7 +1139,7 @@ static void ahci_dev_config(struct ata_device *dev)
        }
 }
 
-static unsigned int ahci_dev_classify(struct ata_port *ap)
+unsigned int ahci_dev_classify(struct ata_port *ap)
 {
        void __iomem *port_mmio = ahci_port_base(ap);
        struct ata_taskfile tf;
@@ -1153,6 +1153,7 @@ static unsigned int ahci_dev_classify(struct ata_port *ap)
 
        return ata_dev_classify(&tf);
 }
+EXPORT_SYMBOL_GPL(ahci_dev_classify);
 
 void ahci_fill_cmd_slot(struct ahci_port_priv *pp, unsigned int tag,
                        u32 opts)
index 902b5a457170958f4d805ae30185cee170e6b6e9..fd9ecf74e631afc800e56927069d97bd61774862 100644 (file)
@@ -60,17 +60,7 @@ acpi_handle ata_ap_acpi_handle(struct ata_port *ap)
        if (ap->flags & ATA_FLAG_ACPI_SATA)
                return NULL;
 
-       /*
-        * If acpi bind operation has already happened, we can get the handle
-        * for the port by checking the corresponding scsi_host device's
-        * firmware node, otherwise we will need to find out the handle from
-        * its parent's acpi node.
-        */
-       if (ap->scsi_host)
-               return DEVICE_ACPI_HANDLE(&ap->scsi_host->shost_gendev);
-       else
-               return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev),
-                               ap->port_no);
+       return acpi_get_child(DEVICE_ACPI_HANDLE(ap->host->dev), ap->port_no);
 }
 EXPORT_SYMBOL(ata_ap_acpi_handle);
 
@@ -1101,6 +1091,9 @@ static int ata_acpi_bind_host(struct ata_port *ap, acpi_handle *handle)
        if (!*handle)
                return -ENODEV;
 
+       if (ata_acpi_gtm(ap, &ap->__acpi_init_gtm) == 0)
+               ap->pflags |= ATA_PFLAG_INIT_GTM_VALID;
+
        return 0;
 }
 
index fadd5866d40fd29b2eb70df29e3d026e2e3722db..8e1039c8e15975aced4e6a359dc4a0451a58bc4b 100644 (file)
@@ -4062,7 +4062,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "_NEC DV5800A",       NULL,           ATA_HORKAGE_NODMA },
        { "SAMSUNG CD-ROM SN-124", "N001",      ATA_HORKAGE_NODMA },
        { "Seagate STT20000A", NULL,            ATA_HORKAGE_NODMA },
-       { "2GB ATA Flash Disk", "ADMA428M",     ATA_HORKAGE_NODMA },
+       { " 2GB ATA Flash Disk", "ADMA428M",    ATA_HORKAGE_NODMA },
        /* Odd clown on sil3726/4726 PMPs */
        { "Config  Disk",       NULL,           ATA_HORKAGE_DISABLE },
 
@@ -4128,6 +4128,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
 
        /* Devices that do not need bridging limits applied */
        { "MTRON MSP-SATA*",            NULL,   ATA_HORKAGE_BRIDGE_OK, },
+       { "BUFFALO HD-QSU2/R5",         NULL,   ATA_HORKAGE_BRIDGE_OK, },
 
        /* Devices which aren't very happy with higher link speeds */
        { "WD My Book",                 NULL,   ATA_HORKAGE_1_5_GBPS, },
index 361c75cea57b9d1836ca6be599343f019759833b..24e51056ac26a857c1db028b9eb71450a0608d45 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/delay.h>
 #include <scsi/scsi_host.h>
 #include <linux/libata.h>
+#include <linux/dmi.h>
 
 #define DRV_NAME "pata_atiixp"
 #define DRV_VERSION "0.4.6"
@@ -33,11 +34,26 @@ enum {
        ATIIXP_IDE_UDMA_MODE    = 0x56
 };
 
+static const struct dmi_system_id attixp_cable_override_dmi_table[] = {
+       {
+               /* Board has onboard PATA<->SATA converters */
+               .ident = "MSI E350DM-E33",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "MSI"),
+                       DMI_MATCH(DMI_BOARD_NAME, "E350DM-E33(MS-7720)"),
+               },
+       },
+       { }
+};
+
 static int atiixp_cable_detect(struct ata_port *ap)
 {
        struct pci_dev *pdev = to_pci_dev(ap->host->dev);
        u8 udma;
 
+       if (dmi_check_system(attixp_cable_override_dmi_table))
+               return ATA_CBL_PATA40_SHORT;
+
        /* Hack from drivers/ide/pci. Really we want to know how to do the
           raw detection not play follow the bios mode guess */
        pci_read_config_byte(pdev, ATIIXP_IDE_UDMA_MODE + ap->port_no, &udma);
index 78efb0306a446027f7fce1019572902f5aaa805b..34d94c762a1e79415fc00b0fc59caf034a3e186a 100644 (file)
@@ -250,7 +250,7 @@ int __init dma_declare_contiguous(struct device *dev, unsigned long size,
                return -EINVAL;
 
        /* Sanitise input arguments */
-       alignment = PAGE_SIZE << max(MAX_ORDER, pageblock_order);
+       alignment = PAGE_SIZE << max(MAX_ORDER - 1, pageblock_order);
        base = ALIGN(base, alignment);
        size = ALIGN(size, alignment);
        limit &= ~(alignment - 1);
index de0435e63b02cbd349c5dcc282682359f6f85934..887f68f6d79a9e615beba7525cb9d0e671917c4e 100644 (file)
@@ -35,6 +35,7 @@ new_skb(ulong len)
                skb_reset_mac_header(skb);
                skb_reset_network_header(skb);
                skb->protocol = __constant_htons(ETH_P_AOE);
+               skb_checksum_none_assert(skb);
        }
        return skb;
 }
index 38aa6dda6b81d0deeb355956ead087324f41f3d1..da3311129a0c5b87b8cc8b3718cc63b5bdfd3928 100644 (file)
@@ -795,6 +795,7 @@ static void complete_scsi_command(CommandList_struct *c, int timeout,
                                }
                        break;
                        case CMD_PROTOCOL_ERR:
+                               cmd->result = DID_ERROR << 16;
                                dev_warn(&h->pdev->dev,
                                        "%p has protocol error\n", c);
                         break;
index ba91b408abad75ce7da0ff173595ce23ee51f635..d84566496746aef57baf19dae86528bc202038cb 100644 (file)
@@ -889,6 +889,7 @@ struct bm_aio_ctx {
        unsigned int done;
        unsigned flags;
 #define BM_AIO_COPY_PAGES      1
+#define BM_WRITE_ALL_PAGES     2
        int error;
        struct kref kref;
 };
@@ -1059,7 +1060,8 @@ static int bm_rw(struct drbd_conf *mdev, int rw, unsigned flags, unsigned lazy_w
                if (lazy_writeout_upper_idx && i == lazy_writeout_upper_idx)
                        break;
                if (rw & WRITE) {
-                       if (bm_test_page_unchanged(b->bm_pages[i])) {
+                       if (!(flags & BM_WRITE_ALL_PAGES) &&
+                           bm_test_page_unchanged(b->bm_pages[i])) {
                                dynamic_dev_dbg(DEV, "skipped bm write for idx %u\n", i);
                                continue;
                        }
@@ -1140,6 +1142,17 @@ int drbd_bm_write(struct drbd_conf *mdev) __must_hold(local)
        return bm_rw(mdev, WRITE, 0, 0);
 }
 
+/**
+ * drbd_bm_write_all() - Write the whole bitmap to its on disk location.
+ * @mdev:      DRBD device.
+ *
+ * Will write all pages.
+ */
+int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local)
+{
+       return bm_rw(mdev, WRITE, BM_WRITE_ALL_PAGES, 0);
+}
+
 /**
  * drbd_bm_lazy_write_out() - Write bitmap pages 0 to @upper_idx-1, if they have changed.
  * @mdev:      DRBD device.
index b2ca143d0053d75487e3a083a4271b9e5d0d285e..b953cc7c9c00ce4fb13885f2631211c6046ed58d 100644 (file)
@@ -1469,6 +1469,7 @@ extern int  drbd_bm_e_weight(struct drbd_conf *mdev, unsigned long enr);
 extern int  drbd_bm_write_page(struct drbd_conf *mdev, unsigned int idx) __must_hold(local);
 extern int  drbd_bm_read(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write(struct drbd_conf *mdev) __must_hold(local);
+extern int drbd_bm_write_all(struct drbd_conf *mdev) __must_hold(local);
 extern int  drbd_bm_write_copy_pages(struct drbd_conf *mdev) __must_hold(local);
 extern unsigned long drbd_bm_ALe_set_all(struct drbd_conf *mdev,
                unsigned long al_enr);
index dbe6135a2abeddfb78b8d812f4b892c7b5696d03..f93a0320e952dd6b07fb8c73739ee73d3c1af0a0 100644 (file)
@@ -79,6 +79,7 @@ static int w_md_sync(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 static void md_sync_timer_fn(unsigned long data);
 static int w_bitmap_io(struct drbd_conf *mdev, struct drbd_work *w, int unused);
 static int w_go_diskless(struct drbd_conf *mdev, struct drbd_work *w, int unused);
+static void _tl_clear(struct drbd_conf *mdev);
 
 MODULE_AUTHOR("Philipp Reisner <phil@linbit.com>, "
              "Lars Ellenberg <lars@linbit.com>");
@@ -432,19 +433,10 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
 
        /* Actions operating on the disk state, also want to work on
           requests that got barrier acked. */
-       switch (what) {
-       case fail_frozen_disk_io:
-       case restart_frozen_disk_io:
-               list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
-                       req = list_entry(le, struct drbd_request, tl_requests);
-                       _req_mod(req, what);
-               }
 
-       case connection_lost_while_pending:
-       case resend:
-               break;
-       default:
-               dev_err(DEV, "what = %d in _tl_restart()\n", what);
+       list_for_each_safe(le, tle, &mdev->barrier_acked_requests) {
+               req = list_entry(le, struct drbd_request, tl_requests);
+               _req_mod(req, what);
        }
 }
 
@@ -458,12 +450,17 @@ static void _tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
  * receiver thread and the worker thread.
  */
 void tl_clear(struct drbd_conf *mdev)
+{
+       spin_lock_irq(&mdev->req_lock);
+       _tl_clear(mdev);
+       spin_unlock_irq(&mdev->req_lock);
+}
+
+static void _tl_clear(struct drbd_conf *mdev)
 {
        struct list_head *le, *tle;
        struct drbd_request *r;
 
-       spin_lock_irq(&mdev->req_lock);
-
        _tl_restart(mdev, connection_lost_while_pending);
 
        /* we expect this list to be empty. */
@@ -482,7 +479,6 @@ void tl_clear(struct drbd_conf *mdev)
 
        memset(mdev->app_reads_hash, 0, APP_R_HSIZE*sizeof(void *));
 
-       spin_unlock_irq(&mdev->req_lock);
 }
 
 void tl_restart(struct drbd_conf *mdev, enum drbd_req_event what)
@@ -1476,12 +1472,12 @@ static void after_state_ch(struct drbd_conf *mdev, union drbd_state os,
        if (ns.susp_fen) {
                /* case1: The outdate peer handler is successful: */
                if (os.pdsk > D_OUTDATED  && ns.pdsk <= D_OUTDATED) {
-                       tl_clear(mdev);
                        if (test_bit(NEW_CUR_UUID, &mdev->flags)) {
                                drbd_uuid_new_current(mdev);
                                clear_bit(NEW_CUR_UUID, &mdev->flags);
                        }
                        spin_lock_irq(&mdev->req_lock);
+                       _tl_clear(mdev);
                        _drbd_set_state(_NS(mdev, susp_fen, 0), CS_VERBOSE, NULL);
                        spin_unlock_irq(&mdev->req_lock);
                }
index fb9dce8daa2468c76992f4ab609adb471bc42af3..edb490aad8b44fa507da3d72724b5df925a020e4 100644 (file)
@@ -674,8 +674,8 @@ enum determine_dev_size drbd_determine_dev_size(struct drbd_conf *mdev, enum dds
                         la_size_changed && md_moved ? "size changed and md moved" :
                         la_size_changed ? "size changed" : "md moved");
                /* next line implicitly does drbd_suspend_io()+drbd_resume_io() */
-               err = drbd_bitmap_io(mdev, &drbd_bm_write,
-                               "size changed", BM_LOCKED_MASK);
+               err = drbd_bitmap_io(mdev, md_moved ? &drbd_bm_write_all : &drbd_bm_write,
+                                    "size changed", BM_LOCKED_MASK);
                if (err) {
                        rv = dev_size_error;
                        goto out;
index 910335c30927f0429a4c4b0fddcfe74033c45e8d..01b2ac641c7babe119f98dac7596ff8a690402a8 100644 (file)
@@ -695,6 +695,12 @@ int __req_mod(struct drbd_request *req, enum drbd_req_event what,
                break;
 
        case resend:
+               /* Simply complete (local only) READs. */
+               if (!(req->rq_state & RQ_WRITE) && !req->w.cb) {
+                       _req_may_be_done(req, m);
+                       break;
+               }
+
                /* If RQ_NET_OK is already set, we got a P_WRITE_ACK or P_RECV_ACK
                   before the connection loss (B&C only); only P_BARRIER_ACK was missing.
                   Trowing them out of the TL here by pretending we got a BARRIER_ACK
@@ -834,7 +840,15 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns
                req->private_bio = NULL;
        }
        if (rw == WRITE) {
-               remote = 1;
+               /* Need to replicate writes.  Unless it is an empty flush,
+                * which is better mapped to a DRBD P_BARRIER packet,
+                * also for drbd wire protocol compatibility reasons. */
+               if (unlikely(size == 0)) {
+                       /* The only size==0 bios we expect are empty flushes. */
+                       D_ASSERT(bio->bi_rw & REQ_FLUSH);
+                       remote = 0;
+               } else
+                       remote = 1;
        } else {
                /* READ || READA */
                if (local) {
@@ -870,8 +884,11 @@ static int drbd_make_request_common(struct drbd_conf *mdev, struct bio *bio, uns
         * extent.  This waits for any resync activity in the corresponding
         * resync extent to finish, and, if necessary, pulls in the target
         * extent into the activity log, which involves further disk io because
-        * of transactional on-disk meta data updates. */
-       if (rw == WRITE && local && !test_bit(AL_SUSPENDED, &mdev->flags)) {
+        * of transactional on-disk meta data updates.
+        * Empty flushes don't need to go into the activity log, they can only
+        * flush data for pending writes which are already in there. */
+       if (rw == WRITE && local && size
+       && !test_bit(AL_SUSPENDED, &mdev->flags)) {
                req->rq_state |= RQ_IN_ACT_LOG;
                drbd_al_begin_io(mdev, sector);
        }
@@ -994,7 +1011,10 @@ allocate_barrier:
        if (rw == WRITE && _req_conflicts(req))
                goto fail_conflicting;
 
-       list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
+       /* no point in adding empty flushes to the transfer log,
+        * they are mapped to drbd barriers already. */
+       if (likely(size!=0))
+               list_add_tail(&req->tl_requests, &mdev->newest_tle->requests);
 
        /* NOTE remote first: to get the concurrent write detection right,
         * we must register the request before start of local IO.  */
@@ -1014,6 +1034,14 @@ allocate_barrier:
            mdev->net_conf->on_congestion != OC_BLOCK && mdev->agreed_pro_version >= 96)
                maybe_pull_ahead(mdev);
 
+       /* If this was a flush, queue a drbd barrier/start a new epoch.
+        * Unless the current epoch was empty anyways, or we are not currently
+        * replicating, in which case there is no point. */
+       if (unlikely(bio->bi_rw & REQ_FLUSH)
+               && mdev->newest_tle->n_writes
+               && drbd_should_do_remote(mdev->state))
+               queue_barrier(mdev);
+
        spin_unlock_irq(&mdev->req_lock);
        kfree(b); /* if someone else has beaten us to it... */
 
index a8fddeb3d638ebcdf9a0191beda816d8f1338ccd..f946d31d6917e00aa0637df5d21cef35ebf82845 100644 (file)
@@ -1148,11 +1148,15 @@ static bool mtip_pause_ncq(struct mtip_port *port,
        reply = port->rxfis + RX_FIS_D2H_REG;
        task_file_data = readl(port->mmio+PORT_TFDATA);
 
-       if ((task_file_data & 1) || (fis->command == ATA_CMD_SEC_ERASE_UNIT))
+       if (fis->command == ATA_CMD_SEC_ERASE_UNIT)
+               clear_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
+
+       if ((task_file_data & 1))
                return false;
 
        if (fis->command == ATA_CMD_SEC_ERASE_PREP) {
                set_bit(MTIP_PF_SE_ACTIVE_BIT, &port->flags);
+               set_bit(MTIP_DDF_SEC_LOCK_BIT, &port->dd->dd_flag);
                port->ic_pause_timer = jiffies;
                return true;
        } else if ((fis->command == ATA_CMD_DOWNLOAD_MICRO) &&
@@ -1900,7 +1904,7 @@ static int exec_drive_command(struct mtip_port *port, u8 *command,
        int rv = 0, xfer_sz = command[3];
 
        if (xfer_sz) {
-               if (user_buffer)
+               if (!user_buffer)
                        return -EFAULT;
 
                buf = dmam_alloc_coherent(&port->dd->pdev->dev,
@@ -2043,7 +2047,7 @@ static void mtip_set_timeout(struct host_to_dev_fis *fis, unsigned int *timeout)
                *timeout = 240000; /* 4 minutes */
                break;
        case ATA_CMD_STANDBYNOW1:
-               *timeout = 10000;  /* 10 seconds */
+               *timeout = 120000;  /* 2 minutes */
                break;
        case 0xF7:
        case 0xFA:
@@ -2588,9 +2592,6 @@ static ssize_t mtip_hw_read_registers(struct file *f, char __user *ubuf,
        if (!len || size)
                return 0;
 
-       if (size < 0)
-               return -EINVAL;
-
        size += sprintf(&buf[size], "H/ S ACTive      : [ 0x");
 
        for (n = dd->slot_groups-1; n >= 0; n--)
@@ -2660,9 +2661,6 @@ static ssize_t mtip_hw_read_flags(struct file *f, char __user *ubuf,
        if (!len || size)
                return 0;
 
-       if (size < 0)
-               return -EINVAL;
-
        size += sprintf(&buf[size], "Flag-port : [ %08lX ]\n",
                                                        dd->port->flags);
        size += sprintf(&buf[size], "Flag-dd   : [ %08lX ]\n",
@@ -3214,8 +3212,8 @@ static int mtip_hw_init(struct driver_data *dd)
                                "Unable to check write protect progress\n");
        else
                dev_info(&dd->pdev->dev,
-                               "Write protect progress: %d%% (%d blocks)\n",
-                               attr242.cur, attr242.data);
+                               "Write protect progress: %u%% (%u blocks)\n",
+                               attr242.cur, le32_to_cpu(attr242.data));
        return rv;
 
 out3:
@@ -3619,6 +3617,10 @@ static void mtip_make_request(struct request_queue *queue, struct bio *bio)
                        bio_endio(bio, -ENODATA);
                        return;
                }
+               if (unlikely(test_bit(MTIP_DDF_SEC_LOCK_BIT, &dd->dd_flag))) {
+                       bio_endio(bio, -ENODATA);
+                       return;
+               }
        }
 
        if (unlikely(!bio_has_data(bio))) {
@@ -4168,7 +4170,13 @@ static void mtip_pci_shutdown(struct pci_dev *pdev)
 
 /* Table of device ids supported by this driver. */
 static DEFINE_PCI_DEVICE_TABLE(mtip_pci_tbl) = {
-       {  PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320H_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320M_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P320S_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P325M_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420H_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P420M_DEVICE_ID) },
+       { PCI_DEVICE(PCI_VENDOR_ID_MICRON, P425M_DEVICE_ID) },
        { 0 }
 };
 
@@ -4199,12 +4207,12 @@ static int __init mtip_init(void)
 {
        int error;
 
-       printk(KERN_INFO MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
+       pr_info(MTIP_DRV_NAME " Version " MTIP_DRV_VERSION "\n");
 
        /* Allocate a major block device number to use with this driver. */
        error = register_blkdev(0, MTIP_DRV_NAME);
        if (error <= 0) {
-               printk(KERN_ERR "Unable to register block device (%d)\n",
+               pr_err("Unable to register block device (%d)\n",
                error);
                return -EBUSY;
        }
@@ -4213,7 +4221,7 @@ static int __init mtip_init(void)
        if (!dfs_parent) {
                dfs_parent = debugfs_create_dir("rssd", NULL);
                if (IS_ERR_OR_NULL(dfs_parent)) {
-                       printk(KERN_WARNING "Error creating debugfs parent\n");
+                       pr_warn("Error creating debugfs parent\n");
                        dfs_parent = NULL;
                }
        }
index f51fc23d17bb0e0025c74ac9f495007dcbc8b784..18627a1d04c59eff34f7cdd2313555b10a75b283 100644 (file)
 
 /* Micron Vendor ID & P320x SSD Device ID */
 #define PCI_VENDOR_ID_MICRON    0x1344
-#define P320_DEVICE_ID         0x5150
+#define P320H_DEVICE_ID                0x5150
+#define P320M_DEVICE_ID                0x5151
+#define P320S_DEVICE_ID                0x5152
+#define P325M_DEVICE_ID                0x5153
+#define P420H_DEVICE_ID                0x5160
+#define P420M_DEVICE_ID                0x5161
+#define P425M_DEVICE_ID                0x5163
 
 /* Driver name and version strings */
 #define MTIP_DRV_NAME          "mtip32xx"
@@ -131,10 +137,12 @@ enum {
        MTIP_PF_SVC_THD_STOP_BIT    = 8,
 
        /* below are bit numbers in 'dd_flag' defined in driver_data */
+       MTIP_DDF_SEC_LOCK_BIT       = 0,
        MTIP_DDF_REMOVE_PENDING_BIT = 1,
        MTIP_DDF_OVER_TEMP_BIT      = 2,
        MTIP_DDF_WRITE_PROTECT_BIT  = 3,
        MTIP_DDF_STOP_IO      = ((1 << MTIP_DDF_REMOVE_PENDING_BIT) | \
+                               (1 << MTIP_DDF_SEC_LOCK_BIT) | \
                                (1 << MTIP_DDF_OVER_TEMP_BIT) | \
                                (1 << MTIP_DDF_WRITE_PROTECT_BIT)),
 
index d07c9f7fded600d76192330ef37c35c2135c0fb5..0c03411c59eb8cba0f744e72aed93342dc9cace8 100644 (file)
@@ -449,6 +449,14 @@ static void nbd_clear_que(struct nbd_device *nbd)
                req->errors++;
                nbd_end_request(req);
        }
+
+       while (!list_empty(&nbd->waiting_queue)) {
+               req = list_entry(nbd->waiting_queue.next, struct request,
+                                queuelist);
+               list_del_init(&req->queuelist);
+               req->errors++;
+               nbd_end_request(req);
+       }
 }
 
 
@@ -598,6 +606,7 @@ static int __nbd_ioctl(struct block_device *bdev, struct nbd_device *nbd,
                nbd->file = NULL;
                nbd_clear_que(nbd);
                BUG_ON(!list_empty(&nbd->queue_head));
+               BUG_ON(!list_empty(&nbd->waiting_queue));
                if (file)
                        fput(file);
                return 0;
index 38a2d0631882ccd192ee475fc3b0f7a2e3b9d0cb..ad16c68c86451bd80dc18bbb7673e14d4611d947 100644 (file)
@@ -79,6 +79,7 @@ struct nvme_dev {
        char serial[20];
        char model[40];
        char firmware_rev[8];
+       u32 max_hw_sectors;
 };
 
 /*
@@ -835,15 +836,15 @@ static int nvme_identify(struct nvme_dev *dev, unsigned nsid, unsigned cns,
 }
 
 static int nvme_get_features(struct nvme_dev *dev, unsigned fid,
-                               unsigned dword11, dma_addr_t dma_addr)
+                               unsigned nsid, dma_addr_t dma_addr)
 {
        struct nvme_command c;
 
        memset(&c, 0, sizeof(c));
        c.features.opcode = nvme_admin_get_features;
+       c.features.nsid = cpu_to_le32(nsid);
        c.features.prp1 = cpu_to_le64(dma_addr);
        c.features.fid = cpu_to_le32(fid);
-       c.features.dword11 = cpu_to_le32(dword11);
 
        return nvme_submit_admin_cmd(dev, &c, NULL);
 }
@@ -862,11 +863,51 @@ static int nvme_set_features(struct nvme_dev *dev, unsigned fid,
        return nvme_submit_admin_cmd(dev, &c, result);
 }
 
+/**
+ * nvme_cancel_ios - Cancel outstanding I/Os
+ * @queue: The queue to cancel I/Os on
+ * @timeout: True to only cancel I/Os which have timed out
+ */
+static void nvme_cancel_ios(struct nvme_queue *nvmeq, bool timeout)
+{
+       int depth = nvmeq->q_depth - 1;
+       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
+       unsigned long now = jiffies;
+       int cmdid;
+
+       for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
+               void *ctx;
+               nvme_completion_fn fn;
+               static struct nvme_completion cqe = {
+                       .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1,
+               };
+
+               if (timeout && !time_after(now, info[cmdid].timeout))
+                       continue;
+               dev_warn(nvmeq->q_dmadev, "Cancelling I/O %d\n", cmdid);
+               ctx = cancel_cmdid(nvmeq, cmdid, &fn);
+               fn(nvmeq->dev, ctx, &cqe);
+       }
+}
+
+static void nvme_free_queue_mem(struct nvme_queue *nvmeq)
+{
+       dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
+                               (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
+       dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
+                                       nvmeq->sq_cmds, nvmeq->sq_dma_addr);
+       kfree(nvmeq);
+}
+
 static void nvme_free_queue(struct nvme_dev *dev, int qid)
 {
        struct nvme_queue *nvmeq = dev->queues[qid];
        int vector = dev->entry[nvmeq->cq_vector].vector;
 
+       spin_lock_irq(&nvmeq->q_lock);
+       nvme_cancel_ios(nvmeq, false);
+       spin_unlock_irq(&nvmeq->q_lock);
+
        irq_set_affinity_hint(vector, NULL);
        free_irq(vector, nvmeq);
 
@@ -876,18 +917,15 @@ static void nvme_free_queue(struct nvme_dev *dev, int qid)
                adapter_delete_cq(dev, qid);
        }
 
-       dma_free_coherent(nvmeq->q_dmadev, CQ_SIZE(nvmeq->q_depth),
-                               (void *)nvmeq->cqes, nvmeq->cq_dma_addr);
-       dma_free_coherent(nvmeq->q_dmadev, SQ_SIZE(nvmeq->q_depth),
-                                       nvmeq->sq_cmds, nvmeq->sq_dma_addr);
-       kfree(nvmeq);
+       nvme_free_queue_mem(nvmeq);
 }
 
 static struct nvme_queue *nvme_alloc_queue(struct nvme_dev *dev, int qid,
                                                        int depth, int vector)
 {
        struct device *dmadev = &dev->pci_dev->dev;
-       unsigned extra = (depth / 8) + (depth * sizeof(struct nvme_cmd_info));
+       unsigned extra = DIV_ROUND_UP(depth, 8) + (depth *
+                                               sizeof(struct nvme_cmd_info));
        struct nvme_queue *nvmeq = kzalloc(sizeof(*nvmeq) + extra, GFP_KERNEL);
        if (!nvmeq)
                return NULL;
@@ -975,7 +1013,7 @@ static __devinit struct nvme_queue *nvme_create_queue(struct nvme_dev *dev,
 
 static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
 {
-       int result;
+       int result = 0;
        u32 aqa;
        u64 cap;
        unsigned long timeout;
@@ -1005,17 +1043,22 @@ static int __devinit nvme_configure_admin_queue(struct nvme_dev *dev)
        timeout = ((NVME_CAP_TIMEOUT(cap) + 1) * HZ / 2) + jiffies;
        dev->db_stride = NVME_CAP_STRIDE(cap);
 
-       while (!(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
+       while (!result && !(readl(&dev->bar->csts) & NVME_CSTS_RDY)) {
                msleep(100);
                if (fatal_signal_pending(current))
-                       return -EINTR;
+                       result = -EINTR;
                if (time_after(jiffies, timeout)) {
                        dev_err(&dev->pci_dev->dev,
                                "Device not ready; aborting initialisation\n");
-                       return -ENODEV;
+                       result = -ENODEV;
                }
        }
 
+       if (result) {
+               nvme_free_queue_mem(nvmeq);
+               return result;
+       }
+
        result = queue_request_irq(dev, nvmeq, "nvme admin");
        dev->queues[0] = nvmeq;
        return result;
@@ -1037,6 +1080,8 @@ static struct nvme_iod *nvme_map_user_pages(struct nvme_dev *dev, int write,
        offset = offset_in_page(addr);
        count = DIV_ROUND_UP(offset + length, PAGE_SIZE);
        pages = kcalloc(count, sizeof(*pages), GFP_KERNEL);
+       if (!pages)
+               return ERR_PTR(-ENOMEM);
 
        err = get_user_pages_fast(addr, count, 1, pages);
        if (err < count) {
@@ -1146,14 +1191,13 @@ static int nvme_submit_io(struct nvme_ns *ns, struct nvme_user_io __user *uio)
        return status;
 }
 
-static int nvme_user_admin_cmd(struct nvme_ns *ns,
+static int nvme_user_admin_cmd(struct nvme_dev *dev,
                                        struct nvme_admin_cmd __user *ucmd)
 {
-       struct nvme_dev *dev = ns->dev;
        struct nvme_admin_cmd cmd;
        struct nvme_command c;
        int status, length;
-       struct nvme_iod *iod;
+       struct nvme_iod *uninitialized_var(iod);
 
        if (!capable(CAP_SYS_ADMIN))
                return -EACCES;
@@ -1204,7 +1248,7 @@ static int nvme_ioctl(struct block_device *bdev, fmode_t mode, unsigned int cmd,
        case NVME_IOCTL_ID:
                return ns->ns_id;
        case NVME_IOCTL_ADMIN_CMD:
-               return nvme_user_admin_cmd(ns, (void __user *)arg);
+               return nvme_user_admin_cmd(ns->dev, (void __user *)arg);
        case NVME_IOCTL_SUBMIT_IO:
                return nvme_submit_io(ns, (void __user *)arg);
        default:
@@ -1218,26 +1262,6 @@ static const struct block_device_operations nvme_fops = {
        .compat_ioctl   = nvme_ioctl,
 };
 
-static void nvme_timeout_ios(struct nvme_queue *nvmeq)
-{
-       int depth = nvmeq->q_depth - 1;
-       struct nvme_cmd_info *info = nvme_cmd_info(nvmeq);
-       unsigned long now = jiffies;
-       int cmdid;
-
-       for_each_set_bit(cmdid, nvmeq->cmdid_data, depth) {
-               void *ctx;
-               nvme_completion_fn fn;
-               static struct nvme_completion cqe = { .status = cpu_to_le16(NVME_SC_ABORT_REQ) << 1, };
-
-               if (!time_after(now, info[cmdid].timeout))
-                       continue;
-               dev_warn(nvmeq->q_dmadev, "Timing out I/O %d\n", cmdid);
-               ctx = cancel_cmdid(nvmeq, cmdid, &fn);
-               fn(nvmeq->dev, ctx, &cqe);
-       }
-}
-
 static void nvme_resubmit_bios(struct nvme_queue *nvmeq)
 {
        while (bio_list_peek(&nvmeq->sq_cong)) {
@@ -1269,7 +1293,7 @@ static int nvme_kthread(void *data)
                                spin_lock_irq(&nvmeq->q_lock);
                                if (nvme_process_cq(nvmeq))
                                        printk("process_cq did something\n");
-                               nvme_timeout_ios(nvmeq);
+                               nvme_cancel_ios(nvmeq, true);
                                nvme_resubmit_bios(nvmeq);
                                spin_unlock_irq(&nvmeq->q_lock);
                        }
@@ -1339,6 +1363,9 @@ static struct nvme_ns *nvme_alloc_ns(struct nvme_dev *dev, int nsid,
        ns->disk = disk;
        lbaf = id->flbas & 0xf;
        ns->lba_shift = id->lbaf[lbaf].ds;
+       blk_queue_logical_block_size(ns->queue, 1 << ns->lba_shift);
+       if (dev->max_hw_sectors)
+               blk_queue_max_hw_sectors(ns->queue, dev->max_hw_sectors);
 
        disk->major = nvme_major;
        disk->minors = NVME_MINORS;
@@ -1383,7 +1410,7 @@ static int set_queue_count(struct nvme_dev *dev, int count)
 
 static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
 {
-       int result, cpu, i, nr_io_queues, db_bar_size;
+       int result, cpu, i, nr_io_queues, db_bar_size, q_depth;
 
        nr_io_queues = num_online_cpus();
        result = set_queue_count(dev, nr_io_queues);
@@ -1429,9 +1456,10 @@ static int __devinit nvme_setup_io_queues(struct nvme_dev *dev)
                cpu = cpumask_next(cpu, cpu_online_mask);
        }
 
+       q_depth = min_t(int, NVME_CAP_MQES(readq(&dev->bar->cap)) + 1,
+                                                               NVME_Q_DEPTH);
        for (i = 0; i < nr_io_queues; i++) {
-               dev->queues[i + 1] = nvme_create_queue(dev, i + 1,
-                                                       NVME_Q_DEPTH, i);
+               dev->queues[i + 1] = nvme_create_queue(dev, i + 1, q_depth, i);
                if (IS_ERR(dev->queues[i + 1]))
                        return PTR_ERR(dev->queues[i + 1]);
                dev->queue_count++;
@@ -1480,6 +1508,10 @@ static int __devinit nvme_dev_add(struct nvme_dev *dev)
        memcpy(dev->serial, ctrl->sn, sizeof(ctrl->sn));
        memcpy(dev->model, ctrl->mn, sizeof(ctrl->mn));
        memcpy(dev->firmware_rev, ctrl->fr, sizeof(ctrl->fr));
+       if (ctrl->mdts) {
+               int shift = NVME_CAP_MPSMIN(readq(&dev->bar->cap)) + 12;
+               dev->max_hw_sectors = 1 << (ctrl->mdts + shift - 9);
+       }
 
        id_ns = mem;
        for (i = 1; i <= nn; i++) {
@@ -1523,8 +1555,6 @@ static int nvme_dev_remove(struct nvme_dev *dev)
        list_del(&dev->node);
        spin_unlock(&dev_list_lock);
 
-       /* TODO: wait all I/O finished or cancel them */
-
        list_for_each_entry_safe(ns, next, &dev->namespaces, list) {
                list_del(&ns->list);
                del_gendisk(ns->disk);
@@ -1560,15 +1590,33 @@ static void nvme_release_prp_pools(struct nvme_dev *dev)
        dma_pool_destroy(dev->prp_small_pool);
 }
 
-/* XXX: Use an ida or something to let remove / add work correctly */
-static void nvme_set_instance(struct nvme_dev *dev)
+static DEFINE_IDA(nvme_instance_ida);
+
+static int nvme_set_instance(struct nvme_dev *dev)
 {
-       static int instance;
-       dev->instance = instance++;
+       int instance, error;
+
+       do {
+               if (!ida_pre_get(&nvme_instance_ida, GFP_KERNEL))
+                       return -ENODEV;
+
+               spin_lock(&dev_list_lock);
+               error = ida_get_new(&nvme_instance_ida, &instance);
+               spin_unlock(&dev_list_lock);
+       } while (error == -EAGAIN);
+
+       if (error)
+               return -ENODEV;
+
+       dev->instance = instance;
+       return 0;
 }
 
 static void nvme_release_instance(struct nvme_dev *dev)
 {
+       spin_lock(&dev_list_lock);
+       ida_remove(&nvme_instance_ida, dev->instance);
+       spin_unlock(&dev_list_lock);
 }
 
 static int __devinit nvme_probe(struct pci_dev *pdev,
@@ -1601,7 +1649,10 @@ static int __devinit nvme_probe(struct pci_dev *pdev,
        pci_set_drvdata(pdev, dev);
        dma_set_mask(&pdev->dev, DMA_BIT_MASK(64));
        dma_set_coherent_mask(&pdev->dev, DMA_BIT_MASK(64));
-       nvme_set_instance(dev);
+       result = nvme_set_instance(dev);
+       if (result)
+               goto disable;
+
        dev->entry[0].vector = pdev->irq;
 
        result = nvme_setup_prp_pools(dev);
@@ -1704,15 +1755,17 @@ static struct pci_driver nvme_driver = {
 
 static int __init nvme_init(void)
 {
-       int result = -EBUSY;
+       int result;
 
        nvme_thread = kthread_run(nvme_kthread, NULL, "nvme");
        if (IS_ERR(nvme_thread))
                return PTR_ERR(nvme_thread);
 
-       nvme_major = register_blkdev(nvme_major, "nvme");
-       if (nvme_major <= 0)
+       result = register_blkdev(nvme_major, "nvme");
+       if (result < 0)
                goto kill_kthread;
+       else if (result > 0)
+               nvme_major = result;
 
        result = pci_register_driver(&nvme_driver);
        if (result)
index 9917943a3572ef577ac7a511ef375d11dae08350..54a55f03115df1df8dddb45e354eb8246336e56b 100644 (file)
@@ -246,13 +246,12 @@ static int rbd_open(struct block_device *bdev, fmode_t mode)
 {
        struct rbd_device *rbd_dev = bdev->bd_disk->private_data;
 
-       rbd_get_dev(rbd_dev);
-
-       set_device_ro(bdev, rbd_dev->read_only);
-
        if ((mode & FMODE_WRITE) && rbd_dev->read_only)
                return -EROFS;
 
+       rbd_get_dev(rbd_dev);
+       set_device_ro(bdev, rbd_dev->read_only);
+
        return 0;
 }
 
index 73f196ca713f20e037e22adccba64d0e00c936b1..c6decb901e5e16f4ba09ccef7db33675aeecb189 100644 (file)
@@ -337,7 +337,7 @@ static void xen_blkbk_unmap(struct pending_req *req)
                invcount++;
        }
 
-       ret = gnttab_unmap_refs(unmap, pages, invcount, false);
+       ret = gnttab_unmap_refs(unmap, NULL, pages, invcount);
        BUG_ON(ret);
 }
 
index 11f36e5021367d7dd7c2b0794241154a0544ad0a..fc2de5528dcc94eb65537baa17b78048a5002827 100644 (file)
@@ -86,6 +86,7 @@ static struct usb_device_id ath3k_table[] = {
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C) },
+       { USB_DEVICE(0x0489, 0xE036) },
 
        { }     /* Terminating entry */
 };
@@ -109,6 +110,7 @@ static struct usb_device_id ath3k_blist_tbl[] = {
 
        /* Atheros AR5BBU22 with sflash firmware */
        { USB_DEVICE(0x0489, 0xE03C), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xE036), .driver_info = BTUSB_ATH3012 },
 
        { }     /* Terminating entry */
 };
index cef3bac1a543d83113b54939585f807748accaf7..654e248763efb98024bd81b57118cd2ad1d77cdf 100644 (file)
@@ -52,6 +52,9 @@ static struct usb_device_id btusb_table[] = {
        /* Generic Bluetooth USB device */
        { USB_DEVICE_INFO(0xe0, 0x01, 0x01) },
 
+       /* Apple-specific (Broadcom) devices */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x05ac, 0xff, 0x01, 0x01) },
+
        /* Broadcom SoftSailing reporting vendor specific */
        { USB_DEVICE(0x0a5c, 0x21e1) },
 
@@ -94,16 +97,14 @@ static struct usb_device_id btusb_table[] = {
 
        /* Broadcom BCM20702A0 */
        { USB_DEVICE(0x0489, 0xe042) },
-       { USB_DEVICE(0x0a5c, 0x21e3) },
-       { USB_DEVICE(0x0a5c, 0x21e6) },
-       { USB_DEVICE(0x0a5c, 0x21e8) },
-       { USB_DEVICE(0x0a5c, 0x21f3) },
-       { USB_DEVICE(0x0a5c, 0x21f4) },
        { USB_DEVICE(0x413c, 0x8197) },
 
        /* Foxconn - Hon Hai */
        { USB_DEVICE(0x0489, 0xe033) },
 
+       /*Broadcom devices with vendor specific id */
+       { USB_VENDOR_AND_INTERFACE_INFO(0x0a5c, 0xff, 0x01, 0x01) },
+
        { }     /* Terminating entry */
 };
 
@@ -141,6 +142,7 @@ static struct usb_device_id blacklist_table[] = {
 
        /* Atheros AR5BBU12 with sflash firmware */
        { USB_DEVICE(0x0489, 0xe03c), .driver_info = BTUSB_ATH3012 },
+       { USB_DEVICE(0x0489, 0xe036), .driver_info = BTUSB_ATH3012 },
 
        /* Broadcom BCM2035 */
        { USB_DEVICE(0x0a5c, 0x2035), .driver_info = BTUSB_WRONG_SCO_MTU },
index 5869ea3870545f0f7c3ab64a185e1c486243b4e1..72ce247a0e8d5c08395fe92c9163a8c376c555bc 100644 (file)
@@ -1,4 +1,5 @@
 # common clock types
+obj-$(CONFIG_HAVE_CLK)         += clk-devres.o
 obj-$(CONFIG_CLKDEV_LOOKUP)    += clkdev.o
 obj-$(CONFIG_COMMON_CLK)       += clk.o clk-fixed-rate.o clk-gate.o \
                                   clk-mux.o clk-divider.o clk-fixed-factor.o
diff --git a/drivers/clk/clk-devres.c b/drivers/clk/clk-devres.c
new file mode 100644 (file)
index 0000000..8f57154
--- /dev/null
@@ -0,0 +1,55 @@
+/*
+ * 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/device.h>
+#include <linux/export.h>
+#include <linux/gfp.h>
+
+static void devm_clk_release(struct device *dev, void *res)
+{
+       clk_put(*(struct clk **)res);
+}
+
+struct clk *devm_clk_get(struct device *dev, const char *id)
+{
+       struct clk **ptr, *clk;
+
+       ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
+       if (!ptr)
+               return ERR_PTR(-ENOMEM);
+
+       clk = clk_get(dev, id);
+       if (!IS_ERR(clk)) {
+               *ptr = clk;
+               devres_add(dev, ptr);
+       } else {
+               devres_free(ptr);
+       }
+
+       return clk;
+}
+EXPORT_SYMBOL(devm_clk_get);
+
+static int devm_clk_match(struct device *dev, void *res, void *data)
+{
+       struct clk **c = res;
+       if (!c || !*c) {
+               WARN_ON(!c || !*c);
+               return 0;
+       }
+       return *c == data;
+}
+
+void devm_clk_put(struct device *dev, struct clk *clk)
+{
+       int ret;
+
+       ret = devres_release(dev, devm_clk_release, devm_clk_match, clk);
+
+       WARN_ON(ret);
+}
+EXPORT_SYMBOL(devm_clk_put);
index d423c9bdd71a9d4670c340c94f7f1eb08152ed41..442a31363873d35f319e0d5ee5b6b250084c02fc 100644 (file)
@@ -171,51 +171,6 @@ void clk_put(struct clk *clk)
 }
 EXPORT_SYMBOL(clk_put);
 
-static void devm_clk_release(struct device *dev, void *res)
-{
-       clk_put(*(struct clk **)res);
-}
-
-struct clk *devm_clk_get(struct device *dev, const char *id)
-{
-       struct clk **ptr, *clk;
-
-       ptr = devres_alloc(devm_clk_release, sizeof(*ptr), GFP_KERNEL);
-       if (!ptr)
-               return ERR_PTR(-ENOMEM);
-
-       clk = clk_get(dev, id);
-       if (!IS_ERR(clk)) {
-               *ptr = clk;
-               devres_add(dev, ptr);
-       } else {
-               devres_free(ptr);
-       }
-
-       return clk;
-}
-EXPORT_SYMBOL(devm_clk_get);
-
-static int devm_clk_match(struct device *dev, void *res, void *data)
-{
-       struct clk **c = res;
-       if (!c || !*c) {
-               WARN_ON(!c || !*c);
-               return 0;
-       }
-       return *c == data;
-}
-
-void devm_clk_put(struct device *dev, struct clk *clk)
-{
-       int ret;
-
-       ret = devres_destroy(dev, devm_clk_release, devm_clk_match, clk);
-
-       WARN_ON(ret);
-}
-EXPORT_SYMBOL(devm_clk_put);
-
 void clkdev_add(struct clk_lookup *cl)
 {
        mutex_lock(&clocks_mutex);
index 17fa04d08be9cc0af181e5f20398128d8b4d5234..b47034e650a579b9d0263f8d0a03af2ecc8b3aa7 100644 (file)
@@ -218,7 +218,7 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
 
        policy->cur = policy->min = policy->max = omap_getspeed(policy->cpu);
 
-       if (atomic_inc_return(&freq_table_users) == 1)
+       if (!freq_table)
                result = opp_init_cpufreq_table(mpu_dev, &freq_table);
 
        if (result) {
@@ -227,6 +227,8 @@ static int __cpuinit omap_cpu_init(struct cpufreq_policy *policy)
                goto fail_ck;
        }
 
+       atomic_inc_return(&freq_table_users);
+
        result = cpufreq_frequency_table_cpuinfo(policy, freq_table);
        if (result)
                goto fail_table;
index c0e816468e300f242735f4825d09b9d291a9b522..1a40935c85fdcc1f21e976ad8dbd5298a87d6060 100644 (file)
@@ -35,7 +35,6 @@
 #include <linux/slab.h>
 #include <linux/string.h>
 #include <linux/cpumask.h>
-#include <linux/sched.h>       /* for current / set_cpus_allowed() */
 #include <linux/io.h>
 #include <linux/delay.h>
 
@@ -1139,16 +1138,23 @@ static int transition_frequency_pstate(struct powernow_k8_data *data,
        return res;
 }
 
-/* Driver entry point to switch to the target frequency */
-static int powernowk8_target(struct cpufreq_policy *pol,
-               unsigned targfreq, unsigned relation)
+struct powernowk8_target_arg {
+       struct cpufreq_policy           *pol;
+       unsigned                        targfreq;
+       unsigned                        relation;
+};
+
+static long powernowk8_target_fn(void *arg)
 {
-       cpumask_var_t oldmask;
+       struct powernowk8_target_arg *pta = arg;
+       struct cpufreq_policy *pol = pta->pol;
+       unsigned targfreq = pta->targfreq;
+       unsigned relation = pta->relation;
        struct powernow_k8_data *data = per_cpu(powernow_data, pol->cpu);
        u32 checkfid;
        u32 checkvid;
        unsigned int newstate;
-       int ret = -EIO;
+       int ret;
 
        if (!data)
                return -EINVAL;
@@ -1156,29 +1162,16 @@ static int powernowk8_target(struct cpufreq_policy *pol,
        checkfid = data->currfid;
        checkvid = data->currvid;
 
-       /* only run on specific CPU from here on. */
-       /* This is poor form: use a workqueue or smp_call_function_single */
-       if (!alloc_cpumask_var(&oldmask, GFP_KERNEL))
-               return -ENOMEM;
-
-       cpumask_copy(oldmask, tsk_cpus_allowed(current));
-       set_cpus_allowed_ptr(current, cpumask_of(pol->cpu));
-
-       if (smp_processor_id() != pol->cpu) {
-               printk(KERN_ERR PFX "limiting to cpu %u failed\n", pol->cpu);
-               goto err_out;
-       }
-
        if (pending_bit_stuck()) {
                printk(KERN_ERR PFX "failing targ, change pending bit set\n");
-               goto err_out;
+               return -EIO;
        }
 
        pr_debug("targ: cpu %d, %d kHz, min %d, max %d, relation %d\n",
                pol->cpu, targfreq, pol->min, pol->max, relation);
 
        if (query_current_values_with_pending_wait(data))
-               goto err_out;
+               return -EIO;
 
        if (cpu_family != CPU_HW_PSTATE) {
                pr_debug("targ: curr fid 0x%x, vid 0x%x\n",
@@ -1196,7 +1189,7 @@ static int powernowk8_target(struct cpufreq_policy *pol,
 
        if (cpufreq_frequency_table_target(pol, data->powernow_table,
                                targfreq, relation, &newstate))
-               goto err_out;
+               return -EIO;
 
        mutex_lock(&fidvid_mutex);
 
@@ -1209,9 +1202,8 @@ static int powernowk8_target(struct cpufreq_policy *pol,
                ret = transition_frequency_fidvid(data, newstate);
        if (ret) {
                printk(KERN_ERR PFX "transition frequency failed\n");
-               ret = 1;
                mutex_unlock(&fidvid_mutex);
-               goto err_out;
+               return 1;
        }
        mutex_unlock(&fidvid_mutex);
 
@@ -1220,12 +1212,25 @@ static int powernowk8_target(struct cpufreq_policy *pol,
                                data->powernow_table[newstate].index);
        else
                pol->cur = find_khz_freq_from_fid(data->currfid);
-       ret = 0;
 
-err_out:
-       set_cpus_allowed_ptr(current, oldmask);
-       free_cpumask_var(oldmask);
-       return ret;
+       return 0;
+}
+
+/* Driver entry point to switch to the target frequency */
+static int powernowk8_target(struct cpufreq_policy *pol,
+               unsigned targfreq, unsigned relation)
+{
+       struct powernowk8_target_arg pta = { .pol = pol, .targfreq = targfreq,
+                                            .relation = relation };
+
+       /*
+        * Must run on @pol->cpu.  cpufreq core is responsible for ensuring
+        * that we're bound to the current CPU and pol->cpu stays online.
+        */
+       if (smp_processor_id() == pol->cpu)
+               return powernowk8_target_fn(&pta);
+       else
+               return work_on_cpu(pol->cpu, powernowk8_target_fn, &pta);
 }
 
 /* Driver entry point to verify the policy and range of frequencies */
index 53c8c51d58817cb62b4641d5e923bb4f72b39f2f..93d14070141ae64fe4e96dd838fc28c36061b3cf 100644 (file)
@@ -63,7 +63,7 @@ static void caam_jr_dequeue(unsigned long devarg)
 
                head = ACCESS_ONCE(jrp->head);
 
-               spin_lock_bh(&jrp->outlock);
+               spin_lock(&jrp->outlock);
 
                sw_idx = tail = jrp->tail;
                hw_idx = jrp->out_ring_read_index;
@@ -115,7 +115,7 @@ static void caam_jr_dequeue(unsigned long devarg)
                        jrp->tail = tail;
                }
 
-               spin_unlock_bh(&jrp->outlock);
+               spin_unlock(&jrp->outlock);
 
                /* Finally, execute user's callback */
                usercall(dev, userdesc, userstatus, userarg);
@@ -236,14 +236,14 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
                return -EIO;
        }
 
-       spin_lock(&jrp->inplock);
+       spin_lock_bh(&jrp->inplock);
 
        head = jrp->head;
        tail = ACCESS_ONCE(jrp->tail);
 
        if (!rd_reg32(&jrp->rregs->inpring_avail) ||
            CIRC_SPACE(head, tail, JOBR_DEPTH) <= 0) {
-               spin_unlock(&jrp->inplock);
+               spin_unlock_bh(&jrp->inplock);
                dma_unmap_single(dev, desc_dma, desc_size, DMA_TO_DEVICE);
                return -EBUSY;
        }
@@ -265,7 +265,7 @@ int caam_jr_enqueue(struct device *dev, u32 *desc,
 
        wr_reg32(&jrp->rregs->inpring_jobadd, 1);
 
-       spin_unlock(&jrp->inplock);
+       spin_unlock_bh(&jrp->inplock);
 
        return 0;
 }
index 002888185f170e92fa798233a40c64ef2258d42c..d216cd3cc569ecdbf195f45b055a5489470f0b70 100644 (file)
@@ -120,3 +120,4 @@ u32 gen_split_key(struct device *jrdev, u8 *key_out, int split_key_len,
 
        return ret;
 }
+EXPORT_SYMBOL(gen_split_key);
index c9c4befb5a8d261701698c570c668d5009113a64..df14358d7fa1658c48e10d8b7a768f32eec6b9ac 100644 (file)
@@ -821,8 +821,8 @@ static int hifn_register_rng(struct hifn_device *dev)
        /*
         * We must wait at least 256 Pk_clk cycles between two reads of the rng.
         */
-       dev->rng_wait_time      = DIV_ROUND_UP(NSEC_PER_SEC, dev->pk_clk_freq) *
-                                 256;
+       dev->rng_wait_time      = DIV_ROUND_UP_ULL(NSEC_PER_SEC,
+                                                  dev->pk_clk_freq) * 256;
 
        dev->rng.name           = dev->name;
        dev->rng.data_present   = hifn_rng_data_present,
index 3934fcc4e00b1b02778bb02866fb86073f9b1f0a..7ab6e26664a77a1ab2b375148488d1209e2e21ba 100644 (file)
@@ -661,7 +661,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
                        flags);
 
        if (unlikely(!atslave || !sg_len)) {
-               dev_dbg(chan2dev(chan), "prep_dma_memcpy: length is zero!\n");
+               dev_dbg(chan2dev(chan), "prep_slave_sg: sg length is zero!\n");
                return NULL;
        }
 
@@ -689,6 +689,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
+                       if (unlikely(!len)) {
+                               dev_dbg(chan2dev(chan),
+                                       "prep_slave_sg: sg(%d) data length is zero\n", i);
+                               goto err;
+                       }
                        mem_width = 2;
                        if (unlikely(mem & 3 || len & 3))
                                mem_width = 0;
@@ -724,6 +729,11 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
                        mem = sg_dma_address(sg);
                        len = sg_dma_len(sg);
+                       if (unlikely(!len)) {
+                               dev_dbg(chan2dev(chan),
+                                       "prep_slave_sg: sg(%d) data length is zero\n", i);
+                               goto err;
+                       }
                        mem_width = 2;
                        if (unlikely(mem & 3 || len & 3))
                                mem_width = 0;
@@ -757,6 +767,7 @@ atc_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
 
 err_desc_get:
        dev_err(chan2dev(chan), "not enough descriptors available\n");
+err:
        atc_desc_put(atchan, first);
        return NULL;
 }
index e4feba6b03c00e6f2ae412a9a1104eef21fb94f4..f5843bc80baa9b8168f6034ad167ce46a0d537bb 100644 (file)
@@ -1567,17 +1567,19 @@ static int pl330_submit_req(void *ch_id, struct pl330_req *r)
                goto xfer_exit;
        }
 
-       /* Prefer Secure Channel */
-       if (!_manager_ns(thrd))
-               r->cfg->nonsecure = 0;
-       else
-               r->cfg->nonsecure = 1;
 
        /* Use last settings, if not provided */
-       if (r->cfg)
+       if (r->cfg) {
+               /* Prefer Secure Channel */
+               if (!_manager_ns(thrd))
+                       r->cfg->nonsecure = 0;
+               else
+                       r->cfg->nonsecure = 1;
+
                ccr = _prepare_ccr(r->cfg);
-       else
+       } else {
                ccr = readl(regs + CC(thrd->id));
+       }
 
        /* If this req doesn't have valid xfer settings */
        if (!_is_valid(ccr)) {
@@ -2928,6 +2930,11 @@ pl330_probe(struct amba_device *adev, const struct amba_id *id)
                num_chan = max_t(int, pi->pcfg.num_peri, pi->pcfg.num_chan);
 
        pdmac->peripherals = kzalloc(num_chan * sizeof(*pch), GFP_KERNEL);
+       if (!pdmac->peripherals) {
+               ret = -ENOMEM;
+               dev_err(&adev->dev, "unable to allocate pdmac->peripherals\n");
+               goto probe_err5;
+       }
 
        for (i = 0; i < num_chan; i++) {
                pch = &pdmac->peripherals[i];
index 616d90bcb3a4106929523c4a98fe32fb27f6a9a6..d5dc9da7f99f95fc9dd3a6edb5d4bc302e69c2c3 100644 (file)
@@ -199,6 +199,36 @@ void *edac_align_ptr(void **p, unsigned size, int n_elems)
        return (void *)(((unsigned long)ptr) + align - r);
 }
 
+static void _edac_mc_free(struct mem_ctl_info *mci)
+{
+       int i, chn, row;
+       struct csrow_info *csr;
+       const unsigned int tot_dimms = mci->tot_dimms;
+       const unsigned int tot_channels = mci->num_cschannel;
+       const unsigned int tot_csrows = mci->nr_csrows;
+
+       if (mci->dimms) {
+               for (i = 0; i < tot_dimms; i++)
+                       kfree(mci->dimms[i]);
+               kfree(mci->dimms);
+       }
+       if (mci->csrows) {
+               for (row = 0; row < tot_csrows; row++) {
+                       csr = mci->csrows[row];
+                       if (csr) {
+                               if (csr->channels) {
+                                       for (chn = 0; chn < tot_channels; chn++)
+                                               kfree(csr->channels[chn]);
+                                       kfree(csr->channels);
+                               }
+                               kfree(csr);
+                       }
+               }
+               kfree(mci->csrows);
+       }
+       kfree(mci);
+}
+
 /**
  * edac_mc_alloc: Allocate and partially fill a struct mem_ctl_info structure
  * @mc_num:            Memory controller number
@@ -413,24 +443,7 @@ struct mem_ctl_info *edac_mc_alloc(unsigned mc_num,
        return mci;
 
 error:
-       if (mci->dimms) {
-               for (i = 0; i < tot_dimms; i++)
-                       kfree(mci->dimms[i]);
-               kfree(mci->dimms);
-       }
-       if (mci->csrows) {
-               for (chn = 0; chn < tot_channels; chn++) {
-                       csr = mci->csrows[chn];
-                       if (csr) {
-                               for (chn = 0; chn < tot_channels; chn++)
-                                       kfree(csr->channels[chn]);
-                               kfree(csr);
-                       }
-                       kfree(mci->csrows[i]);
-               }
-               kfree(mci->csrows);
-       }
-       kfree(mci);
+       _edac_mc_free(mci);
 
        return NULL;
 }
@@ -445,6 +458,14 @@ void edac_mc_free(struct mem_ctl_info *mci)
 {
        edac_dbg(1, "\n");
 
+       /* If we're not yet registered with sysfs free only what was allocated
+        * in edac_mc_alloc().
+        */
+       if (!device_is_registered(&mci->dev)) {
+               _edac_mc_free(mci);
+               return;
+       }
+
        /* the mci instance is freed here, when the sysfs object is dropped */
        edac_unregister_sysfs(mci);
 }
index 47180a08edad28c7c95fea0cd51e9b7b15172f27..b6653a6fc5d56af68e55b0f2ea10855a1927ee2f 100644 (file)
@@ -391,7 +391,7 @@ static int i3200_probe1(struct pci_dev *pdev, int dev_idx)
                for (j = 0; j < nr_channels; j++) {
                        struct dimm_info *dimm = csrow->channels[j]->dimm;
 
-                       dimm->nr_pages = nr_pages / nr_channels;
+                       dimm->nr_pages = nr_pages;
                        dimm->grain = nr_pages << PAGE_SHIFT;
                        dimm->mtype = MEM_DDR2;
                        dimm->dtype = DEV_UNKNOWN;
index 39c63757c2a14fd7bc988c23d7ee6be2e84d0a06..6a49dd00b81b8fce1181a0e0d436bb8e4ce211d5 100644 (file)
@@ -1012,6 +1012,10 @@ static void handle_channel(struct i5000_pvt *pvt, int slot, int channel,
                        /* add the number of COLUMN bits */
                        addrBits += MTR_DIMM_COLS_ADDR_BITS(mtr);
 
+                       /* Dual-rank memories have twice the size */
+                       if (dinfo->dual_rank)
+                               addrBits++;
+
                        addrBits += 6;  /* add 64 bits per DIMM */
                        addrBits -= 20; /* divide by 2^^20 */
                        addrBits -= 3;  /* 8 bits per bytes */
index f3b1f9fafa4b20b4f40917bcbab827ad760515df..5715b7c2c5177a6c76ed732fb6f20de9b7578220 100644 (file)
@@ -513,7 +513,8 @@ static int get_dimm_config(struct mem_ctl_info *mci)
 {
        struct sbridge_pvt *pvt = mci->pvt_info;
        struct dimm_info *dimm;
-       int i, j, banks, ranks, rows, cols, size, npages;
+       unsigned i, j, banks, ranks, rows, cols, npages;
+       u64 size;
        u32 reg;
        enum edac_type mode;
        enum mem_type mtype;
@@ -585,10 +586,10 @@ static int get_dimm_config(struct mem_ctl_info *mci)
                                cols = numcol(mtr);
 
                                /* DDR3 has 8 I/O banks */
-                               size = (rows * cols * banks * ranks) >> (20 - 3);
+                               size = ((u64)rows * cols * banks * ranks) >> (20 - 3);
                                npages = MiB_TO_PAGES(size);
 
-                               edac_dbg(0, "mc#%d: channel %d, dimm %d, %d Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
+                               edac_dbg(0, "mc#%d: channel %d, dimm %d, %Ld Mb (%d pages) bank: %d, rank: %d, row: %#x, col: %#x\n",
                                         pvt->sbridge_dev->mc, i, j,
                                         size, npages,
                                         banks, ranks, rows, cols);
index 920a609b2c35857c2fa64c8341ad6561fe6f7d65..38f9e52f358b17596b8b41177d6af493d509f84b 100644 (file)
@@ -669,13 +669,18 @@ static int __devinit max77693_muic_probe(struct platform_device *pdev)
        }
        info->dev = &pdev->dev;
        info->max77693 = max77693;
-       info->max77693->regmap_muic = regmap_init_i2c(info->max77693->muic,
-                                        &max77693_muic_regmap_config);
-       if (IS_ERR(info->max77693->regmap_muic)) {
-               ret = PTR_ERR(info->max77693->regmap_muic);
-               dev_err(max77693->dev,
-                       "failed to allocate register map: %d\n", ret);
-               goto err_regmap;
+       if (info->max77693->regmap_muic)
+               dev_dbg(&pdev->dev, "allocate register map\n");
+       else {
+               info->max77693->regmap_muic = devm_regmap_init_i2c(
+                                               info->max77693->muic,
+                                               &max77693_muic_regmap_config);
+               if (IS_ERR(info->max77693->regmap_muic)) {
+                       ret = PTR_ERR(info->max77693->regmap_muic);
+                       dev_err(max77693->dev,
+                               "failed to allocate register map: %d\n", ret);
+                       goto err_regmap;
+               }
        }
        platform_set_drvdata(pdev, info);
        mutex_init(&info->mutex);
index b16c8a72a2e241a8a47c524564a02c48a5389b35..ba7926f5c0996ea78f571ab5e87de2a3aa2c490e 100644 (file)
@@ -294,7 +294,7 @@ config GPIO_MAX732X_IRQ
 
 config GPIO_MC9S08DZ60
        bool "MX35 3DS BOARD MC9S08DZ60 GPIO functions"
-       depends on I2C && MACH_MX35_3DS
+       depends on I2C=y && MACH_MX35_3DS
        help
          Select this to enable the MC9S08DZ60 GPIO driver
 
index e4cc7eb69bb2488e36c3db104feab9858fa6a764..92d555d5c25aad4c7a4df39a4ce772b8a448ed3c 100644 (file)
@@ -50,7 +50,7 @@
 #include <linux/slab.h>
 
 /* Steal the hardware definitions from the bttv driver. */
-#include "../media/video/bt8xx/bt848.h"
+#include "../media/pci/bt8xx/bt848.h"
 
 
 #define BT8XXGPIO_NR_GPIOS             24 /* We have 24 GPIO pins */
index ae37181798b3c979d9ce423a437f7ba09511166a..ec48ed5126284d4f41303a5ac4e654f856ca4b7a 100644 (file)
@@ -247,9 +247,9 @@ static int __devinit em_gio_irq_domain_init(struct em_gio_priv *p)
 
        p->irq_base = irq_alloc_descs(pdata->irq_base, 0,
                                      pdata->number_of_pins, numa_node_id());
-       if (IS_ERR_VALUE(p->irq_base)) {
+       if (p->irq_base < 0) {
                dev_err(&pdev->dev, "cannot get irq_desc\n");
-               return -ENXIO;
+               return p->irq_base;
        }
        pr_debug("gio: hw base = %d, nr = %d, sw base = %d\n",
                 pdata->gpio_base, pdata->number_of_pins, p->irq_base);
index 8a420f13905e814bc9e76672941d64fd31ab57f2..ed94b4ea72e9324cdc70a1ad4551f0e85fca89d0 100644 (file)
@@ -308,6 +308,7 @@ static int lpc32xx_gpio_dir_output_p012(struct gpio_chip *chip, unsigned pin,
 {
        struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
 
+       __set_gpio_level_p012(group, pin, value);
        __set_gpio_dir_p012(group, pin, 0);
 
        return 0;
@@ -318,6 +319,7 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
 {
        struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
 
+       __set_gpio_level_p3(group, pin, value);
        __set_gpio_dir_p3(group, pin, 0);
 
        return 0;
@@ -326,6 +328,9 @@ static int lpc32xx_gpio_dir_output_p3(struct gpio_chip *chip, unsigned pin,
 static int lpc32xx_gpio_dir_out_always(struct gpio_chip *chip, unsigned pin,
        int value)
 {
+       struct lpc32xx_gpio_chip *group = to_lpc32xx_gpio(chip);
+
+       __set_gpo_level_p3(group, pin, value);
        return 0;
 }
 
index e97016af64434e292db5025240295fa3d1859dd6..b62d443e9a59125518289229b0a90c6d58503363 100644 (file)
@@ -170,6 +170,7 @@ static int __devinit rdc321x_gpio_probe(struct platform_device *pdev)
        rdc321x_gpio_dev->reg2_data_base = r->start + 0x4;
 
        rdc321x_gpio_dev->chip.label = "rdc321x-gpio";
+       rdc321x_gpio_dev->chip.owner = THIS_MODULE;
        rdc321x_gpio_dev->chip.direction_input = rdc_gpio_direction_input;
        rdc321x_gpio_dev->chip.direction_output = rdc_gpio_config;
        rdc321x_gpio_dev->chip.get = rdc_gpio_get_value;
index a18c4aa68b1e8dcfadd5340e3f076bf33ecb788f..f1a45997aea8c3255aa7ecb697c72abe0beaf6d0 100644 (file)
@@ -82,7 +82,7 @@ int of_get_named_gpio_flags(struct device_node *np, const char *propname,
        gpiochip_find(&gg_data, of_gpiochip_find_and_xlate);
 
        of_node_put(gg_data.gpiospec.np);
-       pr_debug("%s exited with status %d\n", __func__, ret);
+       pr_debug("%s exited with status %d\n", __func__, gg_data.out_gpio);
        return gg_data.out_gpio;
 }
 EXPORT_SYMBOL(of_get_named_gpio_flags);
index d0c4574ef49c1d60b074643b278580a72ff8dc69..36164806b9d475aabff5165f47d481c8a93ce644 100644 (file)
@@ -193,6 +193,9 @@ static const struct file_operations ast_fops = {
        .mmap = ast_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .read = drm_read,
 };
 
index 7282c081fb53000397346d6c34879c06f940a4bd..a712cafcfa1dfde6f76e5c94a77307b7c1f1041a 100644 (file)
@@ -841,7 +841,7 @@ int ast_cursor_init(struct drm_device *dev)
 
        ast->cursor_cache = obj;
        ast->cursor_cache_gpu_addr = gpu_addr;
-       DRM_ERROR("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);
+       DRM_DEBUG_KMS("pinned cursor cache at %llx\n", ast->cursor_cache_gpu_addr);
        return 0;
 fail:
        return ret;
index 7053140c65969758f9f22ded7cea130fe0ab7bd5..b83a2d7ddd1ae8ec04ae0df1b1e647fbc1e327af 100644 (file)
@@ -74,6 +74,9 @@ static const struct file_operations cirrus_driver_fops = {
        .unlocked_ioctl = drm_ioctl,
        .mmap = cirrus_mmap,
        .poll = drm_poll,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .fasync = drm_fasync,
 };
 static struct drm_driver driver = {
index 08a7aa722d6b8f0d798b7a59ccd5b8146183f497..6fbfc244748fd9f5e23e05c90d57bcfbdead4b6b 100644 (file)
@@ -1981,7 +1981,7 @@ int drm_mode_cursor_ioctl(struct drm_device *dev,
        if (!drm_core_check_feature(dev, DRIVER_MODESET))
                return -EINVAL;
 
-       if (!req->flags)
+       if (!req->flags || (~DRM_MODE_CURSOR_FLAGS & req->flags))
                return -EINVAL;
 
        mutex_lock(&dev->mode_config.mutex);
index a8743c399e83234c976ebdb4b471542a0645c42d..b7ee230572b7c053a20c6bf115d4fd98a836f820 100644 (file)
@@ -87,6 +87,9 @@ static struct edid_quirk {
        int product_id;
        u32 quirks;
 } edid_quirk_list[] = {
+       /* ASUS VW222S */
+       { "ACI", 0x22a2, EDID_QUIRK_FORCE_REDUCED_BLANKING },
+
        /* Acer AL1706 */
        { "ACR", 44358, EDID_QUIRK_PREFER_LARGE_60 },
        /* Acer F51 */
index 7f5096763b7d387c25713d7e9ee95e17ce90f7d6..59a26e577b57f423077d5a2c86d75364f14b6838 100644 (file)
@@ -36,6 +36,6 @@ config DRM_EXYNOS_VIDI
 
 config DRM_EXYNOS_G2D
        bool "Exynos DRM G2D"
-       depends on DRM_EXYNOS
+       depends on DRM_EXYNOS && !VIDEO_SAMSUNG_S5P_G2D
        help
          Choose this option if you want to use Exynos G2D for DRM.
index 613bf8a5d9b268331779b0f60f43f52a047269de..ae13febe0eaa64e821adf2f5db306e5ebdd07186 100644 (file)
@@ -163,6 +163,12 @@ static void exynos_gem_dmabuf_kunmap(struct dma_buf *dma_buf,
        /* TODO */
 }
 
+static int exynos_gem_dmabuf_mmap(struct dma_buf *dma_buf,
+       struct vm_area_struct *vma)
+{
+       return -ENOTTY;
+}
+
 static struct dma_buf_ops exynos_dmabuf_ops = {
        .map_dma_buf            = exynos_gem_map_dma_buf,
        .unmap_dma_buf          = exynos_gem_unmap_dma_buf,
@@ -170,6 +176,7 @@ static struct dma_buf_ops exynos_dmabuf_ops = {
        .kmap_atomic            = exynos_gem_dmabuf_kmap_atomic,
        .kunmap                 = exynos_gem_dmabuf_kunmap,
        .kunmap_atomic          = exynos_gem_dmabuf_kunmap_atomic,
+       .mmap                   = exynos_gem_dmabuf_mmap,
        .release                = exynos_dmabuf_release,
 };
 
index ebacec6f1e48efef646700c630f02813007eaac0..d07071937453302fc74793c4aecb48a086b8069f 100644 (file)
@@ -160,7 +160,6 @@ static int exynos_drm_open(struct drm_device *dev, struct drm_file *file)
        if (!file_priv)
                return -ENOMEM;
 
-       drm_prime_init_file_private(&file->prime);
        file->driver_priv = file_priv;
 
        return exynos_drm_subdrv_open(dev, file);
@@ -184,7 +183,6 @@ static void exynos_drm_preclose(struct drm_device *dev,
                        e->base.destroy(&e->base);
                }
        }
-       drm_prime_destroy_file_private(&file->prime);
        spin_unlock_irqrestore(&dev->event_lock, flags);
 
        exynos_drm_subdrv_close(dev, file);
@@ -241,6 +239,9 @@ static const struct file_operations exynos_drm_driver_fops = {
        .poll           = drm_poll,
        .read           = drm_read,
        .unlocked_ioctl = drm_ioctl,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .release        = drm_release,
 };
 
index a68d2b313f03cab1d42fae0d362159f6a4f1ba26..b19cd93e70472b325224611d5725614c33f72f83 100644 (file)
@@ -831,11 +831,6 @@ static int __devinit fimd_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to find registers\n");
-               ret = -ENOENT;
-               goto err_clk;
-       }
 
        ctx->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!ctx->regs) {
index d2d88f22a037a8ace36fae877fd45dbf60357b6c..1065e90d09199414585adca93e2e586b9fe215f0 100644 (file)
@@ -129,7 +129,6 @@ struct g2d_runqueue_node {
 struct g2d_data {
        struct device                   *dev;
        struct clk                      *gate_clk;
-       struct resource                 *regs_res;
        void __iomem                    *regs;
        int                             irq;
        struct workqueue_struct         *g2d_workq;
@@ -751,7 +750,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        struct exynos_drm_subdrv *subdrv;
        int ret;
 
-       g2d = kzalloc(sizeof(*g2d), GFP_KERNEL);
+       g2d = devm_kzalloc(&pdev->dev, sizeof(*g2d), GFP_KERNEL);
        if (!g2d) {
                dev_err(dev, "failed to allocate driver data\n");
                return -ENOMEM;
@@ -759,10 +758,8 @@ static int __devinit g2d_probe(struct platform_device *pdev)
 
        g2d->runqueue_slab = kmem_cache_create("g2d_runqueue_slab",
                        sizeof(struct g2d_runqueue_node), 0, 0, NULL);
-       if (!g2d->runqueue_slab) {
-               ret = -ENOMEM;
-               goto err_free_mem;
-       }
+       if (!g2d->runqueue_slab)
+               return -ENOMEM;
 
        g2d->dev = dev;
 
@@ -794,38 +791,26 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        pm_runtime_enable(dev);
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               dev_err(dev, "failed to get I/O memory\n");
-               ret = -ENOENT;
-               goto err_put_clk;
-       }
 
-       g2d->regs_res = request_mem_region(res->start, resource_size(res),
-                                          dev_name(dev));
-       if (!g2d->regs_res) {
-               dev_err(dev, "failed to request I/O memory\n");
-               ret = -ENOENT;
-               goto err_put_clk;
-       }
-
-       g2d->regs = ioremap(res->start, resource_size(res));
+       g2d->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!g2d->regs) {
                dev_err(dev, "failed to remap I/O memory\n");
                ret = -ENXIO;
-               goto err_release_res;
+               goto err_put_clk;
        }
 
        g2d->irq = platform_get_irq(pdev, 0);
        if (g2d->irq < 0) {
                dev_err(dev, "failed to get irq\n");
                ret = g2d->irq;
-               goto err_unmap_base;
+               goto err_put_clk;
        }
 
-       ret = request_irq(g2d->irq, g2d_irq_handler, 0, "drm_g2d", g2d);
+       ret = devm_request_irq(&pdev->dev, g2d->irq, g2d_irq_handler, 0,
+                                                               "drm_g2d", g2d);
        if (ret < 0) {
                dev_err(dev, "irq request failed\n");
-               goto err_unmap_base;
+               goto err_put_clk;
        }
 
        platform_set_drvdata(pdev, g2d);
@@ -838,7 +823,7 @@ static int __devinit g2d_probe(struct platform_device *pdev)
        ret = exynos_drm_subdrv_register(subdrv);
        if (ret < 0) {
                dev_err(dev, "failed to register drm g2d device\n");
-               goto err_free_irq;
+               goto err_put_clk;
        }
 
        dev_info(dev, "The exynos g2d(ver %d.%d) successfully probed\n",
@@ -846,13 +831,6 @@ static int __devinit g2d_probe(struct platform_device *pdev)
 
        return 0;
 
-err_free_irq:
-       free_irq(g2d->irq, g2d);
-err_unmap_base:
-       iounmap(g2d->regs);
-err_release_res:
-       release_resource(g2d->regs_res);
-       kfree(g2d->regs_res);
 err_put_clk:
        pm_runtime_disable(dev);
        clk_put(g2d->gate_clk);
@@ -862,8 +840,6 @@ err_destroy_workqueue:
        destroy_workqueue(g2d->g2d_workq);
 err_destroy_slab:
        kmem_cache_destroy(g2d->runqueue_slab);
-err_free_mem:
-       kfree(g2d);
        return ret;
 }
 
@@ -873,24 +849,18 @@ static int __devexit g2d_remove(struct platform_device *pdev)
 
        cancel_work_sync(&g2d->runqueue_work);
        exynos_drm_subdrv_unregister(&g2d->subdrv);
-       free_irq(g2d->irq, g2d);
 
        while (g2d->runqueue_node) {
                g2d_free_runqueue_node(g2d, g2d->runqueue_node);
                g2d->runqueue_node = g2d_get_runqueue_node(g2d);
        }
 
-       iounmap(g2d->regs);
-       release_resource(g2d->regs_res);
-       kfree(g2d->regs_res);
-
        pm_runtime_disable(&pdev->dev);
        clk_put(g2d->gate_clk);
 
        g2d_fini_cmdlist(g2d);
        destroy_workqueue(g2d->g2d_workq);
        kmem_cache_destroy(g2d->runqueue_slab);
-       kfree(g2d);
 
        return 0;
 }
@@ -924,7 +894,7 @@ static int g2d_resume(struct device *dev)
 }
 #endif
 
-SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
+static SIMPLE_DEV_PM_OPS(g2d_pm_ops, g2d_suspend, g2d_resume);
 
 struct platform_driver g2d_driver = {
        .probe          = g2d_probe,
index f9efde40c097b819af24d41ff32162f3191ea632..a38051c95ec4384176ddc5f8bd8937e4270c3fb6 100644 (file)
@@ -122,7 +122,7 @@ fail:
                __free_page(pages[i]);
 
        drm_free_large(pages);
-       return ERR_PTR(PTR_ERR(p));
+       return ERR_CAST(p);
 }
 
 static void exynos_gem_put_pages(struct drm_gem_object *obj,
@@ -662,7 +662,7 @@ int exynos_drm_gem_dumb_create(struct drm_file *file_priv,
         */
 
        args->pitch = args->width * ((args->bpp + 7) / 8);
-       args->size = PAGE_ALIGN(args->pitch * args->height);
+       args->size = args->pitch * args->height;
 
        exynos_gem_obj = exynos_drm_gem_create(dev, args->flags, args->size);
        if (IS_ERR(exynos_gem_obj))
index 8ffcdf8b9e223ffdfe7552aa1d57b4334cba19cc..3fdf0b65f47e6659b820d1fa343005b682e354b1 100644 (file)
@@ -345,7 +345,7 @@ static int __devinit exynos_drm_hdmi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                DRM_LOG_KMS("failed to alloc common hdmi context.\n");
                return -ENOMEM;
@@ -371,7 +371,6 @@ static int __devexit exynos_drm_hdmi_remove(struct platform_device *pdev)
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
        exynos_drm_subdrv_unregister(&ctx->subdrv);
-       kfree(ctx);
 
        return 0;
 }
index b89829e5043a59a67152c5cafc241265f0183f12..e1f94b746bd7e0a9419e40ce694bf55e1bff36ab 100644 (file)
@@ -29,7 +29,6 @@ static const uint32_t formats[] = {
        DRM_FORMAT_XRGB8888,
        DRM_FORMAT_ARGB8888,
        DRM_FORMAT_NV12,
-       DRM_FORMAT_NV12M,
        DRM_FORMAT_NV12MT,
 };
 
index bb1550c4dd57db37554954537ef19c61d4e513ce..537027a74fd54f06b49c1387c1650bf90abc11f1 100644 (file)
@@ -633,7 +633,7 @@ static int __devinit vidi_probe(struct platform_device *pdev)
 
        DRM_DEBUG_KMS("%s\n", __FILE__);
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&pdev->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -673,8 +673,6 @@ static int __devexit vidi_remove(struct platform_device *pdev)
                ctx->raw_edid = NULL;
        }
 
-       kfree(ctx);
-
        return 0;
 }
 
index 409e2ec1207c3ddbe4ecae65f9fae1498fcd6410..a6aea6f3ea1ab842d8c6d26a5ecb7e606c335f0d 100644 (file)
@@ -2172,7 +2172,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
 
        DRM_DEBUG_KMS("HDMI resource init\n");
 
-       memset(res, 0, sizeof *res);
+       memset(res, 0, sizeof(*res));
 
        /* get clocks, power */
        res->hdmi = clk_get(dev, "hdmi");
@@ -2204,7 +2204,7 @@ static int __devinit hdmi_resources_init(struct hdmi_context *hdata)
        clk_set_parent(res->sclk_hdmi, res->sclk_pixel);
 
        res->regul_bulk = kzalloc(ARRAY_SIZE(supply) *
-               sizeof res->regul_bulk[0], GFP_KERNEL);
+               sizeof(res->regul_bulk[0]), GFP_KERNEL);
        if (!res->regul_bulk) {
                DRM_ERROR("failed to get memory for regulators\n");
                goto fail;
@@ -2243,7 +2243,7 @@ static int hdmi_resources_cleanup(struct hdmi_context *hdata)
                clk_put(res->sclk_hdmi);
        if (!IS_ERR_OR_NULL(res->hdmi))
                clk_put(res->hdmi);
-       memset(res, 0, sizeof *res);
+       memset(res, 0, sizeof(*res));
 
        return 0;
 }
@@ -2312,11 +2312,6 @@ static int __devinit hdmi_probe(struct platform_device *pdev)
        }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       if (!res) {
-               DRM_ERROR("failed to find registers\n");
-               ret = -ENOENT;
-               goto err_resource;
-       }
 
        hdata->regs = devm_request_and_ioremap(&pdev->dev, res);
        if (!hdata->regs) {
index 30fcc12f81dd943802031936dcfc9ea81b8f1548..25b97d5e5fcb44679a331b8e8e5b1a9da7d7d3ca 100644 (file)
@@ -236,11 +236,11 @@ static inline void vp_filter_set(struct mixer_resources *res,
 static void vp_default_filter(struct mixer_resources *res)
 {
        vp_filter_set(res, VP_POLY8_Y0_LL,
-               filter_y_horiz_tap8, sizeof filter_y_horiz_tap8);
+               filter_y_horiz_tap8, sizeof(filter_y_horiz_tap8));
        vp_filter_set(res, VP_POLY4_Y0_LL,
-               filter_y_vert_tap4, sizeof filter_y_vert_tap4);
+               filter_y_vert_tap4, sizeof(filter_y_vert_tap4));
        vp_filter_set(res, VP_POLY4_C0_LL,
-               filter_cr_horiz_tap4, sizeof filter_cr_horiz_tap4);
+               filter_cr_horiz_tap4, sizeof(filter_cr_horiz_tap4));
 }
 
 static void mixer_vsync_set_update(struct mixer_context *ctx, bool enable)
index 0f9b7db80f6bdc91193ef7bd914a580e2b5eec26..cf49ba5a54bf3a351b4bda14c8fd3d4daf26df73 100644 (file)
@@ -476,6 +476,7 @@ static const struct psb_offset oaktrail_regmap[2] = {
                .pos = DSPAPOS,
                .surf = DSPASURF,
                .addr = MRST_DSPABASE,
+               .base = MRST_DSPABASE,
                .status = PIPEASTAT,
                .linoff = DSPALINOFF,
                .tileoff = DSPATILEOFF,
@@ -499,6 +500,7 @@ static const struct psb_offset oaktrail_regmap[2] = {
                .pos = DSPBPOS,
                .surf = DSPBSURF,
                .addr = DSPBBASE,
+               .base = DSPBBASE,
                .status = PIPEBSTAT,
                .linoff = DSPBLINOFF,
                .tileoff = DSPBTILEOFF,
index 30dc22a7156ce88446d1a11ff2d484c2581c82e6..8033526bb53b98fd84e197f8b57a5b340cc45bd6 100644 (file)
@@ -1362,6 +1362,9 @@ void psb_intel_crtc_init(struct drm_device *dev, int pipe,
            (struct drm_connector **) (psb_intel_crtc + 1);
        psb_intel_crtc->mode_set.num_connectors = 0;
        psb_intel_cursor_init(dev, psb_intel_crtc);
+
+       /* Set to true so that the pipe is forced off on initial config. */
+       psb_intel_crtc->active = true;
 }
 
 int psb_intel_get_pipe_from_crtc_id(struct drm_device *dev, void *data,
index 57d892eaaa6effc66defdbb890bb9f1b68208515..463ec6871fe998229659eaa82fb8237a57109543 100644 (file)
@@ -115,6 +115,9 @@ static const struct file_operations i810_buffer_fops = {
        .unlocked_ioctl = drm_ioctl,
        .mmap = i810_mmap_buffers,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index f9924ad04d0993d5d6157918082b9d4d5d3ed604..48cfcca2b350122f0b3ed5fdb7e78dee78af8dd6 100644 (file)
@@ -51,6 +51,9 @@ static const struct file_operations i810_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 9cf7dfe022b989a23e02cb8ad45cd2177f956605..914c0dfabe6048113abc150b38e06a107eb33c5b 100644 (file)
@@ -1587,6 +1587,7 @@ int i915_driver_load(struct drm_device *dev, unsigned long flags)
        spin_lock_init(&dev_priv->irq_lock);
        spin_lock_init(&dev_priv->error_lock);
        spin_lock_init(&dev_priv->rps_lock);
+       spin_lock_init(&dev_priv->dpio_lock);
 
        if (IS_IVYBRIDGE(dev) || IS_HASWELL(dev))
                dev_priv->num_pipe = 3;
index 489e2b162b2736b4fc3d43e171ebddb25c66b12e..274d25de521e78c577d5a62456fc812024bbae79 100644 (file)
@@ -3242,7 +3242,8 @@ i915_gem_object_pin(struct drm_i915_gem_object *obj,
 {
        int ret;
 
-       BUG_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT);
+       if (WARN_ON(obj->pin_count == DRM_I915_GEM_OBJECT_MAX_PIN_COUNT))
+               return -EBUSY;
 
        if (obj->gtt_space != NULL) {
                if ((alignment && obj->gtt_offset & (alignment - 1)) ||
index d9a5372ec56f84a76f1e270e1edeb704462ed2e8..60815b861ec2143dc1fdad526232d03bea1158fd 100644 (file)
@@ -72,7 +72,7 @@ int i915_gem_init_aliasing_ppgtt(struct drm_device *dev)
        /* ppgtt PDEs reside in the global gtt pagetable, which has 512*1024
         * entries. For aliasing ppgtt support we just steal them at the end for
         * now. */
-       first_pd_entry_in_global_pt = 512*1024 - I915_PPGTT_PD_ENTRIES;
+       first_pd_entry_in_global_pt = dev_priv->mm.gtt->gtt_total_entries - I915_PPGTT_PD_ENTRIES;
 
        ppgtt = kzalloc(sizeof(*ppgtt), GFP_KERNEL);
        if (!ppgtt)
index 8a3828528b9ddfa9678e7bfbf015bd7acdfdc29d..5249640cce1381c912c76ec73c6658cde12ae95f 100644 (file)
@@ -2700,9 +2700,6 @@ void intel_irq_init(struct drm_device *dev)
                        dev->driver->irq_handler = i8xx_irq_handler;
                        dev->driver->irq_uninstall = i8xx_irq_uninstall;
                } else if (INTEL_INFO(dev)->gen == 3) {
-                       /* IIR "flip pending" means done if this bit is set */
-                       I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
-
                        dev->driver->irq_preinstall = i915_irq_preinstall;
                        dev->driver->irq_postinstall = i915_irq_postinstall;
                        dev->driver->irq_uninstall = i915_irq_uninstall;
index a69a3d0d3acf6c7bc81119342aa830b41c047025..c040aee1341cf2065f1ea91eb1b54fbdf54d96b8 100644 (file)
@@ -1376,7 +1376,8 @@ static void assert_pch_dp_disabled(struct drm_i915_private *dev_priv,
             "PCH DP (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 
-       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & DP_PORT_EN) == 0
+            && (val & DP_PIPEB_SELECT),
             "IBX PCH dp port still using transcoder B\n");
 }
 
@@ -1384,11 +1385,12 @@ static void assert_pch_hdmi_disabled(struct drm_i915_private *dev_priv,
                                     enum pipe pipe, int reg)
 {
        u32 val = I915_READ(reg);
-       WARN(hdmi_pipe_enabled(dev_priv, val, pipe),
+       WARN(hdmi_pipe_enabled(dev_priv, pipe, val),
             "PCH HDMI (0x%08x) enabled on transcoder %c, should be disabled\n",
             reg, pipe_name(pipe));
 
-       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & SDVO_PIPE_B_SELECT),
+       WARN(HAS_PCH_IBX(dev_priv->dev) && (val & PORT_ENABLE) == 0
+            && (val & SDVO_PIPE_B_SELECT),
             "IBX PCH hdmi port still using transcoder B\n");
 }
 
@@ -1404,13 +1406,13 @@ static void assert_pch_ports_disabled(struct drm_i915_private *dev_priv,
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
-       WARN(adpa_pipe_enabled(dev_priv, val, pipe),
+       WARN(adpa_pipe_enabled(dev_priv, pipe, val),
             "PCH VGA enabled on transcoder %c, should be disabled\n",
             pipe_name(pipe));
 
        reg = PCH_LVDS;
        val = I915_READ(reg);
-       WARN(lvds_pipe_enabled(dev_priv, val, pipe),
+       WARN(lvds_pipe_enabled(dev_priv, pipe, val),
             "PCH LVDS enabled on transcoder %c, should be disabled\n",
             pipe_name(pipe));
 
@@ -1872,7 +1874,7 @@ static void disable_pch_hdmi(struct drm_i915_private *dev_priv,
                             enum pipe pipe, int reg)
 {
        u32 val = I915_READ(reg);
-       if (hdmi_pipe_enabled(dev_priv, val, pipe)) {
+       if (hdmi_pipe_enabled(dev_priv, pipe, val)) {
                DRM_DEBUG_KMS("Disabling pch HDMI %x on pipe %d\n",
                              reg, pipe);
                I915_WRITE(reg, val & ~PORT_ENABLE);
@@ -1894,12 +1896,12 @@ static void intel_disable_pch_ports(struct drm_i915_private *dev_priv,
 
        reg = PCH_ADPA;
        val = I915_READ(reg);
-       if (adpa_pipe_enabled(dev_priv, val, pipe))
+       if (adpa_pipe_enabled(dev_priv, pipe, val))
                I915_WRITE(reg, val & ~ADPA_DAC_ENABLE);
 
        reg = PCH_LVDS;
        val = I915_READ(reg);
-       if (lvds_pipe_enabled(dev_priv, val, pipe)) {
+       if (lvds_pipe_enabled(dev_priv, pipe, val)) {
                DRM_DEBUG_KMS("disable lvds on pipe %d val 0x%08x\n", pipe, val);
                I915_WRITE(reg, val & ~LVDS_PORT_EN);
                POSTING_READ(reg);
@@ -4189,12 +4191,6 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
        POSTING_READ(DPLL(pipe));
        udelay(150);
 
-       I915_WRITE(DPLL(pipe), dpll);
-
-       /* Wait for the clocks to stabilize. */
-       POSTING_READ(DPLL(pipe));
-       udelay(150);
-
        /* The LVDS pin pair needs to be on before the DPLLs are enabled.
         * This is an exception to the general rule that mode_set doesn't turn
         * things on.
@@ -4202,6 +4198,12 @@ static void i8xx_update_pll(struct drm_crtc *crtc,
        if (intel_pipe_has_type(crtc, INTEL_OUTPUT_LVDS))
                intel_update_lvds(crtc, clock, adjusted_mode);
 
+       I915_WRITE(DPLL(pipe), dpll);
+
+       /* Wait for the clocks to stabilize. */
+       POSTING_READ(DPLL(pipe));
+       udelay(150);
+
        /* The pixel multiplier can only be updated once the
         * DPLL is enabled and the clocks are stable.
         *
index a6c426afaa7aca46144f5a3710c0ea6f10a46b83..ace757af913366db3e7cff4e670fa9c804c84d08 100644 (file)
@@ -2533,14 +2533,10 @@ intel_dp_init(struct drm_device *dev, int output_reg)
                        break;
        }
 
-       intel_dp_i2c_init(intel_dp, intel_connector, name);
-
        /* Cache some DPCD data in the eDP case */
        if (is_edp(intel_dp)) {
-               bool ret;
                struct edp_power_seq    cur, vbt;
                u32 pp_on, pp_off, pp_div;
-               struct edid *edid;
 
                pp_on = I915_READ(PCH_PP_ON_DELAYS);
                pp_off = I915_READ(PCH_PP_OFF_DELAYS);
@@ -2591,6 +2587,13 @@ intel_dp_init(struct drm_device *dev, int output_reg)
 
                DRM_DEBUG_KMS("backlight on delay %d, off delay %d\n",
                              intel_dp->backlight_on_delay, intel_dp->backlight_off_delay);
+       }
+
+       intel_dp_i2c_init(intel_dp, intel_connector, name);
+
+       if (is_edp(intel_dp)) {
+               bool ret;
+               struct edid *edid;
 
                ironlake_edp_panel_vdd_on(intel_dp);
                ret = intel_dp_get_dpcd(intel_dp);
index 98f602427eb8cb8fe9a8cc975ff1b4128ce68ae6..12dc3308ab8c982f063a4b5b0e7dcc8dd2b3519b 100644 (file)
@@ -609,7 +609,7 @@ static void intel_hdmi_dpms(struct drm_encoder *encoder, int mode)
        u32 temp;
        u32 enable_bits = SDVO_ENABLE;
 
-       if (intel_hdmi->has_audio)
+       if (intel_hdmi->has_audio || mode != DRM_MODE_DPMS_ON)
                enable_bits |= SDVO_AUDIO_ENABLE;
 
        temp = I915_READ(intel_hdmi->sdvox_reg);
index e05c0d3e3440f1398f85806f00203998bbfc24ce..e9a6f6aaed855dfa5acad6026c0f95e79a33955e 100644 (file)
@@ -780,6 +780,14 @@ static const struct dmi_system_id intel_no_lvds[] = {
                        DMI_MATCH(DMI_BOARD_NAME, "ZBOXSD-ID12/ID13"),
                },
        },
+       {
+               .callback = intel_no_lvds_dmi_callback,
+               .ident = "Gigabyte GA-D525TUD",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_VENDOR, "Gigabyte Technology Co., Ltd."),
+                       DMI_MATCH(DMI_BOARD_NAME, "D525TUD"),
+               },
+       },
 
        { }     /* terminating entry */
 };
index 3df4f5fa892ad847b394c2050e8956779473afd8..e019b236986128bae46c61bf49180f7ec2502a0d 100644 (file)
@@ -162,19 +162,12 @@ static u32 i915_read_blc_pwm_ctl(struct drm_i915_private *dev_priv)
        return val;
 }
 
-u32 intel_panel_get_max_backlight(struct drm_device *dev)
+static u32 _intel_panel_get_max_backlight(struct drm_device *dev)
 {
        struct drm_i915_private *dev_priv = dev->dev_private;
        u32 max;
 
        max = i915_read_blc_pwm_ctl(dev_priv);
-       if (max == 0) {
-               /* XXX add code here to query mode clock or hardware clock
-                * and program max PWM appropriately.
-                */
-               pr_warn_once("fixme: max PWM is zero\n");
-               return 1;
-       }
 
        if (HAS_PCH_SPLIT(dev)) {
                max >>= 16;
@@ -188,6 +181,22 @@ u32 intel_panel_get_max_backlight(struct drm_device *dev)
                        max *= 0xff;
        }
 
+       return max;
+}
+
+u32 intel_panel_get_max_backlight(struct drm_device *dev)
+{
+       u32 max;
+
+       max = _intel_panel_get_max_backlight(dev);
+       if (max == 0) {
+               /* XXX add code here to query mode clock or hardware clock
+                * and program max PWM appropriately.
+                */
+               pr_warn_once("fixme: max PWM is zero\n");
+               return 1;
+       }
+
        DRM_DEBUG_DRIVER("max backlight PWM = %d\n", max);
        return max;
 }
@@ -424,7 +433,11 @@ int intel_panel_setup_backlight(struct drm_device *dev)
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_RAW;
-       props.max_brightness = intel_panel_get_max_backlight(dev);
+       props.max_brightness = _intel_panel_get_max_backlight(dev);
+       if (props.max_brightness == 0) {
+               DRM_ERROR("Failed to get maximum backlight value\n");
+               return -ENODEV;
+       }
        dev_priv->backlight =
                backlight_device_register("intel_backlight",
                                          &connector->kdev, dev,
index 1881c8c83f0e0c44ab009dfed7049235c4074d97..ba8a27b1757ad97e774fe8266432161477a3561a 100644 (file)
@@ -3672,6 +3672,9 @@ static void gen3_init_clock_gating(struct drm_device *dev)
 
        if (IS_PINEVIEW(dev))
                I915_WRITE(ECOSKPD, _MASKED_BIT_ENABLE(ECO_GATING_CX_ONLY));
+
+       /* IIR "flip pending" means done if this bit is set */
+       I915_WRITE(ECOSKPD, _MASKED_BIT_DISABLE(ECO_FLIP_DONE));
 }
 
 static void i85x_init_clock_gating(struct drm_device *dev)
index d81bb0bf28850f4ea734dedabec44d8478b12d44..123afd357611a6fbbd4c235aa7449afd6ac15dff 100644 (file)
@@ -2573,7 +2573,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                hotplug_mask = intel_sdvo->is_sdvob ?
                        SDVOB_HOTPLUG_INT_STATUS_I915 : SDVOC_HOTPLUG_INT_STATUS_I915;
        }
-       dev_priv->hotplug_supported_mask |= hotplug_mask;
 
        drm_encoder_helper_add(&intel_encoder->base, &intel_sdvo_helper_funcs);
 
@@ -2581,14 +2580,6 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
        if (!intel_sdvo_get_capabilities(intel_sdvo, &intel_sdvo->caps))
                goto err;
 
-       /* Set up hotplug command - note paranoia about contents of reply.
-        * We assume that the hardware is in a sane state, and only touch
-        * the bits we think we understand.
-        */
-       intel_sdvo_get_value(intel_sdvo, SDVO_CMD_GET_ACTIVE_HOT_PLUG,
-                            &intel_sdvo->hotplug_active, 2);
-       intel_sdvo->hotplug_active[0] &= ~0x3;
-
        if (intel_sdvo_output_setup(intel_sdvo,
                                    intel_sdvo->caps.output_flags) != true) {
                DRM_DEBUG_KMS("SDVO output failed to setup on %s\n",
@@ -2596,6 +2587,12 @@ bool intel_sdvo_init(struct drm_device *dev, uint32_t sdvo_reg, bool is_sdvob)
                goto err;
        }
 
+       /* Only enable the hotplug irq if we need it, to work around noisy
+        * hotplug lines.
+        */
+       if (intel_sdvo->hotplug_active[0])
+               dev_priv->hotplug_supported_mask |= hotplug_mask;
+
        intel_sdvo_select_ddc_bus(dev_priv, intel_sdvo, sdvo_reg);
 
        /* Set the input timing to the screen. Assume always input 0. */
index cc8df4de2d921691fdee876b1cdc9b97acb39b8f..7644f31a3778685bb3e21c021e1ad76c5afb2e95 100644 (file)
@@ -60,11 +60,11 @@ ivb_update_plane(struct drm_plane *plane, struct drm_framebuffer *fb,
 
        switch (fb->pixel_format) {
        case DRM_FORMAT_XBGR8888:
-               sprctl |= SPRITE_FORMAT_RGBX888;
+               sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
                pixel_size = 4;
                break;
        case DRM_FORMAT_XRGB8888:
-               sprctl |= SPRITE_FORMAT_RGBX888 | SPRITE_RGB_ORDER_RGBX;
+               sprctl |= SPRITE_FORMAT_RGBX888;
                pixel_size = 4;
                break;
        case DRM_FORMAT_YUYV:
index ea1024d79974a0f05b91c0e763ca6929266f5a72..e5f145d2cb3bac2565051a65cfbb07a8cf206c36 100644 (file)
@@ -84,6 +84,9 @@ static const struct file_operations mgag200_driver_fops = {
        .mmap = mgag200_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .read = drm_read,
 };
 
index ff23d88880e50ab727b6836c4fc7ad6d8860a222..3ca240b4413d48eb9ddf0bdf479db97345397965 100644 (file)
@@ -179,7 +179,7 @@ nouveau_abi16_ioctl_grobj_alloc(ABI16_IOCTL_ARGS)
                        return 0;
        } else
        if (init->class == 0x906e) {
-               NV_ERROR(dev, "906e not supported yet\n");
+               NV_DEBUG(dev, "906e not supported yet\n");
                return -EINVAL;
        }
 
index 69688ef5cf46802d82922046577ada8d27f3a82c..7e16dc5e64672929e80a2aecf4b6e6e2446641b8 100644 (file)
@@ -598,7 +598,7 @@ nouveau_display_dumb_create(struct drm_file *file_priv, struct drm_device *dev,
        args->size = args->pitch * args->height;
        args->size = roundup(args->size, PAGE_SIZE);
 
-       ret = nouveau_gem_new(dev, args->size, 0, TTM_PL_FLAG_VRAM, 0, 0, &bo);
+       ret = nouveau_gem_new(dev, args->size, 0, NOUVEAU_GEM_DOMAIN_VRAM, 0, 0, &bo);
        if (ret)
                return ret;
 
index 1866dbb499792e4e4758938c50802d11beb29bb7..c61014442aa931cfe5822069c7ecf6c0d565f4dc 100644 (file)
@@ -736,9 +736,11 @@ nouveau_card_init(struct drm_device *dev)
                        }
                        break;
                case NV_C0:
-                       nvc0_copy_create(dev, 1);
+                       if (!(nv_rd32(dev, 0x022500) & 0x00000200))
+                               nvc0_copy_create(dev, 1);
                case NV_D0:
-                       nvc0_copy_create(dev, 0);
+                       if (!(nv_rd32(dev, 0x022500) & 0x00000100))
+                               nvc0_copy_create(dev, 0);
                        break;
                default:
                        break;
index f429e6a8ca7aeba09b3f8ef852376ea8d360c4ee..c399d510b27a8611aa4524b3cffa582f9f033da7 100644 (file)
@@ -22,6 +22,7 @@
  * Authors: Ben Skeggs
  */
 
+#include <linux/dmi.h>
 #include "drmP.h"
 #include "nouveau_drv.h"
 #include "nouveau_hw.h"
@@ -110,11 +111,26 @@ nv50_gpio_isr(struct drm_device *dev)
                nv_wr32(dev, 0xe074, intr1);
 }
 
+static struct dmi_system_id gpio_reset_ids[] = {
+       {
+               .ident = "Apple Macbook 10,1",
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "Apple Inc."),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "MacBookPro10,1"),
+               }
+       },
+       { }
+};
+
 int
 nv50_gpio_init(struct drm_device *dev)
 {
        struct drm_nouveau_private *dev_priv = dev->dev_private;
 
+       /* initialise gpios and routing to vbios defaults */
+       if (dmi_check_system(gpio_reset_ids))
+               nouveau_gpio_reset(dev);
+
        /* disable, and ack any pending gpio interrupts */
        nv_wr32(dev, 0xe050, 0x00000000);
        nv_wr32(dev, 0xe054, 0xffffffff);
index f704e942372e75b291cc505536a197c4c464a537..f376c39310dfb11e00a944577aba9209e4481451 100644 (file)
@@ -124,6 +124,7 @@ nvc0_fb_init(struct drm_device *dev)
        priv = dev_priv->engine.fb.priv;
 
        nv_wr32(dev, 0x100c10, priv->r100c10 >> 8);
+       nv_mask(dev, 0x17e820, 0x00100000, 0x00000000); /* NV_PLTCG_INTR_EN */
        return 0;
 }
 
index 7d85553d518c42ee5826c0cf516086cf01ce1534..cd39eb99f5b15b4aef3f9fa4d47967b7bf3f55f6 100644 (file)
@@ -373,7 +373,8 @@ nvc0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
 static void
 nvc0_fifo_isr(struct drm_device *dev)
 {
-       u32 stat = nv_rd32(dev, 0x002100);
+       u32 mask = nv_rd32(dev, 0x002140);
+       u32 stat = nv_rd32(dev, 0x002100) & mask;
 
        if (stat & 0x00000100) {
                NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
index dac525b2994ee4bd28ff862625e7a6fe7649d2cd..8a2fc89b7763cc278c65a2ba20382165cde4a203 100644 (file)
@@ -1510,10 +1510,10 @@ nvd0_sor_mode_set(struct drm_encoder *encoder, struct drm_display_mode *umode,
        case OUTPUT_DP:
                if (nv_connector->base.display_info.bpc == 6) {
                        nv_encoder->dp.datarate = mode->clock * 18 / 8;
-                       syncs |= 0x00000140;
+                       syncs |= 0x00000002 << 6;
                } else {
                        nv_encoder->dp.datarate = mode->clock * 24 / 8;
-                       syncs |= 0x00000180;
+                       syncs |= 0x00000005 << 6;
                }
 
                if (nv_encoder->dcb->sorconf.link & 1)
index e98d144e6eb9df766fc458e03bdd35acef349ce4..281bece751b61eb091d2b6da73144dc9d2ddb5c5 100644 (file)
@@ -345,7 +345,8 @@ nve0_fifo_isr_subfifo_intr(struct drm_device *dev, int unit)
 static void
 nve0_fifo_isr(struct drm_device *dev)
 {
-       u32 stat = nv_rd32(dev, 0x002100);
+       u32 mask = nv_rd32(dev, 0x002140);
+       u32 stat = nv_rd32(dev, 0x002100) & mask;
 
        if (stat & 0x00000100) {
                NV_INFO(dev, "PFIFO: unknown status 0x00000100\n");
index f4d4505fe831b9c60b676b2f761727af6987ac13..2817101fb167eb1f70ac36d88e2f4f1c58dd2427 100644 (file)
@@ -258,7 +258,6 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                radeon_crtc->enabled = true;
                /* adjust pm to dpms changes BEFORE enabling crtcs */
                radeon_pm_compute_clocks(rdev);
-               /* disable crtc pair power gating before programming */
                if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
                        atombios_powergate_crtc(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_ENABLE);
@@ -278,25 +277,8 @@ void atombios_crtc_dpms(struct drm_crtc *crtc, int mode)
                        atombios_enable_crtc_memreq(crtc, ATOM_DISABLE);
                atombios_enable_crtc(crtc, ATOM_DISABLE);
                radeon_crtc->enabled = false;
-               /* power gating is per-pair */
-               if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set) {
-                       struct drm_crtc *other_crtc;
-                       struct radeon_crtc *other_radeon_crtc;
-                       list_for_each_entry(other_crtc, &rdev->ddev->mode_config.crtc_list, head) {
-                               other_radeon_crtc = to_radeon_crtc(other_crtc);
-                               if (((radeon_crtc->crtc_id == 0) && (other_radeon_crtc->crtc_id == 1)) ||
-                                   ((radeon_crtc->crtc_id == 1) && (other_radeon_crtc->crtc_id == 0)) ||
-                                   ((radeon_crtc->crtc_id == 2) && (other_radeon_crtc->crtc_id == 3)) ||
-                                   ((radeon_crtc->crtc_id == 3) && (other_radeon_crtc->crtc_id == 2)) ||
-                                   ((radeon_crtc->crtc_id == 4) && (other_radeon_crtc->crtc_id == 5)) ||
-                                   ((radeon_crtc->crtc_id == 5) && (other_radeon_crtc->crtc_id == 4))) {
-                                       /* if both crtcs in the pair are off, enable power gating */
-                                       if (other_radeon_crtc->enabled == false)
-                                               atombios_powergate_crtc(crtc, ATOM_ENABLE);
-                                       break;
-                               }
-                       }
-               }
+               if (ASIC_IS_DCE6(rdev) && !radeon_crtc->in_mode_set)
+                       atombios_powergate_crtc(crtc, ATOM_ENABLE);
                /* adjust pm to dpms changes AFTER disabling crtcs */
                radeon_pm_compute_clocks(rdev);
                break;
@@ -1682,9 +1664,22 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
        struct drm_device *dev = crtc->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_atom_ss ss;
+       int i;
 
        atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
 
+       for (i = 0; i < rdev->num_crtc; i++) {
+               if (rdev->mode_info.crtcs[i] &&
+                   rdev->mode_info.crtcs[i]->enabled &&
+                   i != radeon_crtc->crtc_id &&
+                   radeon_crtc->pll_id == rdev->mode_info.crtcs[i]->pll_id) {
+                       /* one other crtc is using this pll don't turn
+                        * off the pll
+                        */
+                       goto done;
+               }
+       }
+
        switch (radeon_crtc->pll_id) {
        case ATOM_PPLL1:
        case ATOM_PPLL2:
@@ -1701,6 +1696,7 @@ static void atombios_crtc_disable(struct drm_crtc *crtc)
        default:
                break;
        }
+done:
        radeon_crtc->pll_id = -1;
 }
 
index 7712cf5ab33b9a107ddf6ef61f1122622a358951..3623b98ed3fe2ab529617e37ceb41dfcf4fd5882 100644 (file)
@@ -577,30 +577,25 @@ int radeon_dp_get_panel_mode(struct drm_encoder *encoder,
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_connector *radeon_connector = to_radeon_connector(connector);
        int panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+       u16 dp_bridge = radeon_connector_encoder_get_dp_bridge_encoder_id(connector);
+       u8 tmp;
 
        if (!ASIC_IS_DCE4(rdev))
                return panel_mode;
 
-       if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-           ENCODER_OBJECT_ID_NUTMEG)
-               panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
-       else if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) ==
-                ENCODER_OBJECT_ID_TRAVIS) {
-               u8 id[6];
-               int i;
-               for (i = 0; i < 6; i++)
-                       id[i] = radeon_read_dpcd_reg(radeon_connector, 0x503 + i);
-               if (id[0] == 0x73 &&
-                   id[1] == 0x69 &&
-                   id[2] == 0x76 &&
-                   id[3] == 0x61 &&
-                   id[4] == 0x72 &&
-                   id[5] == 0x54)
+       if (dp_bridge != ENCODER_OBJECT_ID_NONE) {
+               /* DP bridge chips */
+               tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+               if (tmp & 1)
+                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+               else if ((dp_bridge == ENCODER_OBJECT_ID_NUTMEG) ||
+                        (dp_bridge == ENCODER_OBJECT_ID_TRAVIS))
                        panel_mode = DP_PANEL_MODE_INTERNAL_DP1_MODE;
                else
-                       panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
+                       panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
        } else if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
-               u8 tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
+               /* eDP */
+               tmp = radeon_read_dpcd_reg(radeon_connector, DP_EDP_CONFIGURATION_CAP);
                if (tmp & 1)
                        panel_mode = DP_PANEL_MODE_INTERNAL_DP2_MODE;
        }
index f9bc27fe269a125b54803350b838a9062f0e6337..6e8803a1170c24b052a0193ce58294605fed01fd 100644 (file)
@@ -1379,6 +1379,8 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
+       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
        struct radeon_connector *radeon_connector = NULL;
        struct radeon_connector_atom_dig *radeon_dig_connector = NULL;
@@ -1390,19 +1392,37 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
 
        switch (mode) {
        case DRM_MODE_DPMS_ON:
-               /* some early dce3.2 boards have a bug in their transmitter control table */
-               if ((rdev->family == CHIP_RV710) || (rdev->family == CHIP_RV730) ||
-                   ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
-                       if (ASIC_IS_DCE6(rdev)) {
-                               /* It seems we need to call ATOM_ENCODER_CMD_SETUP again
-                                * before reenabling encoder on DPMS ON, otherwise we never
-                                * get picture
-                                */
-                               atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+                       if (!connector)
+                               dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
+                       else
+                               dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
+
+                       /* setup and enable the encoder */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+                       atombios_dig_encoder_setup(encoder,
+                                                  ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
+                                                  dig->panel_mode);
+                       if (ext_encoder) {
+                               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
+                                       atombios_external_encoder_setup(encoder, ext_encoder,
+                                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
                        }
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-               } else {
+               } else if (ASIC_IS_DCE4(rdev)) {
+                       /* setup and enable the encoder */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
+                       /* enable the transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
+               } else {
+                       /* setup and enable the encoder and transmitter */
+                       atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
+                       /* some early dce3.2 boards have a bug in their transmitter control table */
+                       if ((rdev->family != CHIP_RV710) || (rdev->family != CHIP_RV730))
+                               atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE_OUTPUT, 0, 0);
                }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
                        if (connector->connector_type == DRM_MODE_CONNECTOR_eDP) {
@@ -1420,10 +1440,19 @@ radeon_atom_encoder_dpms_dig(struct drm_encoder *encoder, int mode)
        case DRM_MODE_DPMS_STANDBY:
        case DRM_MODE_DPMS_SUSPEND:
        case DRM_MODE_DPMS_OFF:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev))
+               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
+                       /* disable the transmitter */
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-               else
+               } else if (ASIC_IS_DCE4(rdev)) {
+                       /* disable the transmitter */
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+               } else {
+                       /* disable the encoder and transmitter */
                        atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE_OUTPUT, 0, 0);
+                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
+                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
+               }
                if (ENCODER_MODE_IS_DP(atombios_get_encoder_mode(encoder)) && connector) {
                        if (ASIC_IS_DCE4(rdev))
                                atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_DP_VIDEO_OFF, 0);
@@ -1740,13 +1769,34 @@ static int radeon_atom_pick_dig_encoder(struct drm_encoder *encoder)
        struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
        struct drm_encoder *test_encoder;
-       struct radeon_encoder_atom_dig *dig;
+       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
        uint32_t dig_enc_in_use = 0;
 
-       /* DCE4/5 */
-       if (ASIC_IS_DCE4(rdev)) {
-               dig = radeon_encoder->enc_priv;
-               if (ASIC_IS_DCE41(rdev)) {
+       if (ASIC_IS_DCE6(rdev)) {
+               /* DCE6 */
+               switch (radeon_encoder->encoder_id) {
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY:
+                       if (dig->linkb)
+                               return 1;
+                       else
+                               return 0;
+                       break;
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
+                       if (dig->linkb)
+                               return 3;
+                       else
+                               return 2;
+                       break;
+               case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
+                       if (dig->linkb)
+                               return 5;
+                       else
+                               return 4;
+                       break;
+               }
+       } else if (ASIC_IS_DCE4(rdev)) {
+               /* DCE4/5 */
+               if (ASIC_IS_DCE41(rdev) && !ASIC_IS_DCE61(rdev)) {
                        /* ontario follows DCE4 */
                        if (rdev->family == CHIP_PALM) {
                                if (dig->linkb)
@@ -1848,10 +1898,12 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        struct drm_device *dev = encoder->dev;
        struct radeon_device *rdev = dev->dev_private;
        struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
-       struct drm_encoder *ext_encoder = radeon_get_external_encoder(encoder);
 
        radeon_encoder->pixel_clock = adjusted_mode->clock;
 
+       /* need to call this here rather than in prepare() since we need some crtc info */
+       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
+
        if (ASIC_IS_AVIVO(rdev) && !ASIC_IS_DCE4(rdev)) {
                if (radeon_encoder->active_device & (ATOM_DEVICE_CV_SUPPORT | ATOM_DEVICE_TV_SUPPORT))
                        atombios_yuv_setup(encoder, true);
@@ -1870,38 +1922,7 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
-                       struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
-                       struct radeon_encoder_atom_dig *dig = radeon_encoder->enc_priv;
-
-                       if (!connector)
-                               dig->panel_mode = DP_PANEL_MODE_EXTERNAL_DP_MODE;
-                       else
-                               dig->panel_mode = radeon_dp_get_panel_mode(encoder, connector);
-
-                       /* setup and enable the encoder */
-                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-                       atombios_dig_encoder_setup(encoder,
-                                                  ATOM_ENCODER_CMD_SETUP_PANEL_MODE,
-                                                  dig->panel_mode);
-               } else if (ASIC_IS_DCE4(rdev)) {
-                       /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       /* setup and enable the encoder */
-                       atombios_dig_encoder_setup(encoder, ATOM_ENCODER_CMD_SETUP, 0);
-
-                       /* enable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-               } else {
-                       /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-
-                       /* setup and enable the encoder and transmitter */
-                       atombios_dig_encoder_setup(encoder, ATOM_ENABLE, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_SETUP, 0, 0);
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_ENABLE, 0, 0);
-               }
+               /* handled in dpms */
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
@@ -1922,14 +1943,6 @@ radeon_atom_encoder_mode_set(struct drm_encoder *encoder,
                break;
        }
 
-       if (ext_encoder) {
-               if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE61(rdev))
-                       atombios_external_encoder_setup(encoder, ext_encoder,
-                                                       EXTERNAL_ENCODER_ACTION_V3_ENCODER_SETUP);
-               else
-                       atombios_external_encoder_setup(encoder, ext_encoder, ATOM_ENABLE);
-       }
-
        atombios_apply_encoder_quirks(encoder, adjusted_mode);
 
        if (atombios_get_encoder_mode(encoder) == ATOM_ENCODER_MODE_HDMI) {
@@ -2116,7 +2129,6 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
        }
 
        radeon_atom_output_lock(encoder, true);
-       radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_OFF);
 
        if (connector) {
                struct radeon_connector *radeon_connector = to_radeon_connector(connector);
@@ -2137,6 +2149,7 @@ static void radeon_atom_encoder_prepare(struct drm_encoder *encoder)
 
 static void radeon_atom_encoder_commit(struct drm_encoder *encoder)
 {
+       /* need to call this here as we need the crtc set up */
        radeon_atom_encoder_dpms(encoder, DRM_MODE_DPMS_ON);
        radeon_atom_output_lock(encoder, false);
 }
@@ -2177,14 +2190,7 @@ static void radeon_atom_encoder_disable(struct drm_encoder *encoder)
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY1:
        case ENCODER_OBJECT_ID_INTERNAL_UNIPHY2:
        case ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA:
-               if (ASIC_IS_DCE4(rdev))
-                       /* disable the transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-               else {
-                       /* disable the encoder and transmitter */
-                       atombios_dig_transmitter_setup(encoder, ATOM_TRANSMITTER_ACTION_DISABLE, 0, 0);
-                       atombios_dig_encoder_setup(encoder, ATOM_DISABLE, 0);
-               }
+               /* handled in dpms */
                break;
        case ENCODER_OBJECT_ID_INTERNAL_DDI:
        case ENCODER_OBJECT_ID_INTERNAL_DVO1:
index 8acb34fd3fd548aa6e34d999682d0f8fafac95fd..8d7e33a0b243585100839905205a5f11ccab5f06 100644 (file)
@@ -1182,7 +1182,8 @@ int r100_cp_init(struct radeon_device *rdev, unsigned ring_size)
        ring->ready = true;
        radeon_ttm_set_active_vram_size(rdev, rdev->mc.real_vram_size);
 
-       if (radeon_ring_supports_scratch_reg(rdev, ring)) {
+       if (!ring->rptr_save_reg /* not resuming from suspend */
+           && radeon_ring_supports_scratch_reg(rdev, ring)) {
                r = radeon_scratch_get(rdev, &ring->rptr_save_reg);
                if (r) {
                        DRM_ERROR("failed to get scratch reg for rptr save (%d).\n", r);
index ab74e6b149e7468c16f47d0f4e6228abdcf41e14..f37676d7f217c56373ba55e7c883098b5736d1f7 100644 (file)
@@ -63,6 +63,7 @@ struct r600_cs_track {
        u32                     cb_color_size_idx[8]; /* unused */
        u32                     cb_target_mask;
        u32                     cb_shader_mask;  /* unused */
+       bool                    is_resolve;
        u32                     cb_color_size[8];
        u32                     vgt_strmout_en;
        u32                     vgt_strmout_buffer_en;
@@ -315,7 +316,15 @@ static void r600_cs_track_init(struct r600_cs_track *track)
                track->cb_color_bo[i] = NULL;
                track->cb_color_bo_offset[i] = 0xFFFFFFFF;
                track->cb_color_bo_mc[i] = 0xFFFFFFFF;
-       }
+               track->cb_color_frag_bo[i] = NULL;
+               track->cb_color_frag_offset[i] = 0xFFFFFFFF;
+               track->cb_color_tile_bo[i] = NULL;
+               track->cb_color_tile_offset[i] = 0xFFFFFFFF;
+               track->cb_color_mask[i] = 0xFFFFFFFF;
+       }
+       track->is_resolve = false;
+       track->nsamples = 16;
+       track->log_nsamples = 4;
        track->cb_target_mask = 0xFFFFFFFF;
        track->cb_shader_mask = 0xFFFFFFFF;
        track->cb_dirty = true;
@@ -352,6 +361,8 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        volatile u32 *ib = p->ib.ptr;
        unsigned array_mode;
        u32 format;
+       /* When resolve is used, the second colorbuffer has always 1 sample. */
+       unsigned nsamples = track->is_resolve && i == 1 ? 1 : track->nsamples;
 
        size = radeon_bo_size(track->cb_color_bo[i]) - track->cb_color_bo_offset[i];
        format = G_0280A0_FORMAT(track->cb_color_info[i]);
@@ -375,7 +386,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
        array_check.group_size = track->group_size;
        array_check.nbanks = track->nbanks;
        array_check.npipes = track->npipes;
-       array_check.nsamples = track->nsamples;
+       array_check.nsamples = nsamples;
        array_check.blocksize = r600_fmt_get_blocksize(format);
        if (r600_get_array_mode_alignment(&array_check,
                                          &pitch_align, &height_align, &depth_align, &base_align)) {
@@ -421,7 +432,7 @@ static int r600_cs_track_validate_cb(struct radeon_cs_parser *p, int i)
 
        /* check offset */
        tmp = r600_fmt_get_nblocksy(format, height) * r600_fmt_get_nblocksx(format, pitch) *
-             r600_fmt_get_blocksize(format) * track->nsamples;
+             r600_fmt_get_blocksize(format) * nsamples;
        switch (array_mode) {
        default:
        case V_0280A0_ARRAY_LINEAR_GENERAL:
@@ -792,6 +803,12 @@ static int r600_cs_track_check(struct radeon_cs_parser *p)
         */
        if (track->cb_dirty) {
                tmp = track->cb_target_mask;
+
+               /* We must check both colorbuffers for RESOLVE. */
+               if (track->is_resolve) {
+                       tmp |= 0xff;
+               }
+
                for (i = 0; i < 8; i++) {
                        if ((tmp >> (i * 4)) & 0xF) {
                                /* at least one component is enabled */
@@ -1281,6 +1298,11 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
                track->nsamples = 1 << tmp;
                track->cb_dirty = true;
                break;
+       case R_028808_CB_COLOR_CONTROL:
+               tmp = G_028808_SPECIAL_OP(radeon_get_ib_value(p, idx));
+               track->is_resolve = tmp == V_028808_SPECIAL_RESOLVE_BOX;
+               track->cb_dirty = true;
+               break;
        case R_0280A0_CB_COLOR0_INFO:
        case R_0280A4_CB_COLOR1_INFO:
        case R_0280A8_CB_COLOR2_INFO:
@@ -1416,7 +1438,7 @@ static int r600_cs_check_reg(struct radeon_cs_parser *p, u32 reg, u32 idx)
        case R_028118_CB_COLOR6_MASK:
        case R_02811C_CB_COLOR7_MASK:
                tmp = (reg - R_028100_CB_COLOR0_MASK) / 4;
-               track->cb_color_mask[tmp] = ib[idx];
+               track->cb_color_mask[tmp] = radeon_get_ib_value(p, idx);
                if (G_0280A0_TILE_MODE(track->cb_color_info[tmp])) {
                        track->cb_dirty = true;
                }
index bdb69a63062fd72947b924503d5fb201c7e33f00..fa6f37099ba90a6968744f15e4531e7ce3de9d17 100644 (file)
 #define        CC_RB_BACKEND_DISABLE                           0x98F4
 #define                BACKEND_DISABLE(x)                              ((x) << 16)
 
+#define R_028808_CB_COLOR_CONTROL                      0x28808
+#define   S_028808_SPECIAL_OP(x)                       (((x) & 0x7) << 4)
+#define   G_028808_SPECIAL_OP(x)                       (((x) >> 4) & 0x7)
+#define   C_028808_SPECIAL_OP                          0xFFFFFF8F
+#define     V_028808_SPECIAL_NORMAL                     0x00
+#define     V_028808_SPECIAL_DISABLE                    0x01
+#define     V_028808_SPECIAL_RESOLVE_BOX                0x07
+
 #define        CB_COLOR0_BASE                                  0x28040
 #define        CB_COLOR1_BASE                                  0x28044
 #define        CB_COLOR2_BASE                                  0x28048
index d2e243867ac6f3c9fe4d6c28e25fa421cac6c48b..7a3daebd732d67d85d40dc04d6aa851af42aae26 100644 (file)
@@ -1051,7 +1051,7 @@ int radeon_device_init(struct radeon_device *rdev,
        if (rdev->flags & RADEON_IS_AGP)
                rdev->need_dma32 = true;
        if ((rdev->flags & RADEON_IS_PCI) &&
-           (rdev->family < CHIP_RS400))
+           (rdev->family <= CHIP_RS740))
                rdev->need_dma32 = true;
 
        dma_bits = rdev->need_dma32 ? 32 : 40;
@@ -1346,12 +1346,15 @@ retry:
                for (i = 0; i < RADEON_NUM_RINGS; ++i) {
                        radeon_ring_restore(rdev, &rdev->ring[i],
                                            ring_sizes[i], ring_data[i]);
+                       ring_sizes[i] = 0;
+                       ring_data[i] = NULL;
                }
 
                r = radeon_ib_ring_tests(rdev);
                if (r) {
                        dev_err(rdev->dev, "ib ring test failed (%d).\n", r);
                        if (saved) {
+                               saved = false;
                                radeon_suspend(rdev);
                                goto retry;
                        }
index 27d22d709c9040561c61e51013d0418ab3625e31..8c593ea82c412b2098d1c3dac3e1f6167356e6fa 100644 (file)
  *   2.19.0 - r600-eg: MSAA textures
  *   2.20.0 - r600-si: RADEON_INFO_TIMESTAMP query
  *   2.21.0 - r600-r700: FMASK and CMASK
+ *   2.22.0 - r600 only: RESOLVE_BOX allowed
  */
 #define KMS_DRIVER_MAJOR       2
-#define KMS_DRIVER_MINOR       21
+#define KMS_DRIVER_MINOR       22
 #define KMS_DRIVER_PATCHLEVEL  0
 int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags);
 int radeon_driver_unload_kms(struct drm_device *dev);
index 7b737b9339ad41e136a96237817ef099bfae3c10..2a59375dbe5205f64764771de6abfe7184a90be9 100644 (file)
@@ -131,7 +131,7 @@ int radeon_fence_emit(struct radeon_device *rdev,
  */
 void radeon_fence_process(struct radeon_device *rdev, int ring)
 {
-       uint64_t seq, last_seq;
+       uint64_t seq, last_seq, last_emitted;
        unsigned count_loop = 0;
        bool wake = false;
 
@@ -158,13 +158,15 @@ void radeon_fence_process(struct radeon_device *rdev, int ring)
         */
        last_seq = atomic64_read(&rdev->fence_drv[ring].last_seq);
        do {
+               last_emitted = rdev->fence_drv[ring].sync_seq[ring];
                seq = radeon_fence_read(rdev, ring);
                seq |= last_seq & 0xffffffff00000000LL;
                if (seq < last_seq) {
-                       seq += 0x100000000LL;
+                       seq &= 0xffffffff;
+                       seq |= last_emitted & 0xffffffff00000000LL;
                }
 
-               if (seq == last_seq) {
+               if (seq <= last_seq || seq > last_emitted) {
                        break;
                }
                /* If we loop over we don't want to return without
index f93e45d869f401225e853d81d2e9ec44baf092e6..20bfbda7b3f1bdcf0eff27332bf2b9812af696b4 100644 (file)
@@ -744,7 +744,6 @@ r600 0x9400
 0x00028C38 CB_CLRCMP_DST
 0x00028C3C CB_CLRCMP_MSK
 0x00028C34 CB_CLRCMP_SRC
-0x00028808 CB_COLOR_CONTROL
 0x0002842C CB_FOG_BLUE
 0x00028428 CB_FOG_GREEN
 0x00028424 CB_FOG_RED
index d31d4cca9a4c7425609cf92d9e8fcb5a512cc4f0..c5a164337bd5deaf7fd85f15b94f0f8b21fbba88 100644 (file)
@@ -43,6 +43,9 @@ static const struct file_operations savage_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 7f119870147c04cee307eaded5e6bf1abfba2bff..867dc03000e62007f470fc963706369d7411b90c 100644 (file)
@@ -74,6 +74,9 @@ static const struct file_operations sis_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 90f6b13acfac416270ac5abb70fa919cf66b611a..a7f4d6bd1330de6ad9e5878be70019d3e6ebf2df 100644 (file)
@@ -49,6 +49,9 @@ static const struct file_operations tdfx_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index ba055e9ca0077875a3a49d3533d729a95ccf98fd..8d9dc44f1f94f56c32234fdb527576f7817433ad 100644 (file)
@@ -69,6 +69,13 @@ static int udl_get_modes(struct drm_connector *connector)
 static int udl_mode_valid(struct drm_connector *connector,
                          struct drm_display_mode *mode)
 {
+       struct udl_device *udl = connector->dev->dev_private;
+       if (!udl->sku_pixel_limit)
+               return 0;
+
+       if (mode->vdisplay * mode->hdisplay > udl->sku_pixel_limit)
+               return MODE_VIRTUAL_Y;
+
        return 0;
 }
 
index 6e52069894b35d91037474521e5ebf6e2f157e98..9f84128505bb420703745d426f0cdba4c8a46ab6 100644 (file)
@@ -66,6 +66,9 @@ static const struct file_operations udl_driver_fops = {
        .unlocked_ioctl = drm_ioctl,
        .release = drm_release,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index e927b4c052f52a4ed2e73a296354a0e84c849f20..af1b914b17e399a8de2265bd8cbdff32ed553a06 100644 (file)
@@ -65,6 +65,9 @@ static const struct file_operations via_driver_fops = {
        .mmap = drm_mmap,
        .poll = drm_poll,
        .fasync = drm_fasync,
+#ifdef CONFIG_COMPAT
+       .compat_ioctl = drm_compat_ioctl,
+#endif
        .llseek = noop_llseek,
 };
 
index 794ff67c5701386ce781abe5c0f91e42de150e26..b71bcd0bfbbf65a60dea1ea47beef41daddb7d8c 100644 (file)
@@ -12,3 +12,11 @@ config DRM_VMWGFX
          This is a KMS enabled DRM driver for the VMware SVGA2
          virtual hardware.
          The compiled module will be called "vmwgfx.ko".
+
+config DRM_VMWGFX_FBCON
+       depends on DRM_VMWGFX
+       bool "Enable framebuffer console under vmwgfx by default"
+       help
+          Choose this option if you are shipping a new vmwgfx
+          userspace driver that supports using the kernel driver.
+
index 4d9edead01acdbcb900a3fdca87d5ed08cdab682..ba2c35dbf10e3a7c90095d3fce4265dd3cfd14ff 100644 (file)
@@ -182,8 +182,9 @@ static struct pci_device_id vmw_pci_id_list[] = {
        {0x15ad, 0x0405, PCI_ANY_ID, PCI_ANY_ID, 0, 0, VMWGFX_CHIP_SVGAII},
        {0, 0, 0}
 };
+MODULE_DEVICE_TABLE(pci, vmw_pci_id_list);
 
-static int enable_fbdev;
+static int enable_fbdev = IS_ENABLED(CONFIG_DRM_VMWGFX_FBCON);
 
 static int vmw_probe(struct pci_dev *, const struct pci_device_id *);
 static void vmw_master_init(struct vmw_master *);
@@ -1154,6 +1155,11 @@ static struct drm_driver driver = {
        .open = vmw_driver_open,
        .preclose = vmw_preclose,
        .postclose = vmw_postclose,
+
+       .dumb_create = vmw_dumb_create,
+       .dumb_map_offset = vmw_dumb_map_offset,
+       .dumb_destroy = vmw_dumb_destroy,
+
        .fops = &vmwgfx_driver_fops,
        .name = VMWGFX_DRIVER_NAME,
        .desc = VMWGFX_DRIVER_DESC,
index d0f2c079ee2732d62f064b2667747412b5b6fb1c..29c984ff7f23aed1012e70d7e3e0744c1d1fa026 100644 (file)
@@ -645,6 +645,16 @@ int vmw_kms_readback(struct vmw_private *dev_priv,
 int vmw_kms_update_layout_ioctl(struct drm_device *dev, void *data,
                                struct drm_file *file_priv);
 
+int vmw_dumb_create(struct drm_file *file_priv,
+                   struct drm_device *dev,
+                   struct drm_mode_create_dumb *args);
+
+int vmw_dumb_map_offset(struct drm_file *file_priv,
+                       struct drm_device *dev, uint32_t handle,
+                       uint64_t *offset);
+int vmw_dumb_destroy(struct drm_file *file_priv,
+                    struct drm_device *dev,
+                    uint32_t handle);
 /**
  * Overlay control - vmwgfx_overlay.c
  */
index f2fb8f15e2f127b350e33c210d2b91d44ed09134..7e0743358dffdf5176d2aa48a393beb21803c6cd 100644 (file)
@@ -1018,7 +1018,7 @@ int vmw_event_fence_action_create(struct drm_file *file_priv,
        }
 
 
-       event = kzalloc(sizeof(event->event), GFP_KERNEL);
+       event = kzalloc(sizeof(*event), GFP_KERNEL);
        if (unlikely(event == NULL)) {
                DRM_ERROR("Failed to allocate an event.\n");
                ret = -ENOMEM;
index 22bf9a21ec7137a38735feea3c131ce72f156516..2c6ffe0e2c07828bc7b07e3a9bf55b71e7d438f6 100644 (file)
@@ -1917,3 +1917,76 @@ err_ref:
        vmw_resource_unreference(&res);
        return ret;
 }
+
+
+int vmw_dumb_create(struct drm_file *file_priv,
+                   struct drm_device *dev,
+                   struct drm_mode_create_dumb *args)
+{
+       struct vmw_private *dev_priv = vmw_priv(dev);
+       struct vmw_master *vmaster = vmw_master(file_priv->master);
+       struct vmw_user_dma_buffer *vmw_user_bo;
+       struct ttm_buffer_object *tmp;
+       int ret;
+
+       args->pitch = args->width * ((args->bpp + 7) / 8);
+       args->size = args->pitch * args->height;
+
+       vmw_user_bo = kzalloc(sizeof(*vmw_user_bo), GFP_KERNEL);
+       if (vmw_user_bo == NULL)
+               return -ENOMEM;
+
+       ret = ttm_read_lock(&vmaster->lock, true);
+       if (ret != 0) {
+               kfree(vmw_user_bo);
+               return ret;
+       }
+
+       ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, args->size,
+                             &vmw_vram_sys_placement, true,
+                             &vmw_user_dmabuf_destroy);
+       if (ret != 0)
+               goto out_no_dmabuf;
+
+       tmp = ttm_bo_reference(&vmw_user_bo->dma.base);
+       ret = ttm_base_object_init(vmw_fpriv(file_priv)->tfile,
+                                  &vmw_user_bo->base,
+                                  false,
+                                  ttm_buffer_type,
+                                  &vmw_user_dmabuf_release, NULL);
+       if (unlikely(ret != 0))
+               goto out_no_base_object;
+
+       args->handle = vmw_user_bo->base.hash.key;
+
+out_no_base_object:
+       ttm_bo_unref(&tmp);
+out_no_dmabuf:
+       ttm_read_unlock(&vmaster->lock);
+       return ret;
+}
+
+int vmw_dumb_map_offset(struct drm_file *file_priv,
+                       struct drm_device *dev, uint32_t handle,
+                       uint64_t *offset)
+{
+       struct ttm_object_file *tfile = vmw_fpriv(file_priv)->tfile;
+       struct vmw_dma_buffer *out_buf;
+       int ret;
+
+       ret = vmw_user_dmabuf_lookup(tfile, handle, &out_buf);
+       if (ret != 0)
+               return -EINVAL;
+
+       *offset = out_buf->base.addr_space_offset;
+       vmw_dmabuf_unreference(&out_buf);
+       return 0;
+}
+
+int vmw_dumb_destroy(struct drm_file *file_priv,
+                    struct drm_device *dev,
+                    uint32_t handle)
+{
+       return ttm_ref_object_base_unref(vmw_fpriv(file_priv)->tfile,
+                                        handle, TTM_REF_USAGE);
+}
index 60ea284407cea4d1f62db43a72b3e6cdbea47e31..8bcd168fffaebbf80808fa9ee9c02e42384eb1f5 100644 (file)
@@ -996,7 +996,8 @@ static void hid_process_event(struct hid_device *hid, struct hid_field *field,
        struct hid_driver *hdrv = hid->driver;
        int ret;
 
-       hid_dump_input(hid, usage, value);
+       if (!list_empty(&hid->debug_list))
+               hid_dump_input(hid, usage, value);
 
        if (hdrv && hdrv->event && hid_match_usage(hid, usage)) {
                ret = hdrv->event(hid, field, usage, value);
@@ -1558,7 +1559,9 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_KYE, USB_DEVICE_ID_KYE_EASYPEN_M610X) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LABTEC, USB_DEVICE_ID_LABTEC_WIRELESS_KEYBOARD) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LCPOWER, USB_DEVICE_ID_LCPOWER_LC1000 ) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#if IS_ENABLED(CONFIG_HID_LENOVO_TPKBD)
+       { HID_USB_DEVICE(USB_VENDOR_ID_LENOVO, USB_DEVICE_ID_LENOVO_TPKBD) },
+#endif
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_MX3000_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER) },
        { HID_USB_DEVICE(USB_VENDOR_ID_LOGITECH, USB_DEVICE_ID_S510_RECEIVER_2) },
@@ -1624,7 +1627,6 @@ static const struct hid_device_id hid_have_special_driver[] = {
        { HID_USB_DEVICE(USB_VENDOR_ID_ORTEK, USB_DEVICE_ID_ORTEK_WKB2000) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PETALYNX, USB_DEVICE_ID_PETALYNX_MAXTER_REMOTE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_PRIMAX, USB_DEVICE_ID_PRIMAX_KEYBOARD) },
-       { HID_USB_DEVICE(USB_VENDOR_ID_QUANTA, USB_DEVICE_ID_PIXART_IMAGING_INC_OPTICAL_TOUCH_SCREEN) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_KONE) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ARVO) },
        { HID_USB_DEVICE(USB_VENDOR_ID_ROCCAT, USB_DEVICE_ID_ROCCAT_ISKU) },
index 77d2df04c97b0dbe6c34eb11b9e566ae07d5ae28..60c4e1e85913fd435ba7c3fe977db50e4fb00f6c 100644 (file)
@@ -519,6 +519,8 @@ static void tpkbd_remove_tp(struct hid_device *hdev)
        led_classdev_unregister(&data_pointer->led_mute);
 
        hid_set_drvdata(hdev, NULL);
+       kfree(data_pointer->led_micmute.name);
+       kfree(data_pointer->led_mute.name);
        kfree(data_pointer);
 }
 
index 0f9c146fc00d7391932bcaef9df70e4fbc55541e..9500f2f3f8fea702432e683a56dc0eea53dbf3fe 100644 (file)
@@ -193,6 +193,7 @@ static struct hid_ll_driver logi_dj_ll_driver;
 static int logi_dj_output_hidraw_report(struct hid_device *hid, u8 * buf,
                                        size_t count,
                                        unsigned char report_type);
+static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev);
 
 static void logi_dj_recv_destroy_djhid_device(struct dj_receiver_dev *djrcv_dev,
                                                struct dj_report *dj_report)
@@ -233,6 +234,7 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
        if (dj_report->report_params[DEVICE_PAIRED_PARAM_SPFUNCTION] &
            SPFUNCTION_DEVICE_LIST_EMPTY) {
                dbg_hid("%s: device list is empty\n", __func__);
+               djrcv_dev->querying_devices = false;
                return;
        }
 
@@ -243,6 +245,12 @@ static void logi_dj_recv_add_djhid_device(struct dj_receiver_dev *djrcv_dev,
                return;
        }
 
+       if (djrcv_dev->paired_dj_devices[dj_report->device_index]) {
+               /* The device is already known. No need to reallocate it. */
+               dbg_hid("%s: device is already known\n", __func__);
+               return;
+       }
+
        dj_hiddev = hid_allocate_device();
        if (IS_ERR(dj_hiddev)) {
                dev_err(&djrcv_hdev->dev, "%s: hid_allocate_device failed\n",
@@ -306,6 +314,7 @@ static void delayedwork_callback(struct work_struct *work)
        struct dj_report dj_report;
        unsigned long flags;
        int count;
+       int retval;
 
        dbg_hid("%s\n", __func__);
 
@@ -338,6 +347,25 @@ static void delayedwork_callback(struct work_struct *work)
                logi_dj_recv_destroy_djhid_device(djrcv_dev, &dj_report);
                break;
        default:
+       /* A normal report (i. e. not belonging to a pair/unpair notification)
+        * arriving here, means that the report arrived but we did not have a
+        * paired dj_device associated to the report's device_index, this
+        * means that the original "device paired" notification corresponding
+        * to this dj_device never arrived to this driver. The reason is that
+        * hid-core discards all packets coming from a device while probe() is
+        * executing. */
+       if (!djrcv_dev->paired_dj_devices[dj_report.device_index]) {
+               /* ok, we don't know the device, just re-ask the
+                * receiver for the list of connected devices. */
+               retval = logi_dj_recv_query_paired_devices(djrcv_dev);
+               if (!retval) {
+                       /* everything went fine, so just leave */
+                       break;
+               }
+               dev_err(&djrcv_dev->hdev->dev,
+                       "%s:logi_dj_recv_query_paired_devices "
+                       "error:%d\n", __func__, retval);
+               }
                dbg_hid("%s: unexpected report type\n", __func__);
        }
 }
@@ -368,6 +396,12 @@ static void logi_dj_recv_forward_null_report(struct dj_receiver_dev *djrcv_dev,
        if (!djdev) {
                dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
                        " is NULL, index %d\n", dj_report->device_index);
+               kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+               if (schedule_work(&djrcv_dev->work) == 0) {
+                       dbg_hid("%s: did not schedule the work item, was already "
+                       "queued\n", __func__);
+               }
                return;
        }
 
@@ -398,6 +432,12 @@ static void logi_dj_recv_forward_report(struct dj_receiver_dev *djrcv_dev,
        if (dj_device == NULL) {
                dbg_hid("djrcv_dev->paired_dj_devices[dj_report->device_index]"
                        " is NULL, index %d\n", dj_report->device_index);
+               kfifo_in(&djrcv_dev->notif_fifo, dj_report, sizeof(struct dj_report));
+
+               if (schedule_work(&djrcv_dev->work) == 0) {
+                       dbg_hid("%s: did not schedule the work item, was already "
+                       "queued\n", __func__);
+               }
                return;
        }
 
@@ -439,7 +479,11 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        struct dj_report *dj_report;
        int retval;
 
-       dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+       /* no need to protect djrcv_dev->querying_devices */
+       if (djrcv_dev->querying_devices)
+               return 0;
+
+       dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
        if (!dj_report)
                return -ENOMEM;
        dj_report->report_id = REPORT_ID_DJ_SHORT;
@@ -450,13 +494,14 @@ static int logi_dj_recv_query_paired_devices(struct dj_receiver_dev *djrcv_dev)
        return retval;
 }
 
+
 static int logi_dj_recv_switch_to_dj_mode(struct dj_receiver_dev *djrcv_dev,
                                          unsigned timeout)
 {
        struct dj_report *dj_report;
        int retval;
 
-       dj_report = kzalloc(sizeof(dj_report), GFP_KERNEL);
+       dj_report = kzalloc(sizeof(struct dj_report), GFP_KERNEL);
        if (!dj_report)
                return -ENOMEM;
        dj_report->report_id = REPORT_ID_DJ_SHORT;
index fd28a5e0ca3b84b8407791421b25f8b17bf7815a..4a4000340ce1ed8cf6be1f81ee8e0f21d8ba5f5a 100644 (file)
@@ -101,6 +101,7 @@ struct dj_receiver_dev {
        struct work_struct work;
        struct kfifo notif_fifo;
        spinlock_t lock;
+       bool querying_devices;
 };
 
 struct dj_device {
index 903eef3d3e10034f8e36974ba4e95ee746438702..991e85c7325c849d4e7c287afe28364a8e3351e6 100644 (file)
@@ -70,6 +70,7 @@ static const struct hid_blacklist {
        { USB_VENDOR_ID_CH, USB_DEVICE_ID_CH_AXIS_295, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_DMI, USB_DEVICE_ID_DMI_ENC, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_ELO, USB_DEVICE_ID_ELO_TS2700, HID_QUIRK_NOGET },
+       { USB_VENDOR_ID_MGE, USB_DEVICE_ID_MGE_UPS, HID_QUIRK_NOGET },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN1, HID_QUIRK_NO_INIT_REPORTS },
        { USB_VENDOR_ID_PIXART, USB_DEVICE_ID_PIXART_OPTICAL_TOUCH_SCREEN2, HID_QUIRK_NO_INIT_REPORTS },
index cfec802cf9ca949b705d24a1d862a702af223193..f915eb1c29f7030e0612c80812e2b32ba25334b4 100644 (file)
@@ -87,10 +87,18 @@ static ssize_t ad7314_show_temperature(struct device *dev,
        }
 }
 
+static ssize_t ad7314_show_name(struct device *dev,
+                               struct device_attribute *devattr, char *buf)
+{
+       return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
+}
+
+static DEVICE_ATTR(name, S_IRUGO, ad7314_show_name, NULL);
 static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO,
                          ad7314_show_temperature, NULL, 0);
 
 static struct attribute *ad7314_attributes[] = {
+       &dev_attr_name.attr,
        &sensor_dev_attr_temp1_input.dev_attr.attr,
        NULL,
 };
index e65c6e45d36b05a24241680558fd2012be3f3c85..7bf4ce3d405e4903e26c010cc9040ce87e7067ba 100644 (file)
@@ -139,6 +139,12 @@ static ssize_t show_voltage(struct device *dev,
        }
 }
 
+static ssize_t ads7871_show_name(struct device *dev,
+                                struct device_attribute *devattr, char *buf)
+{
+       return sprintf(buf, "%s\n", to_spi_device(dev)->modalias);
+}
+
 static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_voltage, NULL, 0);
 static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_voltage, NULL, 1);
 static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_voltage, NULL, 2);
@@ -148,6 +154,8 @@ static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_voltage, NULL, 5);
 static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_voltage, NULL, 6);
 static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_voltage, NULL, 7);
 
+static DEVICE_ATTR(name, S_IRUGO, ads7871_show_name, NULL);
+
 static struct attribute *ads7871_attributes[] = {
        &sensor_dev_attr_in0_input.dev_attr.attr,
        &sensor_dev_attr_in1_input.dev_attr.attr,
@@ -157,6 +165,7 @@ static struct attribute *ads7871_attributes[] = {
        &sensor_dev_attr_in5_input.dev_attr.attr,
        &sensor_dev_attr_in6_input.dev_attr.attr,
        &sensor_dev_attr_in7_input.dev_attr.attr,
+       &dev_attr_name.attr,
        NULL
 };
 
index 282708860517e8de41e2f86c3aeb55a118aaca17..8f3f6f2c45fd1a5ba95664a4ba92a6ffe7e6323c 100644 (file)
 
 #define APPLESMC_MAX_DATA_LENGTH 32
 
-/* wait up to 32 ms for a status change. */
+/* wait up to 128 ms for a status change. */
 #define APPLESMC_MIN_WAIT      0x0010
 #define APPLESMC_RETRY_WAIT    0x0100
-#define APPLESMC_MAX_WAIT      0x8000
+#define APPLESMC_MAX_WAIT      0x20000
 
 #define APPLESMC_READ_CMD      0x10
 #define APPLESMC_WRITE_CMD     0x11
index 351d1f4593e7a8276da3ff7cdd9b286d4ea2b097..4ee5789487233dbe6bf03920fa29fb820d366b8d 100644 (file)
@@ -34,6 +34,12 @@ static const struct dmi_system_id __initconst atk_force_new_if[] = {
                .matches = {
                        DMI_MATCH(DMI_BOARD_NAME, "SABERTOOTH X58")
                }
+       }, {
+               /* Old interface reads the same sensor for fan0 and fan1 */
+               .ident = "Asus M5A78L",
+               .matches = {
+                       DMI_MATCH(DMI_BOARD_NAME, "M5A78L")
+               }
        },
        { }
 };
index 0fa356fe82ccc00fc6a70704627da99bb66fc49a..984a3f13923b615b7c6849cd59b396689680ed20 100644 (file)
@@ -815,17 +815,20 @@ static int __init coretemp_init(void)
        if (err)
                goto exit;
 
+       get_online_cpus();
        for_each_online_cpu(i)
                get_core_online(i);
 
 #ifndef CONFIG_HOTPLUG_CPU
        if (list_empty(&pdev_list)) {
+               put_online_cpus();
                err = -ENODEV;
                goto exit_driver_unreg;
        }
 #endif
 
        register_hotcpu_notifier(&coretemp_cpu_notifier);
+       put_online_cpus();
        return 0;
 
 #ifndef CONFIG_HOTPLUG_CPU
@@ -840,6 +843,7 @@ static void __exit coretemp_exit(void)
 {
        struct pdev_entry *p, *n;
 
+       get_online_cpus();
        unregister_hotcpu_notifier(&coretemp_cpu_notifier);
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
@@ -848,6 +852,7 @@ static void __exit coretemp_exit(void)
                kfree(p);
        }
        mutex_unlock(&pdev_list_mutex);
+       put_online_cpus();
        platform_driver_unregister(&coretemp_driver);
 }
 
index 2764b78a784b9be83f9df1fd48f558452d9b8d61..af69073b3fe87a323e8986f76268c3ec1aa78522 100644 (file)
@@ -129,12 +129,12 @@ static bool __devinit fam15h_power_is_internal_node0(struct pci_dev *f4)
  * counter saturations resulting in bogus power readings.
  * We correct this value ourselves to cope with older BIOSes.
  */
-static DEFINE_PCI_DEVICE_TABLE(affected_device) = {
+static const struct pci_device_id affected_device[] = {
        { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) },
        { 0 }
 };
 
-static void __devinit tweak_runavg_range(struct pci_dev *pdev)
+static void tweak_runavg_range(struct pci_dev *pdev)
 {
        u32 val;
 
@@ -158,6 +158,16 @@ static void __devinit tweak_runavg_range(struct pci_dev *pdev)
                REG_TDP_RUNNING_AVERAGE, val);
 }
 
+#ifdef CONFIG_PM
+static int fam15h_power_resume(struct pci_dev *pdev)
+{
+       tweak_runavg_range(pdev);
+       return 0;
+}
+#else
+#define fam15h_power_resume NULL
+#endif
+
 static void __devinit fam15h_power_init_data(struct pci_dev *f4,
                                             struct fam15h_power_data *data)
 {
@@ -256,6 +266,7 @@ static struct pci_driver fam15h_power_driver = {
        .id_table = fam15h_power_id_table,
        .probe = fam15h_power_probe,
        .remove = __devexit_p(fam15h_power_remove),
+       .resume = fam15h_power_resume,
 };
 
 module_pci_driver(fam15h_power_driver);
index 7f3f4a385729375c002409387d157f3565b30e04..602148299f68db03a81683ab95c14e39614e5d8d 100644 (file)
@@ -69,22 +69,6 @@ struct ina2xx_data {
        u16 regs[INA2XX_MAX_REGISTERS];
 };
 
-int ina2xx_read_word(struct i2c_client *client, int reg)
-{
-       int val = i2c_smbus_read_word_data(client, reg);
-       if (unlikely(val < 0)) {
-               dev_dbg(&client->dev,
-                       "Failed to read register: %d\n", reg);
-               return val;
-       }
-       return be16_to_cpu(val);
-}
-
-void ina2xx_write_word(struct i2c_client *client, int reg, int data)
-{
-       i2c_smbus_write_word_data(client, reg, cpu_to_be16(data));
-}
-
 static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 {
        struct i2c_client *client = to_i2c_client(dev);
@@ -102,7 +86,7 @@ static struct ina2xx_data *ina2xx_update_device(struct device *dev)
 
                /* Read all registers */
                for (i = 0; i < data->registers; i++) {
-                       int rv = ina2xx_read_word(client, i);
+                       int rv = i2c_smbus_read_word_swapped(client, i);
                        if (rv < 0) {
                                ret = ERR_PTR(rv);
                                goto abort;
@@ -279,22 +263,26 @@ static int ina2xx_probe(struct i2c_client *client,
        switch (data->kind) {
        case ina219:
                /* device configuration */
-               ina2xx_write_word(client, INA2XX_CONFIG, INA219_CONFIG_DEFAULT);
+               i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+                                            INA219_CONFIG_DEFAULT);
 
                /* set current LSB to 1mA, shunt is in uOhms */
                /* (equation 13 in datasheet) */
-               ina2xx_write_word(client, INA2XX_CALIBRATION, 40960000 / shunt);
+               i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+                                            40960000 / shunt);
                dev_info(&client->dev,
                         "power monitor INA219 (Rshunt = %li uOhm)\n", shunt);
                data->registers = INA219_REGISTERS;
                break;
        case ina226:
                /* device configuration */
-               ina2xx_write_word(client, INA2XX_CONFIG, INA226_CONFIG_DEFAULT);
+               i2c_smbus_write_word_swapped(client, INA2XX_CONFIG,
+                                            INA226_CONFIG_DEFAULT);
 
                /* set current LSB to 1mA, shunt is in uOhms */
                /* (equation 1 in datasheet)*/
-               ina2xx_write_word(client, INA2XX_CALIBRATION, 5120000 / shunt);
+               i2c_smbus_write_word_swapped(client, INA2XX_CALIBRATION,
+                                            5120000 / shunt);
                dev_info(&client->dev,
                         "power monitor INA226 (Rshunt = %li uOhm)\n", shunt);
                data->registers = INA226_REGISTERS;
index 0018c7dd0097de5045f646d98e715713ea7edba4..1a174f0a3cdeb9bd854d13fa61171a63c33e41d7 100644 (file)
@@ -44,12 +44,13 @@ static ssize_t madc_read(struct device *dev,
                         struct device_attribute *devattr, char *buf)
 {
        struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-       struct twl4030_madc_request req;
+       struct twl4030_madc_request req = {
+               .channels = 1 << attr->index,
+               .method = TWL4030_MADC_SW2,
+               .type = TWL4030_MADC_WAIT,
+       };
        long val;
 
-       req.channels = (1 << attr->index);
-       req.method = TWL4030_MADC_SW2;
-       req.func_cb = NULL;
        val = twl4030_madc_conversion(&req);
        if (val < 0)
                return val;
index ee4ebc198a9448e868f45af079e8f3d5f51968ae..2e56c6ce9fb654cb0532f4cbef756fd99f618e9d 100644 (file)
@@ -328,6 +328,7 @@ static int __init via_cputemp_init(void)
        if (err)
                goto exit;
 
+       get_online_cpus();
        for_each_online_cpu(i) {
                struct cpuinfo_x86 *c = &cpu_data(i);
 
@@ -347,12 +348,14 @@ static int __init via_cputemp_init(void)
 
 #ifndef CONFIG_HOTPLUG_CPU
        if (list_empty(&pdev_list)) {
+               put_online_cpus();
                err = -ENODEV;
                goto exit_driver_unreg;
        }
 #endif
 
        register_hotcpu_notifier(&via_cputemp_cpu_notifier);
+       put_online_cpus();
        return 0;
 
 #ifndef CONFIG_HOTPLUG_CPU
@@ -367,6 +370,7 @@ static void __exit via_cputemp_exit(void)
 {
        struct pdev_entry *p, *n;
 
+       get_online_cpus();
        unregister_hotcpu_notifier(&via_cputemp_cpu_notifier);
        mutex_lock(&pdev_list_mutex);
        list_for_each_entry_safe(p, n, &pdev_list, list) {
@@ -375,6 +379,7 @@ static void __exit via_cputemp_exit(void)
                kfree(p);
        }
        mutex_unlock(&pdev_list_mutex);
+       put_online_cpus();
        platform_driver_unregister(&via_cputemp_driver);
 }
 
index 1201a15784c3a0eec329affa6f6edf1546df0b51..db713c0dfba4d6c6272ac19c79b793595a9cdad7 100644 (file)
@@ -552,7 +552,7 @@ EXPORT_SYMBOL_GPL(hwspin_lock_request_specific);
  */
 int hwspin_lock_free(struct hwspinlock *hwlock)
 {
-       struct device *dev = hwlock->bank->dev;
+       struct device *dev;
        struct hwspinlock *tmp;
        int ret;
 
@@ -561,6 +561,7 @@ int hwspin_lock_free(struct hwspinlock *hwlock)
                return -EINVAL;
        }
 
+       dev = hwlock->bank->dev;
        mutex_lock(&hwspinlock_tree_lock);
 
        /* make sure the hwspinlock is used */
index 73133b1063f012416d2a957f3fc2432ace395439..6f5f98d69af7c26b2fd7b895106e11745ce7d155 100644 (file)
@@ -476,17 +476,17 @@ static int pca_init(struct i2c_adapter *adap)
                /* To avoid integer overflow, use clock/100 for calculations */
                clock = pca_clock(pca_data) / 100;
 
-               if (pca_data->i2c_clock > 10000) {
+               if (pca_data->i2c_clock > 1000000) {
                        mode = I2C_PCA_MODE_TURBO;
                        min_tlow = 14;
                        min_thi  = 5;
                        raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
-               } else if (pca_data->i2c_clock > 4000) {
+               } else if (pca_data->i2c_clock > 400000) {
                        mode = I2C_PCA_MODE_FASTP;
                        min_tlow = 17;
                        min_thi  = 9;
                        raise_fall_time = 22; /* Raise 11e-8s, Fall 11e-8s */
-               } else if (pca_data->i2c_clock > 1000) {
+               } else if (pca_data->i2c_clock > 100000) {
                        mode = I2C_PCA_MODE_FAST;
                        min_tlow = 44;
                        min_thi  = 20;
index b4aaa1bd6728503b629acea078f3021fc148115a..970a1612e795566f007ccebe2b6ae811131694c9 100644 (file)
@@ -104,6 +104,7 @@ config I2C_I801
            DH89xxCC (PCH)
            Panther Point (PCH)
            Lynx Point (PCH)
+           Lynx Point-LP (PCH)
 
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
@@ -354,9 +355,13 @@ config I2C_DAVINCI
          devices such as DaVinci NIC.
          For details please see http://www.ti.com/davinci
 
+config I2C_DESIGNWARE_CORE
+       tristate
+
 config I2C_DESIGNWARE_PLATFORM
        tristate "Synopsys DesignWare Platform"
        depends on HAVE_CLK
+       select I2C_DESIGNWARE_CORE
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
@@ -367,6 +372,7 @@ config I2C_DESIGNWARE_PLATFORM
 config I2C_DESIGNWARE_PCI
        tristate "Synopsys DesignWare PCI"
        depends on PCI
+       select I2C_DESIGNWARE_CORE
        help
          If you say yes to this option, support will be included for the
          Synopsys DesignWare I2C adapter. Only master mode is supported.
index ce3c2be7fb40a6cb453a92a9cc1eb89da510383f..37c4182cc98bb28520eeb1ce579bb3b601cffc01 100644 (file)
@@ -33,10 +33,11 @@ obj-$(CONFIG_I2C_AU1550)    += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
 obj-$(CONFIG_I2C_CPM)          += i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
+obj-$(CONFIG_I2C_DESIGNWARE_CORE)      += i2c-designware-core.o
 obj-$(CONFIG_I2C_DESIGNWARE_PLATFORM)  += i2c-designware-platform.o
-i2c-designware-platform-objs := i2c-designware-platdrv.o i2c-designware-core.o
+i2c-designware-platform-objs := i2c-designware-platdrv.o
 obj-$(CONFIG_I2C_DESIGNWARE_PCI)       += i2c-designware-pci.o
-i2c-designware-pci-objs := i2c-designware-pcidrv.o i2c-designware-core.o
+i2c-designware-pci-objs := i2c-designware-pcidrv.o
 obj-$(CONFIG_I2C_EG20T)                += i2c-eg20t.o
 obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
 obj-$(CONFIG_I2C_HIGHLANDER)   += i2c-highlander.o
index 1e48bec80edfb08a0628cc816004c1955075fc42..7b8ebbefb581156ee8dd795cd6c4d458e37367f7 100644 (file)
@@ -25,6 +25,7 @@
  * ----------------------------------------------------------------------------
  *
  */
+#include <linux/export.h>
 #include <linux/clk.h>
 #include <linux/errno.h>
 #include <linux/err.h>
@@ -316,6 +317,7 @@ int i2c_dw_init(struct dw_i2c_dev *dev)
        dw_writel(dev, dev->master_cfg , DW_IC_CON);
        return 0;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_init);
 
 /*
  * Waiting for bus not busy
@@ -568,12 +570,14 @@ done:
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_xfer);
 
 u32 i2c_dw_func(struct i2c_adapter *adap)
 {
        struct dw_i2c_dev *dev = i2c_get_adapdata(adap);
        return dev->functionality;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_func);
 
 static u32 i2c_dw_read_clear_intrbits(struct dw_i2c_dev *dev)
 {
@@ -678,17 +682,20 @@ tx_aborted:
 
        return IRQ_HANDLED;
 }
+EXPORT_SYMBOL_GPL(i2c_dw_isr);
 
 void i2c_dw_enable(struct dw_i2c_dev *dev)
 {
        /* Enable the adapter */
        dw_writel(dev, 1, DW_IC_ENABLE);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_enable);
 
 u32 i2c_dw_is_enabled(struct dw_i2c_dev *dev)
 {
        return dw_readl(dev, DW_IC_ENABLE);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_is_enabled);
 
 void i2c_dw_disable(struct dw_i2c_dev *dev)
 {
@@ -699,18 +706,22 @@ void i2c_dw_disable(struct dw_i2c_dev *dev)
        dw_writel(dev, 0, DW_IC_INTR_MASK);
        dw_readl(dev, DW_IC_CLR_INTR);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable);
 
 void i2c_dw_clear_int(struct dw_i2c_dev *dev)
 {
        dw_readl(dev, DW_IC_CLR_INTR);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_clear_int);
 
 void i2c_dw_disable_int(struct dw_i2c_dev *dev)
 {
        dw_writel(dev, 0, DW_IC_INTR_MASK);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_disable_int);
 
 u32 i2c_dw_read_comp_param(struct dw_i2c_dev *dev)
 {
        return dw_readl(dev, DW_IC_COMP_PARAM_1);
 }
+EXPORT_SYMBOL_GPL(i2c_dw_read_comp_param);
index 898dcf9c7adeaac26d932b6e8c6a6e8d90e9be66..33e9b0c09af208762f7f8f58b4c3895798618233 100644 (file)
@@ -52,6 +52,7 @@
   DH89xxCC (PCH)        0x2330     32     hard     yes     yes     yes
   Panther Point (PCH)   0x1e22     32     hard     yes     yes     yes
   Lynx Point (PCH)      0x8c22     32     hard     yes     yes     yes
+  Lynx Point-LP (PCH)   0x9c22     32     hard     yes     yes     yes
 
   Features supported by this driver:
   Software PEC                     no
 #define PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS     0x2330
 #define PCI_DEVICE_ID_INTEL_5_3400_SERIES_SMBUS        0x3b30
 #define PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS    0x8c22
+#define PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS 0x9c22
 
 struct i801_priv {
        struct i2c_adapter adapter;
@@ -771,6 +773,7 @@ static DEFINE_PCI_DEVICE_TABLE(i801_ids) = {
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_DH89XXCC_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_PANTHERPOINT_SMBUS) },
        { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_SMBUS) },
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_LYNXPOINT_LP_SMBUS) },
        { 0, }
 };
 
index 088c5c1ed17dfe831c4345ee8f02dd0ef4e1c82d..51f05b8520edb3f95b983d5002859afd386586e4 100644 (file)
@@ -365,10 +365,6 @@ static int mxs_i2c_get_ofdata(struct mxs_i2c_dev *i2c)
        struct device_node *node = dev->of_node;
        int ret;
 
-       if (!node)
-               return -EINVAL;
-
-       i2c->speed = &mxs_i2c_95kHz_config;
        ret = of_property_read_u32(node, "clock-frequency", &speed);
        if (ret)
                dev_warn(dev, "No I2C speed selected, using 100kHz\n");
@@ -419,10 +415,13 @@ static int __devinit mxs_i2c_probe(struct platform_device *pdev)
                return err;
 
        i2c->dev = dev;
+       i2c->speed = &mxs_i2c_95kHz_config;
 
-       err = mxs_i2c_get_ofdata(i2c);
-       if (err)
-               return err;
+       if (dev->of_node) {
+               err = mxs_i2c_get_ofdata(i2c);
+               if (err)
+                       return err;
+       }
 
        platform_set_drvdata(pdev, i2c);
 
index 5d54416770b01e7816cc85cd7dcbf403bf407442..8488bddfe46596109249edd242a3ad0ebc7cfe8b 100644 (file)
@@ -48,8 +48,9 @@ enum {
        mcntrl_afie = 0x00000002,
        mcntrl_naie = 0x00000004,
        mcntrl_drmie = 0x00000008,
-       mcntrl_daie = 0x00000020,
-       mcntrl_rffie = 0x00000040,
+       mcntrl_drsie = 0x00000010,
+       mcntrl_rffie = 0x00000020,
+       mcntrl_daie = 0x00000040,
        mcntrl_tffie = 0x00000080,
        mcntrl_reset = 0x00000100,
        mcntrl_cdbmode = 0x00000400,
@@ -290,31 +291,37 @@ static int i2c_pnx_master_rcv(struct i2c_pnx_algo_data *alg_data)
         * or we didn't 'ask' for it yet.
         */
        if (ioread32(I2C_REG_STS(alg_data)) & mstatus_rfe) {
-               dev_dbg(&alg_data->adapter.dev,
-                       "%s(): Write dummy data to fill Rx-fifo...\n",
-                       __func__);
+               /* 'Asking' is done asynchronously, e.g. dummy TX of several
+                * bytes is done before the first actual RX arrives in FIFO.
+                * Therefore, ordered bytes (via TX) are counted separately.
+                */
+               if (alg_data->mif.order) {
+                       dev_dbg(&alg_data->adapter.dev,
+                               "%s(): Write dummy data to fill Rx-fifo...\n",
+                               __func__);
 
-               if (alg_data->mif.len == 1) {
-                       /* Last byte, do not acknowledge next rcv. */
-                       val |= stop_bit;
+                       if (alg_data->mif.order == 1) {
+                               /* Last byte, do not acknowledge next rcv. */
+                               val |= stop_bit;
+
+                               /*
+                                * Enable interrupt RFDAIE (data in Rx fifo),
+                                * and disable DRMIE (need data for Tx)
+                                */
+                               ctl = ioread32(I2C_REG_CTL(alg_data));
+                               ctl |= mcntrl_rffie | mcntrl_daie;
+                               ctl &= ~mcntrl_drmie;
+                               iowrite32(ctl, I2C_REG_CTL(alg_data));
+                       }
 
                        /*
-                        * Enable interrupt RFDAIE (data in Rx fifo),
-                        * and disable DRMIE (need data for Tx)
+                        * Now we'll 'ask' for data:
+                        * For each byte we want to receive, we must
+                        * write a (dummy) byte to the Tx-FIFO.
                         */
-                       ctl = ioread32(I2C_REG_CTL(alg_data));
-                       ctl |= mcntrl_rffie | mcntrl_daie;
-                       ctl &= ~mcntrl_drmie;
-                       iowrite32(ctl, I2C_REG_CTL(alg_data));
+                       iowrite32(val, I2C_REG_TX(alg_data));
+                       alg_data->mif.order--;
                }
-
-               /*
-                * Now we'll 'ask' for data:
-                * For each byte we want to receive, we must
-                * write a (dummy) byte to the Tx-FIFO.
-                */
-               iowrite32(val, I2C_REG_TX(alg_data));
-
                return 0;
        }
 
@@ -514,6 +521,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
 
                alg_data->mif.buf = pmsg->buf;
                alg_data->mif.len = pmsg->len;
+               alg_data->mif.order = pmsg->len;
                alg_data->mif.mode = (pmsg->flags & I2C_M_RD) ?
                        I2C_SMBUS_READ : I2C_SMBUS_WRITE;
                alg_data->mif.ret = 0;
@@ -566,6 +574,7 @@ i2c_pnx_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
        /* Cleanup to be sure... */
        alg_data->mif.buf = NULL;
        alg_data->mif.len = 0;
+       alg_data->mif.order = 0;
 
        dev_dbg(&alg_data->adapter.dev, "%s(): exiting, stat = %x\n",
                __func__, ioread32(I2C_REG_STS(alg_data)));
index 2efa56c5ff2c32d10ff3018def5bc077b8492e4e..2091ae8f539a5e78ee59338cd29876109b22883d 100644 (file)
@@ -636,6 +636,22 @@ static void i2c_adapter_dev_release(struct device *dev)
        complete(&adap->dev_released);
 }
 
+/*
+ * This function is only needed for mutex_lock_nested, so it is never
+ * called unless locking correctness checking is enabled. Thus we
+ * make it inline to avoid a compiler warning. That's what gcc ends up
+ * doing anyway.
+ */
+static inline unsigned int i2c_adapter_depth(struct i2c_adapter *adapter)
+{
+       unsigned int depth = 0;
+
+       while ((adapter = i2c_parent_is_i2c_adapter(adapter)))
+               depth++;
+
+       return depth;
+}
+
 /*
  * Let users instantiate I2C devices through sysfs. This can be used when
  * platform initialization code doesn't contain the proper data for
@@ -726,7 +742,8 @@ i2c_sysfs_delete_device(struct device *dev, struct device_attribute *attr,
 
        /* Make sure the device was added through sysfs */
        res = -ENOENT;
-       mutex_lock(&adap->userspace_clients_lock);
+       mutex_lock_nested(&adap->userspace_clients_lock,
+                         i2c_adapter_depth(adap));
        list_for_each_entry_safe(client, next, &adap->userspace_clients,
                                 detected) {
                if (client->addr == addr) {
@@ -1073,7 +1090,8 @@ int i2c_del_adapter(struct i2c_adapter *adap)
                return res;
 
        /* Remove devices instantiated from sysfs */
-       mutex_lock(&adap->userspace_clients_lock);
+       mutex_lock_nested(&adap->userspace_clients_lock,
+                         i2c_adapter_depth(adap));
        list_for_each_entry_safe(client, next, &adap->userspace_clients,
                                 detected) {
                dev_dbg(&adap->dev, "Removing %s at 0x%x\n", client->name,
index 92406097efebcb5e0052fba38a0f59b5eb8c45eb..8d1e32d7cd9767db4e1c99db627681f03f233139 100644 (file)
@@ -4,7 +4,7 @@
 
 int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 {
-       ide_drive_t *drive = dev_get_drvdata(dev);
+       ide_drive_t *drive = to_ide_device(dev);
        ide_drive_t *pair = ide_get_pair_dev(drive);
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq;
@@ -40,7 +40,7 @@ int generic_ide_suspend(struct device *dev, pm_message_t mesg)
 
 int generic_ide_resume(struct device *dev)
 {
-       ide_drive_t *drive = dev_get_drvdata(dev);
+       ide_drive_t *drive = to_ide_device(dev);
        ide_drive_t *pair = ide_get_pair_dev(drive);
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq;
index f61780a02374d1f855af861092c3ebae5b35cd80..3bd5540238a7e6d683fd903cfacc14c8b05b92d5 100644 (file)
@@ -617,7 +617,7 @@ static int __devinit at91_adc_probe(struct platform_device *pdev)
        st->adc_clk = clk_get(&pdev->dev, "adc_op_clk");
        if (IS_ERR(st->adc_clk)) {
                dev_err(&pdev->dev, "Failed to get the ADC clock.\n");
-               ret = PTR_ERR(st->clk);
+               ret = PTR_ERR(st->adc_clk);
                goto error_disable_clk;
        }
 
index 51f42061dae9de4d375795e89e5a95b28bbc0405..6cfd4d8fd0bd8e240dd1311698a2cf603fcfed15 100644 (file)
@@ -1361,11 +1361,11 @@ static int abort_rpl(struct c4iw_dev *dev, struct sk_buff *skb)
        struct tid_info *t = dev->rdev.lldi.tids;
 
        ep = lookup_tid(t, tid);
-       PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        if (!ep) {
                printk(KERN_WARNING MOD "Abort rpl to freed endpoint\n");
                return 0;
        }
+       PDBG("%s ep %p tid %u\n", __func__, ep, ep->hwtid);
        mutex_lock(&ep->com.mutex);
        switch (ep->com.state) {
        case ABORTING:
index cb5b7f7d4d3876904bb6b515273747c37787465d..b29a4246ef41ef6068372398ed23134cceae3384 100644 (file)
@@ -2219,7 +2219,6 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,
        u32 wqe_idx;
 
        if (!qp->wqe_wr_id_tbl[tail].signaled) {
-               expand = true;  /* CQE cannot be consumed yet */
                *polled = false;    /* WC cannot be consumed yet */
        } else {
                ibwc->status = IB_WC_SUCCESS;
@@ -2227,10 +2226,11 @@ static bool ocrdma_poll_success_scqe(struct ocrdma_qp *qp,
                ibwc->qp = &qp->ibqp;
                ocrdma_update_wc(qp, ibwc, tail);
                *polled = true;
-               wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK;
-               if (tail != wqe_idx)
-                       expand = true; /* Coalesced CQE can't be consumed yet */
        }
+       wqe_idx = le32_to_cpu(cqe->wq.wqeidx) & OCRDMA_CQE_WQEIDX_MASK;
+       if (tail != wqe_idx)
+               expand = true; /* Coalesced CQE can't be consumed yet */
+
        ocrdma_hwq_inc_tail(&qp->sq);
        return expand;
 }
index 19f1e6c45fb6847caaac2a45af4e69d4df981ca4..ccb119143d20568eb0570ab5b1360a78ca888e08 100644 (file)
@@ -471,9 +471,10 @@ static int subn_get_portinfo(struct ib_smp *smp, struct ib_device *ibdev,
                if (port_num != port) {
                        ibp = to_iport(ibdev, port_num);
                        ret = check_mkey(ibp, smp, 0);
-                       if (ret)
+                       if (ret) {
                                ret = IB_MAD_RESULT_FAILURE;
                                goto bail;
+                       }
                }
        }
 
index ca43901ed861b8d2bc31c70a9e570d9db3d2f8c1..0af216d21f8790c31af507022bbc722627f41671 100644 (file)
@@ -262,7 +262,10 @@ struct ipoib_ethtool_st {
        u16     max_coalesced_frames;
 };
 
+struct ipoib_neigh_table;
+
 struct ipoib_neigh_hash {
+       struct ipoib_neigh_table       *ntbl;
        struct ipoib_neigh __rcu      **buckets;
        struct rcu_head                 rcu;
        u32                             mask;
@@ -271,9 +274,9 @@ struct ipoib_neigh_hash {
 
 struct ipoib_neigh_table {
        struct ipoib_neigh_hash __rcu  *htbl;
-       rwlock_t                        rwlock;
        atomic_t                        entries;
        struct completion               flushed;
+       struct completion               deleted;
 };
 
 /*
index 3e2085a3ee474fc0111c7034ca013bfda7d63d7e..1e19b5ae7c479a5865837ffa4b08f7f5c89bdcdc 100644 (file)
@@ -546,15 +546,15 @@ static void neigh_add_path(struct sk_buff *skb, u8 *daddr,
        struct ipoib_neigh *neigh;
        unsigned long flags;
 
+       spin_lock_irqsave(&priv->lock, flags);
        neigh = ipoib_neigh_alloc(daddr, dev);
        if (!neigh) {
+               spin_unlock_irqrestore(&priv->lock, flags);
                ++dev->stats.tx_dropped;
                dev_kfree_skb_any(skb);
                return;
        }
 
-       spin_lock_irqsave(&priv->lock, flags);
-
        path = __path_find(dev, daddr + 4);
        if (!path) {
                path = path_rec_create(dev, daddr + 4);
@@ -863,10 +863,10 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
        if (test_bit(IPOIB_STOP_NEIGH_GC, &priv->flags))
                return;
 
-       write_lock_bh(&ntbl->rwlock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
 
        if (!htbl)
                goto out_unlock;
@@ -883,16 +883,14 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                                         lockdep_is_held(&priv->lock))) != NULL) {
                        /* was the neigh idle for two GC periods */
                        if (time_after(neigh_obsolete, neigh->alive)) {
                                rcu_assign_pointer(*np,
                                                   rcu_dereference_protected(neigh->hnext,
-                                                                            lockdep_is_held(&ntbl->rwlock)));
+                                                                            lockdep_is_held(&priv->lock)));
                                /* remove from path/mc list */
-                               spin_lock_irqsave(&priv->lock, flags);
                                list_del(&neigh->list);
-                               spin_unlock_irqrestore(&priv->lock, flags);
                                call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                        } else {
                                np = &neigh->hnext;
@@ -902,7 +900,7 @@ static void __ipoib_reap_neigh(struct ipoib_dev_priv *priv)
        }
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static void ipoib_reap_neigh(struct work_struct *work)
@@ -947,10 +945,8 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
        struct ipoib_neigh *neigh;
        u32 hash_val;
 
-       write_lock_bh(&ntbl->rwlock);
-
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
        if (!htbl) {
                neigh = NULL;
                goto out_unlock;
@@ -961,10 +957,10 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
         */
        hash_val = ipoib_addr_hash(htbl, daddr);
        for (neigh = rcu_dereference_protected(htbl->buckets[hash_val],
-                                              lockdep_is_held(&ntbl->rwlock));
+                                              lockdep_is_held(&priv->lock));
             neigh != NULL;
             neigh = rcu_dereference_protected(neigh->hnext,
-                                              lockdep_is_held(&ntbl->rwlock))) {
+                                              lockdep_is_held(&priv->lock))) {
                if (memcmp(daddr, neigh->daddr, INFINIBAND_ALEN) == 0) {
                        /* found, take one ref on behalf of the caller */
                        if (!atomic_inc_not_zero(&neigh->refcnt)) {
@@ -987,12 +983,11 @@ struct ipoib_neigh *ipoib_neigh_alloc(u8 *daddr,
        /* put in hash */
        rcu_assign_pointer(neigh->hnext,
                           rcu_dereference_protected(htbl->buckets[hash_val],
-                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                    lockdep_is_held(&priv->lock)));
        rcu_assign_pointer(htbl->buckets[hash_val], neigh);
        atomic_inc(&ntbl->entries);
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
 
        return neigh;
 }
@@ -1040,35 +1035,29 @@ void ipoib_neigh_free(struct ipoib_neigh *neigh)
        struct ipoib_neigh *n;
        u32 hash_val;
 
-       write_lock_bh(&ntbl->rwlock);
-
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                       lockdep_is_held(&ntbl->rwlock));
+                                       lockdep_is_held(&priv->lock));
        if (!htbl)
-               goto out_unlock;
+               return;
 
        hash_val = ipoib_addr_hash(htbl, neigh->daddr);
        np = &htbl->buckets[hash_val];
        for (n = rcu_dereference_protected(*np,
-                                           lockdep_is_held(&ntbl->rwlock));
+                                           lockdep_is_held(&priv->lock));
             n != NULL;
             n = rcu_dereference_protected(*np,
-                                       lockdep_is_held(&ntbl->rwlock))) {
+                                       lockdep_is_held(&priv->lock))) {
                if (n == neigh) {
                        /* found */
                        rcu_assign_pointer(*np,
                                           rcu_dereference_protected(neigh->hnext,
-                                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                                    lockdep_is_held(&priv->lock)));
                        call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
-                       goto out_unlock;
+                       return;
                } else {
                        np = &n->hnext;
                }
        }
-
-out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
-
 }
 
 static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
@@ -1080,7 +1069,6 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
 
        clear_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
        ntbl->htbl = NULL;
-       rwlock_init(&ntbl->rwlock);
        htbl = kzalloc(sizeof(*htbl), GFP_KERNEL);
        if (!htbl)
                return -ENOMEM;
@@ -1095,6 +1083,7 @@ static int ipoib_neigh_hash_init(struct ipoib_dev_priv *priv)
        htbl->mask = (size - 1);
        htbl->buckets = buckets;
        ntbl->htbl = htbl;
+       htbl->ntbl = ntbl;
        atomic_set(&ntbl->entries, 0);
 
        /* start garbage collection */
@@ -1111,9 +1100,11 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
                                                    struct ipoib_neigh_hash,
                                                    rcu);
        struct ipoib_neigh __rcu **buckets = htbl->buckets;
+       struct ipoib_neigh_table *ntbl = htbl->ntbl;
 
        kfree(buckets);
        kfree(htbl);
+       complete(&ntbl->deleted);
 }
 
 void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
@@ -1125,10 +1116,10 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
        int i;
 
        /* remove all neigh connected to a given path or mcast */
-       write_lock_bh(&ntbl->rwlock);
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                        lockdep_is_held(&ntbl->rwlock));
+                                        lockdep_is_held(&priv->lock));
 
        if (!htbl)
                goto out_unlock;
@@ -1138,16 +1129,14 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                                         lockdep_is_held(&priv->lock))) != NULL) {
                        /* delete neighs belong to this parent */
                        if (!memcmp(gid, neigh->daddr + 4, sizeof (union ib_gid))) {
                                rcu_assign_pointer(*np,
                                                   rcu_dereference_protected(neigh->hnext,
-                                                                            lockdep_is_held(&ntbl->rwlock)));
+                                                                            lockdep_is_held(&priv->lock)));
                                /* remove from parent list */
-                               spin_lock_irqsave(&priv->lock, flags);
                                list_del(&neigh->list);
-                               spin_unlock_irqrestore(&priv->lock, flags);
                                call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                        } else {
                                np = &neigh->hnext;
@@ -1156,7 +1145,7 @@ void ipoib_del_neighs_by_gid(struct net_device *dev, u8 *gid)
                }
        }
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
 }
 
 static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)
@@ -1164,37 +1153,44 @@ static void ipoib_flush_neighs(struct ipoib_dev_priv *priv)
        struct ipoib_neigh_table *ntbl = &priv->ntbl;
        struct ipoib_neigh_hash *htbl;
        unsigned long flags;
-       int i;
+       int i, wait_flushed = 0;
 
-       write_lock_bh(&ntbl->rwlock);
+       init_completion(&priv->ntbl.flushed);
+
+       spin_lock_irqsave(&priv->lock, flags);
 
        htbl = rcu_dereference_protected(ntbl->htbl,
-                                       lockdep_is_held(&ntbl->rwlock));
+                                       lockdep_is_held(&priv->lock));
        if (!htbl)
                goto out_unlock;
 
+       wait_flushed = atomic_read(&priv->ntbl.entries);
+       if (!wait_flushed)
+               goto free_htbl;
+
        for (i = 0; i < htbl->size; i++) {
                struct ipoib_neigh *neigh;
                struct ipoib_neigh __rcu **np = &htbl->buckets[i];
 
                while ((neigh = rcu_dereference_protected(*np,
-                                                         lockdep_is_held(&ntbl->rwlock))) != NULL) {
+                                      lockdep_is_held(&priv->lock))) != NULL) {
                        rcu_assign_pointer(*np,
                                           rcu_dereference_protected(neigh->hnext,
-                                                                    lockdep_is_held(&ntbl->rwlock)));
+                                                                    lockdep_is_held(&priv->lock)));
                        /* remove from path/mc list */
-                       spin_lock_irqsave(&priv->lock, flags);
                        list_del(&neigh->list);
-                       spin_unlock_irqrestore(&priv->lock, flags);
                        call_rcu(&neigh->rcu, ipoib_neigh_reclaim);
                }
        }
 
+free_htbl:
        rcu_assign_pointer(ntbl->htbl, NULL);
        call_rcu(&htbl->rcu, neigh_hash_free_rcu);
 
 out_unlock:
-       write_unlock_bh(&ntbl->rwlock);
+       spin_unlock_irqrestore(&priv->lock, flags);
+       if (wait_flushed)
+               wait_for_completion(&priv->ntbl.flushed);
 }
 
 static void ipoib_neigh_hash_uninit(struct net_device *dev)
@@ -1203,7 +1199,7 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
        int stopped;
 
        ipoib_dbg(priv, "ipoib_neigh_hash_uninit\n");
-       init_completion(&priv->ntbl.flushed);
+       init_completion(&priv->ntbl.deleted);
        set_bit(IPOIB_NEIGH_TBL_FLUSH, &priv->flags);
 
        /* Stop GC if called at init fail need to cancel work */
@@ -1211,10 +1207,9 @@ static void ipoib_neigh_hash_uninit(struct net_device *dev)
        if (!stopped)
                cancel_delayed_work(&priv->neigh_reap_task);
 
-       if (atomic_read(&priv->ntbl.entries)) {
-               ipoib_flush_neighs(priv);
-               wait_for_completion(&priv->ntbl.flushed);
-       }
+       ipoib_flush_neighs(priv);
+
+       wait_for_completion(&priv->ntbl.deleted);
 }
 
 
index 13f4aa7593c834f2ee1475c6471cad8e0bcd12f8..75367249f447f497851e76a0a4312b6000989ff2 100644 (file)
@@ -707,9 +707,7 @@ out:
                neigh = ipoib_neigh_get(dev, daddr);
                spin_lock_irqsave(&priv->lock, flags);
                if (!neigh) {
-                       spin_unlock_irqrestore(&priv->lock, flags);
                        neigh = ipoib_neigh_alloc(daddr, dev);
-                       spin_lock_irqsave(&priv->lock, flags);
                        if (neigh) {
                                kref_get(&mcast->ah->ref);
                                neigh->ah       = mcast->ah;
index ff4c0a87a25f9804441ac90561e7c97e24610e85..cdc252612c0b35c453b976355c13b26f6d6767e1 100644 (file)
@@ -358,6 +358,7 @@ static void imx_keypad_inhibit(struct imx_keypad *keypad)
        /* Inhibit KDI and KRI interrupts. */
        reg_val = readw(keypad->mmio_base + KPSR);
        reg_val &= ~(KBD_STAT_KRIE | KBD_STAT_KDIE);
+       reg_val |= KBD_STAT_KPKR | KBD_STAT_KPKD;
        writew(reg_val, keypad->mmio_base + KPSR);
 
        /* Colums as open drain and disable all rows */
@@ -515,7 +516,9 @@ static int __devinit imx_keypad_probe(struct platform_device *pdev)
        input_set_drvdata(input_dev, keypad);
 
        /* Ensure that the keypad will stay dormant until opened */
+       clk_prepare_enable(keypad->clk);
        imx_keypad_inhibit(keypad);
+       clk_disable_unprepare(keypad->clk);
 
        error = request_irq(irq, imx_keypad_irq_handler, 0,
                            pdev->name, keypad);
index f06231b7cab1ef762d7ad5db073b3a6b64d39987..84ec691c05aa983751492a8dff29c5ca87b27ad2 100644 (file)
@@ -74,8 +74,8 @@ static int __devinit ab8500_ponkey_probe(struct platform_device *pdev)
 
        ponkey->idev = input;
        ponkey->ab8500 = ab8500;
-       ponkey->irq_dbf = ab8500_irq_get_virq(ab8500, irq_dbf);
-       ponkey->irq_dbr = ab8500_irq_get_virq(ab8500, irq_dbr);
+       ponkey->irq_dbf = irq_dbf;
+       ponkey->irq_dbr = irq_dbr;
 
        input->name = "AB8500 POn(PowerOn) Key";
        input->dev.parent = &pdev->dev;
index 3f5649f190824408a25c495bdfd4da88b8febe9a..a261d857691957a98e732124f6370c6f8280451a 100644 (file)
@@ -721,6 +721,17 @@ static psmouse_ret_t fsp_process_byte(struct psmouse *psmouse)
 
        switch (psmouse->packet[0] >> FSP_PKT_TYPE_SHIFT) {
        case FSP_PKT_TYPE_ABS:
+
+               if ((packet[0] == 0x48 || packet[0] == 0x49) &&
+                   packet[1] == 0 && packet[2] == 0) {
+                       /*
+                        * Ignore coordinate noise when finger leaving the
+                        * surface, otherwise cursor may jump to upper-left
+                        * corner.
+                        */
+                       packet[3] &= 0xf0;
+               }
+
                abs_x = GET_ABS_X(packet);
                abs_y = GET_ABS_Y(packet);
 
index 2ffd110bd5bc756e461051d39ba31238202a0fa7..2e77246c2e5ac8293569ecd19fe1df673c394c75 100644 (file)
@@ -72,7 +72,7 @@ static int amba_kmi_open(struct serio *io)
        unsigned int divisor;
        int ret;
 
-       ret = clk_enable(kmi->clk);
+       ret = clk_prepare_enable(kmi->clk);
        if (ret)
                goto out;
 
@@ -92,7 +92,7 @@ static int amba_kmi_open(struct serio *io)
        return 0;
 
  clk_disable:
-       clk_disable(kmi->clk);
+       clk_disable_unprepare(kmi->clk);
  out:
        return ret;
 }
@@ -104,7 +104,7 @@ static void amba_kmi_close(struct serio *io)
        writeb(0, KMICR);
 
        free_irq(kmi->irq, kmi);
-       clk_disable(kmi->clk);
+       clk_disable_unprepare(kmi->clk);
 }
 
 static int __devinit amba_kmi_probe(struct amba_device *dev,
index 5ec774d6c82b4be13f06c97efffe7cc42860ebab..d6cc77a53c7e2bdbe94ee3c138ab8c86f0d90135 100644 (file)
@@ -176,6 +176,20 @@ static const struct dmi_system_id __initconst i8042_dmi_noloop_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "Spring Peak"),
                },
        },
+       {
+               /* Gigabyte T1005 - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005"),
+               },
+       },
+       {
+               /* Gigabyte T1005M/P - defines wrong chassis type ("Other") */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "GIGABYTE"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "T1005M/P"),
+               },
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "Hewlett-Packard"),
@@ -319,6 +333,12 @@ static const struct dmi_system_id __initconst i8042_dmi_nomux_table[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "EQUIUM A110"),
                },
        },
+       {
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "TOSHIBA"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "SATELLITE C850D"),
+               },
+       },
        {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "ALIENWARE"),
index 002041975de9c902f193f2448865d051f0ce98dc..532d067a9e07a0745188eb3dab8e4025ef7b664f 100644 (file)
@@ -1848,7 +1848,10 @@ static const struct wacom_features wacom_features_0x2A =
        { "Wacom Intuos5 M", WACOM_PKGLEN_INTUOS,  44704, 27940, 2047,
          63, INTUOS5, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0xF4 =
-       { "Wacom Cintiq 24HD",    WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+       { "Wacom Cintiq 24HD",       WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
+         63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
+static const struct wacom_features wacom_features_0xF8 =
+       { "Wacom Cintiq 24HD touch", WACOM_PKGLEN_INTUOS,   104480, 65600, 2047,
          63, WACOM_24HD, WACOM_INTUOS3_RES, WACOM_INTUOS3_RES };
 static const struct wacom_features wacom_features_0x3F =
        { "Wacom Cintiq 21UX",    WACOM_PKGLEN_INTUOS,    87200, 65600, 1023,
@@ -2091,6 +2094,7 @@ const struct usb_device_id wacom_ids[] = {
        { USB_DEVICE_WACOM(0xEF) },
        { USB_DEVICE_WACOM(0x47) },
        { USB_DEVICE_WACOM(0xF4) },
+       { USB_DEVICE_WACOM(0xF8) },
        { USB_DEVICE_WACOM(0xFA) },
        { USB_DEVICE_LENOVO(0x6004) },
        { }
index 9afc777a40a7077a5bbd667944f1c1ee3bac38d7..64957770b52209fcc527e3f015e21816b3165bc7 100644 (file)
@@ -566,9 +566,12 @@ static ssize_t edt_ft5x06_debugfs_raw_data_read(struct file *file,
        }
 
        read = min_t(size_t, count, tsdata->raw_bufsize - *off);
-       error = copy_to_user(buf, tsdata->raw_buffer + *off, read);
-       if (!error)
-               *off += read;
+       if (copy_to_user(buf, tsdata->raw_buffer + *off, read)) {
+               error = -EFAULT;
+               goto out;
+       }
+
+       *off += read;
 out:
        mutex_unlock(&tsdata->mutex);
        return error ?: read;
@@ -602,6 +605,7 @@ edt_ft5x06_ts_teardown_debugfs(struct edt_ft5x06_ts_data *tsdata)
 {
        if (tsdata->debug_dir)
                debugfs_remove_recursive(tsdata->debug_dir);
+       kfree(tsdata->raw_buffer);
 }
 
 #else
@@ -843,7 +847,6 @@ static int __devexit edt_ft5x06_ts_remove(struct i2c_client *client)
        if (gpio_is_valid(pdata->reset_pin))
                gpio_free(pdata->reset_pin);
 
-       kfree(tsdata->raw_buffer);
        kfree(tsdata);
 
        return 0;
index e32709e0dd65193286bccc2e81bd4e86d717c643..721fdb3597ca9d9ecb3f971f389f6852395ff39c 100644 (file)
@@ -304,6 +304,45 @@ static int e2i_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 #define EGALAX_PKT_TYPE_REPT           0x80
 #define EGALAX_PKT_TYPE_DIAG           0x0A
 
+static int egalax_init(struct usbtouch_usb *usbtouch)
+{
+       int ret, i;
+       unsigned char *buf;
+       struct usb_device *udev = interface_to_usbdev(usbtouch->interface);
+
+       /*
+        * An eGalax diagnostic packet kicks the device into using the right
+        * protocol.  We send a "check active" packet.  The response will be
+        * read later and ignored.
+        */
+
+       buf = kmalloc(3, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       buf[0] = EGALAX_PKT_TYPE_DIAG;
+       buf[1] = 1;     /* length */
+       buf[2] = 'A';   /* command - check active */
+
+       for (i = 0; i < 3; i++) {
+               ret = usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                                     0,
+                                     USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                                     0, 0, buf, 3,
+                                     USB_CTRL_SET_TIMEOUT);
+               if (ret >= 0) {
+                       ret = 0;
+                       break;
+               }
+               if (ret != -EPIPE)
+                       break;
+       }
+
+       kfree(buf);
+
+       return ret;
+}
+
 static int egalax_read_data(struct usbtouch_usb *dev, unsigned char *pkt)
 {
        if ((pkt[0] & EGALAX_PKT_TYPE_MASK) != EGALAX_PKT_TYPE_REPT)
@@ -1056,6 +1095,7 @@ static struct usbtouch_device_info usbtouch_dev_info[] = {
                .process_pkt    = usbtouch_process_multi,
                .get_pkt_len    = egalax_get_pkt_len,
                .read_data      = egalax_read_data,
+               .init           = egalax_init,
        },
 #endif
 
index b64502dfa9f4567ca028bcb9b7913d4b38696019..e89daf1b21b49159e549ce863f45dd72e39b1b56 100644 (file)
@@ -266,7 +266,7 @@ static void swap_pci_ref(struct pci_dev **from, struct pci_dev *to)
 
 static int iommu_init_device(struct device *dev)
 {
-       struct pci_dev *dma_pdev, *pdev = to_pci_dev(dev);
+       struct pci_dev *dma_pdev = NULL, *pdev = to_pci_dev(dev);
        struct iommu_dev_data *dev_data;
        struct iommu_group *group;
        u16 alias;
@@ -293,7 +293,9 @@ static int iommu_init_device(struct device *dev)
                dev_data->alias_data = alias_data;
 
                dma_pdev = pci_get_bus_and_slot(alias >> 8, alias & 0xff);
-       } else
+       }
+
+       if (dma_pdev == NULL)
                dma_pdev = pci_dev_get(pdev);
 
        /* Account for quirked devices */
index fa6ca473372539fda128a7a1ec46d9c4d13c3c4a..dceaec821b0e5324cbfa2d92bdb7334845bf9262 100644 (file)
@@ -857,8 +857,9 @@ avm_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&fc->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                modehdlc(bch, ISDN_P_NONE);
                spin_unlock_irqrestore(&fc->lock, flags);
                ch->protocol = ISDN_P_NONE;
index 5e402cf2e79506b82288140334da60eb4e923e6d..f02794203bb193b41291efc3bc6d8457b2043883 100644 (file)
@@ -5059,6 +5059,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
                                printk(KERN_INFO
                                       "HFC-E1 #%d has overlapping B-channels on fragment #%d\n",
                                       E1_cnt + 1, pt);
+                               kfree(hc);
                                return -EINVAL;
                        }
                        maskcheck |= hc->bmask[pt];
@@ -5086,6 +5087,7 @@ hfcmulti_init(struct hm_map *m, struct pci_dev *pdev,
        if ((poll >> 1) > sizeof(hc->silence_data)) {
                printk(KERN_ERR "HFCMULTI error: silence_data too small, "
                       "please fix\n");
+               kfree(hc);
                return -EINVAL;
        }
        for (i = 0; i < (poll >> 1); i++)
index 752e0825591fbed9e820044495d42b9a80842320..ccd7d851be26d27913a26656cdef1fc838c90870 100644 (file)
@@ -1406,8 +1406,9 @@ hscx_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(hx->ip->hwlock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                hscx_mode(hx, ISDN_P_NONE);
                spin_unlock_irqrestore(hx->ip->hwlock, flags);
                ch->protocol = ISDN_P_NONE;
index be5973ded6d6e4288fe8fdebd0967150228ff937..182ecf0626c2098e3c38c4da0eeea54a1197ce7d 100644 (file)
@@ -1588,8 +1588,9 @@ isar_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(ich->is->hwlock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                modeisar(ich, ISDN_P_NONE);
                spin_unlock_irqrestore(ich->is->hwlock, flags);
                ch->protocol = ISDN_P_NONE;
index c3e3e76862731496b6bea5d35b3ca8ef5662e486..9bcade59eb73bdf24f72e8fa5a6e08e4be641f1c 100644 (file)
@@ -812,8 +812,9 @@ nj_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&card->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                mode_tiger(bc, ISDN_P_NONE);
                spin_unlock_irqrestore(&card->lock, flags);
                ch->protocol = ISDN_P_NONE;
index 26a86b8460992e5e98c722f8b6487fb8ff1fe932..335fe6455002c708cfb0be66318b2473f4cdfcc7 100644 (file)
@@ -1054,8 +1054,9 @@ w6692_bctrl(struct mISDNchannel *ch, u32 cmd, void *arg)
        switch (cmd) {
        case CLOSE_CHANNEL:
                test_and_clear_bit(FLG_OPEN, &bch->Flags);
+               cancel_work_sync(&bch->workq);
                spin_lock_irqsave(&card->lock, flags);
-               mISDN_freebchannel(bch);
+               mISDN_clear_bchannel(bch);
                w6692_mode(bc, ISDN_P_NONE);
                spin_unlock_irqrestore(&card->lock, flags);
                ch->protocol = ISDN_P_NONE;
index ef34fd40867cb6b7f5b767542c4da2e173d6b9cc..2602be23f341287468524c9fbd79e33a18e21aa6 100644 (file)
@@ -148,17 +148,16 @@ mISDN_clear_bchannel(struct bchannel *ch)
        ch->next_minlen = ch->init_minlen;
        ch->maxlen = ch->init_maxlen;
        ch->next_maxlen = ch->init_maxlen;
+       skb_queue_purge(&ch->rqueue);
+       ch->rcount = 0;
 }
 EXPORT_SYMBOL(mISDN_clear_bchannel);
 
-int
+void
 mISDN_freebchannel(struct bchannel *ch)
 {
+       cancel_work_sync(&ch->workq);
        mISDN_clear_bchannel(ch);
-       skb_queue_purge(&ch->rqueue);
-       ch->rcount = 0;
-       flush_work_sync(&ch->workq);
-       return 0;
 }
 EXPORT_SYMBOL(mISDN_freebchannel);
 
index d8abb90a6c2fbecae99ae2de09ebc2f3d726731e..034233eefc8266eba122556fc6ffdb36e054eced 100644 (file)
@@ -1555,6 +1555,7 @@ static int multipath_ioctl(struct dm_target *ti, unsigned int cmd,
                           unsigned long arg)
 {
        struct multipath *m = ti->private;
+       struct pgpath *pgpath;
        struct block_device *bdev;
        fmode_t mode;
        unsigned long flags;
@@ -1570,12 +1571,14 @@ again:
        if (!m->current_pgpath)
                __choose_pgpath(m, 0);
 
-       if (m->current_pgpath) {
-               bdev = m->current_pgpath->path.dev->bdev;
-               mode = m->current_pgpath->path.dev->mode;
+       pgpath = m->current_pgpath;
+
+       if (pgpath) {
+               bdev = pgpath->path.dev->bdev;
+               mode = pgpath->path.dev->mode;
        }
 
-       if (m->queue_io)
+       if ((pgpath && m->queue_io) || (!pgpath && m->queue_if_no_path))
                r = -EAGAIN;
        else if (!bdev)
                r = -EIO;
index f90069029aaeed02ab6f4f61814afc92d13db2f0..100368eb7991a50c57e473ea20bf4a8441e91ff0 100644 (file)
@@ -1212,6 +1212,41 @@ struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector)
        return &t->targets[(KEYS_PER_NODE * n) + k];
 }
 
+static int count_device(struct dm_target *ti, struct dm_dev *dev,
+                       sector_t start, sector_t len, void *data)
+{
+       unsigned *num_devices = data;
+
+       (*num_devices)++;
+
+       return 0;
+}
+
+/*
+ * Check whether a table has no data devices attached using each
+ * target's iterate_devices method.
+ * Returns false if the result is unknown because a target doesn't
+ * support iterate_devices.
+ */
+bool dm_table_has_no_data_devices(struct dm_table *table)
+{
+       struct dm_target *uninitialized_var(ti);
+       unsigned i = 0, num_devices = 0;
+
+       while (i < dm_table_get_num_targets(table)) {
+               ti = dm_table_get_target(table, i++);
+
+               if (!ti->type->iterate_devices)
+                       return false;
+
+               ti->type->iterate_devices(ti, count_device, &num_devices);
+               if (num_devices)
+                       return false;
+       }
+
+       return true;
+}
+
 /*
  * Establish the new table's queue_limits and validate them.
  */
@@ -1354,17 +1389,25 @@ static int device_is_nonrot(struct dm_target *ti, struct dm_dev *dev,
        return q && blk_queue_nonrot(q);
 }
 
-static bool dm_table_is_nonrot(struct dm_table *t)
+static int device_is_not_random(struct dm_target *ti, struct dm_dev *dev,
+                            sector_t start, sector_t len, void *data)
+{
+       struct request_queue *q = bdev_get_queue(dev->bdev);
+
+       return q && !blk_queue_add_random(q);
+}
+
+static bool dm_table_all_devices_attribute(struct dm_table *t,
+                                          iterate_devices_callout_fn func)
 {
        struct dm_target *ti;
        unsigned i = 0;
 
-       /* Ensure that all underlying device are non-rotational. */
        while (i < dm_table_get_num_targets(t)) {
                ti = dm_table_get_target(t, i++);
 
                if (!ti->type->iterate_devices ||
-                   !ti->type->iterate_devices(ti, device_is_nonrot, NULL))
+                   !ti->type->iterate_devices(ti, func, NULL))
                        return 0;
        }
 
@@ -1396,13 +1439,23 @@ void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
        if (!dm_table_discard_zeroes_data(t))
                q->limits.discard_zeroes_data = 0;
 
-       if (dm_table_is_nonrot(t))
+       /* Ensure that all underlying devices are non-rotational. */
+       if (dm_table_all_devices_attribute(t, device_is_nonrot))
                queue_flag_set_unlocked(QUEUE_FLAG_NONROT, q);
        else
                queue_flag_clear_unlocked(QUEUE_FLAG_NONROT, q);
 
        dm_table_set_integrity(t);
 
+       /*
+        * Determine whether or not this queue's I/O timings contribute
+        * to the entropy pool, Only request-based targets use this.
+        * Clear QUEUE_FLAG_ADD_RANDOM if any underlying device does not
+        * have it set.
+        */
+       if (blk_queue_add_random(q) && dm_table_all_devices_attribute(t, device_is_not_random))
+               queue_flag_clear_unlocked(QUEUE_FLAG_ADD_RANDOM, q);
+
        /*
         * QUEUE_FLAG_STACKABLE must be set after all queue settings are
         * visible to other CPUs because, once the flag is set, incoming bios
index af1fc3b2c2adbb365e247a2d45c1f7a94de9b6dd..c29410af1e2211cbba6029a16128e2fabbf97976 100644 (file)
@@ -509,9 +509,9 @@ enum pool_mode {
 struct pool_features {
        enum pool_mode mode;
 
-       unsigned zero_new_blocks:1;
-       unsigned discard_enabled:1;
-       unsigned discard_passdown:1;
+       bool zero_new_blocks:1;
+       bool discard_enabled:1;
+       bool discard_passdown:1;
 };
 
 struct thin_c;
@@ -580,7 +580,8 @@ struct pool_c {
        struct dm_target_callbacks callbacks;
 
        dm_block_t low_water_blocks;
-       struct pool_features pf;
+       struct pool_features requested_pf; /* Features requested during table load */
+       struct pool_features adjusted_pf;  /* Features used after adjusting for constituent devices */
 };
 
 /*
@@ -1839,6 +1840,47 @@ static void __requeue_bios(struct pool *pool)
 /*----------------------------------------------------------------
  * Binding of control targets to a pool object
  *--------------------------------------------------------------*/
+static bool data_dev_supports_discard(struct pool_c *pt)
+{
+       struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
+
+       return q && blk_queue_discard(q);
+}
+
+/*
+ * If discard_passdown was enabled verify that the data device
+ * supports discards.  Disable discard_passdown if not.
+ */
+static void disable_passdown_if_not_supported(struct pool_c *pt)
+{
+       struct pool *pool = pt->pool;
+       struct block_device *data_bdev = pt->data_dev->bdev;
+       struct queue_limits *data_limits = &bdev_get_queue(data_bdev)->limits;
+       sector_t block_size = pool->sectors_per_block << SECTOR_SHIFT;
+       const char *reason = NULL;
+       char buf[BDEVNAME_SIZE];
+
+       if (!pt->adjusted_pf.discard_passdown)
+               return;
+
+       if (!data_dev_supports_discard(pt))
+               reason = "discard unsupported";
+
+       else if (data_limits->max_discard_sectors < pool->sectors_per_block)
+               reason = "max discard sectors smaller than a block";
+
+       else if (data_limits->discard_granularity > block_size)
+               reason = "discard granularity larger than a block";
+
+       else if (block_size & (data_limits->discard_granularity - 1))
+               reason = "discard granularity not a factor of block size";
+
+       if (reason) {
+               DMWARN("Data device (%s) %s: Disabling discard passdown.", bdevname(data_bdev, buf), reason);
+               pt->adjusted_pf.discard_passdown = false;
+       }
+}
+
 static int bind_control_target(struct pool *pool, struct dm_target *ti)
 {
        struct pool_c *pt = ti->private;
@@ -1847,31 +1889,16 @@ static int bind_control_target(struct pool *pool, struct dm_target *ti)
         * We want to make sure that degraded pools are never upgraded.
         */
        enum pool_mode old_mode = pool->pf.mode;
-       enum pool_mode new_mode = pt->pf.mode;
+       enum pool_mode new_mode = pt->adjusted_pf.mode;
 
        if (old_mode > new_mode)
                new_mode = old_mode;
 
        pool->ti = ti;
        pool->low_water_blocks = pt->low_water_blocks;
-       pool->pf = pt->pf;
-       set_pool_mode(pool, new_mode);
+       pool->pf = pt->adjusted_pf;
 
-       /*
-        * If discard_passdown was enabled verify that the data device
-        * supports discards.  Disable discard_passdown if not; otherwise
-        * -EOPNOTSUPP will be returned.
-        */
-       /* FIXME: pull this out into a sep fn. */
-       if (pt->pf.discard_passdown) {
-               struct request_queue *q = bdev_get_queue(pt->data_dev->bdev);
-               if (!q || !blk_queue_discard(q)) {
-                       char buf[BDEVNAME_SIZE];
-                       DMWARN("Discard unsupported by data device (%s): Disabling discard passdown.",
-                              bdevname(pt->data_dev->bdev, buf));
-                       pool->pf.discard_passdown = 0;
-               }
-       }
+       set_pool_mode(pool, new_mode);
 
        return 0;
 }
@@ -1889,9 +1916,9 @@ static void unbind_control_target(struct pool *pool, struct dm_target *ti)
 static void pool_features_init(struct pool_features *pf)
 {
        pf->mode = PM_WRITE;
-       pf->zero_new_blocks = 1;
-       pf->discard_enabled = 1;
-       pf->discard_passdown = 1;
+       pf->zero_new_blocks = true;
+       pf->discard_enabled = true;
+       pf->discard_passdown = true;
 }
 
 static void __pool_destroy(struct pool *pool)
@@ -2119,13 +2146,13 @@ static int parse_pool_features(struct dm_arg_set *as, struct pool_features *pf,
                argc--;
 
                if (!strcasecmp(arg_name, "skip_block_zeroing"))
-                       pf->zero_new_blocks = 0;
+                       pf->zero_new_blocks = false;
 
                else if (!strcasecmp(arg_name, "ignore_discard"))
-                       pf->discard_enabled = 0;
+                       pf->discard_enabled = false;
 
                else if (!strcasecmp(arg_name, "no_discard_passdown"))
-                       pf->discard_passdown = 0;
+                       pf->discard_passdown = false;
 
                else if (!strcasecmp(arg_name, "read_only"))
                        pf->mode = PM_READ_ONLY;
@@ -2259,8 +2286,9 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
        pt->metadata_dev = metadata_dev;
        pt->data_dev = data_dev;
        pt->low_water_blocks = low_water_blocks;
-       pt->pf = pf;
+       pt->adjusted_pf = pt->requested_pf = pf;
        ti->num_flush_requests = 1;
+
        /*
         * Only need to enable discards if the pool should pass
         * them down to the data device.  The thin device's discard
@@ -2268,12 +2296,14 @@ static int pool_ctr(struct dm_target *ti, unsigned argc, char **argv)
         */
        if (pf.discard_enabled && pf.discard_passdown) {
                ti->num_discard_requests = 1;
+
                /*
                 * Setting 'discards_supported' circumvents the normal
                 * stacking of discard limits (this keeps the pool and
                 * thin devices' discard limits consistent).
                 */
                ti->discards_supported = true;
+               ti->discard_zeroes_data_unsupported = true;
        }
        ti->private = pt;
 
@@ -2703,7 +2733,7 @@ static int pool_status(struct dm_target *ti, status_type_t type,
                       format_dev_t(buf2, pt->data_dev->bdev->bd_dev),
                       (unsigned long)pool->sectors_per_block,
                       (unsigned long long)pt->low_water_blocks);
-               emit_flags(&pt->pf, result, sz, maxlen);
+               emit_flags(&pt->requested_pf, result, sz, maxlen);
                break;
        }
 
@@ -2732,20 +2762,21 @@ static int pool_merge(struct dm_target *ti, struct bvec_merge_data *bvm,
        return min(max_size, q->merge_bvec_fn(q, bvm, biovec));
 }
 
-static void set_discard_limits(struct pool *pool, struct queue_limits *limits)
+static void set_discard_limits(struct pool_c *pt, struct queue_limits *limits)
 {
-       /*
-        * FIXME: these limits may be incompatible with the pool's data device
-        */
+       struct pool *pool = pt->pool;
+       struct queue_limits *data_limits;
+
        limits->max_discard_sectors = pool->sectors_per_block;
 
        /*
-        * This is just a hint, and not enforced.  We have to cope with
-        * bios that cover a block partially.  A discard that spans a block
-        * boundary is not sent to this target.
+        * discard_granularity is just a hint, and not enforced.
         */
-       limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
-       limits->discard_zeroes_data = pool->pf.zero_new_blocks;
+       if (pt->adjusted_pf.discard_passdown) {
+               data_limits = &bdev_get_queue(pt->data_dev->bdev)->limits;
+               limits->discard_granularity = data_limits->discard_granularity;
+       } else
+               limits->discard_granularity = pool->sectors_per_block << SECTOR_SHIFT;
 }
 
 static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
@@ -2755,15 +2786,25 @@ static void pool_io_hints(struct dm_target *ti, struct queue_limits *limits)
 
        blk_limits_io_min(limits, 0);
        blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
-       if (pool->pf.discard_enabled)
-               set_discard_limits(pool, limits);
+
+       /*
+        * pt->adjusted_pf is a staging area for the actual features to use.
+        * They get transferred to the live pool in bind_control_target()
+        * called from pool_preresume().
+        */
+       if (!pt->adjusted_pf.discard_enabled)
+               return;
+
+       disable_passdown_if_not_supported(pt);
+
+       set_discard_limits(pt, limits);
 }
 
 static struct target_type pool_target = {
        .name = "thin-pool",
        .features = DM_TARGET_SINGLETON | DM_TARGET_ALWAYS_WRITEABLE |
                    DM_TARGET_IMMUTABLE,
-       .version = {1, 3, 0},
+       .version = {1, 4, 0},
        .module = THIS_MODULE,
        .ctr = pool_ctr,
        .dtr = pool_dtr,
@@ -3042,19 +3083,19 @@ static int thin_iterate_devices(struct dm_target *ti,
        return 0;
 }
 
+/*
+ * A thin device always inherits its queue limits from its pool.
+ */
 static void thin_io_hints(struct dm_target *ti, struct queue_limits *limits)
 {
        struct thin_c *tc = ti->private;
-       struct pool *pool = tc->pool;
 
-       blk_limits_io_min(limits, 0);
-       blk_limits_io_opt(limits, pool->sectors_per_block << SECTOR_SHIFT);
-       set_discard_limits(pool, limits);
+       *limits = bdev_get_queue(tc->pool_dev->bdev)->limits;
 }
 
 static struct target_type thin_target = {
        .name = "thin",
-       .version = {1, 3, 0},
+       .version = {1, 4, 0},
        .module = THIS_MODULE,
        .ctr = thin_ctr,
        .dtr = thin_dtr,
index 254d19268ad2fa0c7102014c997b75294450ba42..892ae2766aa6adad52b6d99030a1d8d3bcf2ac38 100644 (file)
@@ -718,8 +718,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        v->hash_dev_block_bits = ffs(num) - 1;
 
        if (sscanf(argv[5], "%llu%c", &num_ll, &dummy) != 1 ||
-           num_ll << (v->data_dev_block_bits - SECTOR_SHIFT) !=
-           (sector_t)num_ll << (v->data_dev_block_bits - SECTOR_SHIFT)) {
+           (sector_t)(num_ll << (v->data_dev_block_bits - SECTOR_SHIFT))
+           >> (v->data_dev_block_bits - SECTOR_SHIFT) != num_ll) {
                ti->error = "Invalid data blocks";
                r = -EINVAL;
                goto bad;
@@ -733,8 +733,8 @@ static int verity_ctr(struct dm_target *ti, unsigned argc, char **argv)
        }
 
        if (sscanf(argv[6], "%llu%c", &num_ll, &dummy) != 1 ||
-           num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT) !=
-           (sector_t)num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT)) {
+           (sector_t)(num_ll << (v->hash_dev_block_bits - SECTOR_SHIFT))
+           >> (v->hash_dev_block_bits - SECTOR_SHIFT) != num_ll) {
                ti->error = "Invalid hash start";
                r = -EINVAL;
                goto bad;
index 4e09b6ff5b493403d4e51be0b4fee2d99643e276..67ffa391edcf1e70a0cc94e7085a1e99abd7a151 100644 (file)
@@ -865,10 +865,14 @@ static void dm_done(struct request *clone, int error, bool mapped)
 {
        int r = error;
        struct dm_rq_target_io *tio = clone->end_io_data;
-       dm_request_endio_fn rq_end_io = tio->ti->type->rq_end_io;
+       dm_request_endio_fn rq_end_io = NULL;
 
-       if (mapped && rq_end_io)
-               r = rq_end_io(tio->ti, clone, error, &tio->info);
+       if (tio->ti) {
+               rq_end_io = tio->ti->type->rq_end_io;
+
+               if (mapped && rq_end_io)
+                       r = rq_end_io(tio->ti, clone, error, &tio->info);
+       }
 
        if (r <= 0)
                /* The target wants to complete the I/O */
@@ -1588,15 +1592,6 @@ static int map_request(struct dm_target *ti, struct request *clone,
        int r, requeued = 0;
        struct dm_rq_target_io *tio = clone->end_io_data;
 
-       /*
-        * Hold the md reference here for the in-flight I/O.
-        * We can't rely on the reference count by device opener,
-        * because the device may be closed during the request completion
-        * when all bios are completed.
-        * See the comment in rq_completed() too.
-        */
-       dm_get(md);
-
        tio->ti = ti;
        r = ti->type->map_rq(ti, clone, &tio->info);
        switch (r) {
@@ -1628,6 +1623,26 @@ static int map_request(struct dm_target *ti, struct request *clone,
        return requeued;
 }
 
+static struct request *dm_start_request(struct mapped_device *md, struct request *orig)
+{
+       struct request *clone;
+
+       blk_start_request(orig);
+       clone = orig->special;
+       atomic_inc(&md->pending[rq_data_dir(clone)]);
+
+       /*
+        * Hold the md reference here for the in-flight I/O.
+        * We can't rely on the reference count by device opener,
+        * because the device may be closed during the request completion
+        * when all bios are completed.
+        * See the comment in rq_completed() too.
+        */
+       dm_get(md);
+
+       return clone;
+}
+
 /*
  * q->request_fn for request-based dm.
  * Called with the queue lock held.
@@ -1657,14 +1672,21 @@ static void dm_request_fn(struct request_queue *q)
                        pos = blk_rq_pos(rq);
 
                ti = dm_table_find_target(map, pos);
-               BUG_ON(!dm_target_is_valid(ti));
+               if (!dm_target_is_valid(ti)) {
+                       /*
+                        * Must perform setup, that dm_done() requires,
+                        * before calling dm_kill_unmapped_request
+                        */
+                       DMERR_LIMIT("request attempted access beyond the end of device");
+                       clone = dm_start_request(md, rq);
+                       dm_kill_unmapped_request(clone, -EIO);
+                       continue;
+               }
 
                if (ti->type->busy && ti->type->busy(ti))
                        goto delay_and_out;
 
-               blk_start_request(rq);
-               clone = rq->special;
-               atomic_inc(&md->pending[rq_data_dir(clone)]);
+               clone = dm_start_request(md, rq);
 
                spin_unlock(q->queue_lock);
                if (map_request(ti, clone, md))
@@ -1684,8 +1706,6 @@ delay_and_out:
        blk_delay_queue(q, HZ / 10);
 out:
        dm_table_put(map);
-
-       return;
 }
 
 int dm_underlying_device_busy(struct request_queue *q)
@@ -2409,7 +2429,7 @@ static void dm_queue_flush(struct mapped_device *md)
  */
 struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
 {
-       struct dm_table *map = ERR_PTR(-EINVAL);
+       struct dm_table *live_map, *map = ERR_PTR(-EINVAL);
        struct queue_limits limits;
        int r;
 
@@ -2419,6 +2439,19 @@ struct dm_table *dm_swap_table(struct mapped_device *md, struct dm_table *table)
        if (!dm_suspended_md(md))
                goto out;
 
+       /*
+        * If the new table has no data devices, retain the existing limits.
+        * This helps multipath with queue_if_no_path if all paths disappear,
+        * then new I/O is queued based on these limits, and then some paths
+        * reappear.
+        */
+       if (dm_table_has_no_data_devices(table)) {
+               live_map = dm_get_live_table(md);
+               if (live_map)
+                       limits = md->queue->limits;
+               dm_table_put(live_map);
+       }
+
        r = dm_calculate_queue_limits(table, &limits);
        if (r) {
                map = ERR_PTR(r);
index 52eef493d2669290eaa3f2a22e46717dac9aa1eb..6a99fefaa74306aa6e586c47c3eacf33706556b1 100644 (file)
@@ -54,6 +54,7 @@ void dm_table_event_callback(struct dm_table *t,
                             void (*fn)(void *), void *context);
 struct dm_target *dm_table_get_target(struct dm_table *t, unsigned int index);
 struct dm_target *dm_table_find_target(struct dm_table *t, sector_t sector);
+bool dm_table_has_no_data_devices(struct dm_table *table);
 int dm_calculate_queue_limits(struct dm_table *table,
                              struct queue_limits *limits);
 void dm_table_set_restrictions(struct dm_table *t, struct request_queue *q,
index 3f6203a4c7ea0dd730b80a6b441b99e8a4da3216..308e87b417e05a74e4429bac63e1eb2e7af43885 100644 (file)
@@ -7619,6 +7619,8 @@ static int remove_and_add_spares(struct mddev *mddev)
                        }
                }
        }
+       if (removed)
+               set_bit(MD_CHANGE_DEVS, &mddev->flags);
        return spares;
 }
 
@@ -7632,9 +7634,11 @@ static void reap_sync_thread(struct mddev *mddev)
            !test_bit(MD_RECOVERY_REQUESTED, &mddev->recovery)) {
                /* success...*/
                /* activate any spares */
-               if (mddev->pers->spare_active(mddev))
+               if (mddev->pers->spare_active(mddev)) {
                        sysfs_notify(&mddev->kobj, NULL,
                                     "degraded");
+                       set_bit(MD_CHANGE_DEVS, &mddev->flags);
+               }
        }
        if (test_bit(MD_RECOVERY_RESHAPE, &mddev->recovery) &&
            mddev->pers->finish_reshape)
index 1c2eb38f3c51a6dcc93148ca34b1a6a1de7aa465..0138a727c1f3c220bc91a02c9bdf720599465eb9 100644 (file)
@@ -1512,14 +1512,16 @@ static int _enough(struct r10conf *conf, struct geom *geo, int ignore)
        do {
                int n = conf->copies;
                int cnt = 0;
+               int this = first;
                while (n--) {
-                       if (conf->mirrors[first].rdev &&
-                           first != ignore)
+                       if (conf->mirrors[this].rdev &&
+                           this != ignore)
                                cnt++;
-                       first = (first+1) % geo->raid_disks;
+                       this = (this+1) % geo->raid_disks;
                }
                if (cnt == 0)
                        return 0;
+               first = (first + geo->near_copies) % geo->raid_disks;
        } while (first != 0);
        return 1;
 }
index adda94df5eb2352775e64fb7fae4e88c6e89a98b..0689173fd9f568583708c53396631ac8e1838c55 100644 (file)
@@ -393,6 +393,8 @@ static int calc_degraded(struct r5conf *conf)
        degraded = 0;
        for (i = 0; i < conf->previous_raid_disks; i++) {
                struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
+               if (rdev && test_bit(Faulty, &rdev->flags))
+                       rdev = rcu_dereference(conf->disks[i].replacement);
                if (!rdev || test_bit(Faulty, &rdev->flags))
                        degraded++;
                else if (test_bit(In_sync, &rdev->flags))
@@ -417,6 +419,8 @@ static int calc_degraded(struct r5conf *conf)
        degraded2 = 0;
        for (i = 0; i < conf->raid_disks; i++) {
                struct md_rdev *rdev = rcu_dereference(conf->disks[i].rdev);
+               if (rdev && test_bit(Faulty, &rdev->flags))
+                       rdev = rcu_dereference(conf->disks[i].replacement);
                if (!rdev || test_bit(Faulty, &rdev->flags))
                        degraded2++;
                else if (test_bit(In_sync, &rdev->flags))
@@ -1587,6 +1591,7 @@ static int resize_stripes(struct r5conf *conf, int newsize)
                #ifdef CONFIG_MULTICORE_RAID456
                init_waitqueue_head(&nsh->ops.wait_for_ops);
                #endif
+               spin_lock_init(&nsh->stripe_lock);
 
                list_add(&nsh->lru, &newstripes);
        }
@@ -4192,7 +4197,7 @@ static void make_request(struct mddev *mddev, struct bio * bi)
                        finish_wait(&conf->wait_for_overlap, &w);
                        set_bit(STRIPE_HANDLE, &sh->state);
                        clear_bit(STRIPE_DELAYED, &sh->state);
-                       if ((bi->bi_rw & REQ_NOIDLE) &&
+                       if ((bi->bi_rw & REQ_SYNC) &&
                            !test_and_set_bit(STRIPE_PREREAD_ACTIVE, &sh->state))
                                atomic_inc(&conf->preread_active_stripes);
                        release_stripe_plug(mddev, sh);
index d941581ab92169c935a85754c6fc28d2bc2dd79a..dd13e3a4c272965bf23cde32b3409bd28dda6f62 100644 (file)
@@ -99,11 +99,6 @@ config VIDEO_DEV
        depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT
        default y
 
-config VIDEO_V4L2_COMMON
-       tristate
-       depends on (I2C || I2C=n) && VIDEO_DEV
-       default (I2C || I2C=n) && VIDEO_DEV
-
 config VIDEO_V4L2_SUBDEV_API
        bool "V4L2 sub-device userspace API (EXPERIMENTAL)"
        depends on VIDEO_DEV && MEDIA_CONTROLLER && EXPERIMENTAL
@@ -113,6 +108,8 @@ config VIDEO_V4L2_SUBDEV_API
 
          This API is mostly used by camera interfaces in embedded platforms.
 
+source "drivers/media/v4l2-core/Kconfig"
+
 #
 # DVB Core
 #      Only enables if one of DTV is selected
@@ -138,28 +135,54 @@ config DVB_NET
          You may want to disable the network support on embedded devices. If
          unsure say Y.
 
+source "drivers/media/dvb-core/Kconfig"
+
 comment "Media drivers"
-source "drivers/media/common/Kconfig"
 source "drivers/media/rc/Kconfig"
 
 #
-# Tuner drivers for DVB and V4L
+# V4L platform/mem2mem drivers
 #
 
-source "drivers/media/common/tuners/Kconfig"
+source "drivers/media/usb/Kconfig"
+source "drivers/media/pci/Kconfig"
+source "drivers/media/platform/Kconfig"
+source "drivers/media/mmc/Kconfig"
+source "drivers/media/parport/Kconfig"
+source "drivers/media/radio/Kconfig"
+
+comment "Supported FireWire (IEEE 1394) Adapters"
+       depends on DVB_CORE && FIREWIRE
+source "drivers/media/firewire/Kconfig"
+
+# Common driver options
+source "drivers/media/common/Kconfig"
 
 #
-# Video/Radio/Hybrid adapters
+# Ancillary drivers (tuners, i2c, frontends)
 #
 
-source "drivers/media/video/Kconfig"
+config MEDIA_SUBDRV_AUTOSELECT
+       bool "Autoselect analog and hybrid tuner modules to build"
+       depends on MEDIA_TUNER
+       default y
+       help
+         By default, a TV driver auto-selects all possible tuners
+         thar could be used by the driver.
 
-source "drivers/media/radio/Kconfig"
+         This is generally the right thing to do, except when there
+         are strict constraints with regards to the kernel size.
 
-#
-# DVB adapters
-#
+         Use this option with care, as deselecting tuner drivers which
+         are in fact necessary will result in TV devices which cannot
+         be tuned due to lack of the tuning driver.
+
+         If unsure say Y.
+
+comment "Media ancillary drivers (tuners, sensors, i2c, frontends)"
 
-source "drivers/media/dvb/Kconfig"
+source "drivers/media/i2c/Kconfig"
+source "drivers/media/tuners/Kconfig"
+source "drivers/media/dvb-frontends/Kconfig"
 
 endif # MEDIA_SUPPORT
index 64755c99ded291e526a8dd7fa5a83e73496486e4..620f275a45c9903069a1ebd7bb24370de71f3f4e 100644 (file)
@@ -4,11 +4,30 @@
 
 media-objs     := media-device.o media-devnode.o media-entity.o
 
+#
+# I2C drivers should come before other drivers, otherwise they'll fail
+# when compiled as builtin drivers
+#
+obj-y += i2c/ tuners/
+obj-$(CONFIG_DVB_CORE)  += dvb-frontends/
+
+#
+# Now, let's link-in the media core
+#
 ifeq ($(CONFIG_MEDIA_CONTROLLER),y)
   obj-$(CONFIG_MEDIA_SUPPORT) += media.o
 endif
 
-obj-y += common/ rc/ video/
+obj-$(CONFIG_VIDEO_DEV) += v4l2-core/
+obj-$(CONFIG_DVB_CORE)  += dvb-core/
 
+# There are both core and drivers at RC subtree - merge before drivers
+obj-y += rc/
+
+#
+# Finally, merge the drivers that require the core
+#
+
+obj-y += common/ platform/ pci/ usb/ mmc/ firewire/ parport/
 obj-$(CONFIG_VIDEO_DEV) += radio/
-obj-$(CONFIG_DVB_CORE)  += dvb/
+
index 769c6f8142d2cd750b9e520ecaaed6a24a525bfa..121b0110af3c525055e426bb7e206c02f2389c04 100644 (file)
@@ -1,9 +1,3 @@
-config VIDEO_SAA7146
-       tristate
-       depends on I2C && PCI
-
-config VIDEO_SAA7146_VV
-       tristate
-       depends on VIDEO_V4L2
-       select VIDEOBUF_DMA_SG
-       select VIDEO_SAA7146
+source "drivers/media/common/b2c2/Kconfig"
+source "drivers/media/common/saa7146/Kconfig"
+source "drivers/media/common/siano/Kconfig"
index e3ec9639321b750ab10d953899e843687adc0cc3..b8e2e3a33a319d408efc812d9bb8109d85deffd5 100644 (file)
@@ -1,6 +1 @@
-saa7146-objs    := saa7146_i2c.o saa7146_core.o
-saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
-
-obj-y += tuners/
-obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
-obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
+obj-y += b2c2/ saa7146/ siano/
diff --git a/drivers/media/common/b2c2/Kconfig b/drivers/media/common/b2c2/Kconfig
new file mode 100644 (file)
index 0000000..1df9e57
--- /dev/null
@@ -0,0 +1,28 @@
+config DVB_B2C2_FLEXCOP
+       tristate
+       depends on DVB_CORE && I2C
+       depends on DVB_B2C2_FLEXCOP_PCI || DVB_B2C2_FLEXCOP_USB
+       default y
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_BCM3510 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUNER_ITD1000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUNER_CX24113 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for the digital TV receiver chip made by B2C2 Inc. included in
+         Technisats PCI cards and USB boxes.
+
+         Say Y if you own such a device and want to use it.
+
+# Selected via the PCI or USB flexcop drivers
+config DVB_B2C2_FLEXCOP_DEBUG
+       bool
diff --git a/drivers/media/common/b2c2/Makefile b/drivers/media/common/b2c2/Makefile
new file mode 100644 (file)
index 0000000..24993a5
--- /dev/null
@@ -0,0 +1,8 @@
+b2c2-flexcop-objs += flexcop.o flexcop-fe-tuner.o flexcop-i2c.o
+b2c2-flexcop-objs += flexcop-sram.o flexcop-eeprom.o flexcop-misc.o
+b2c2-flexcop-objs += flexcop-hw-filter.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
similarity index 99%
rename from drivers/media/dvb/b2c2/flexcop.c
rename to drivers/media/common/b2c2/flexcop.c
index b1e8c99f469b403005cdb9ff7680050c1ea6278b..412c5daf2b48c4208f2fb0bd60ed50fb2f4acbef 100644 (file)
@@ -43,6 +43,7 @@
 #endif
 
 int b2c2_flexcop_debug;
+EXPORT_SYMBOL_GPL(b2c2_flexcop_debug);
 module_param_named(debug, b2c2_flexcop_debug,  int, 0644);
 MODULE_PARM_DESC(debug,
                "set debug level (1=info,2=tuner,4=i2c,8=ts,"
diff --git a/drivers/media/common/saa7146/Kconfig b/drivers/media/common/saa7146/Kconfig
new file mode 100644 (file)
index 0000000..769c6f8
--- /dev/null
@@ -0,0 +1,9 @@
+config VIDEO_SAA7146
+       tristate
+       depends on I2C && PCI
+
+config VIDEO_SAA7146_VV
+       tristate
+       depends on VIDEO_V4L2
+       select VIDEOBUF_DMA_SG
+       select VIDEO_SAA7146
diff --git a/drivers/media/common/saa7146/Makefile b/drivers/media/common/saa7146/Makefile
new file mode 100644 (file)
index 0000000..3219b00
--- /dev/null
@@ -0,0 +1,5 @@
+saa7146-objs    := saa7146_i2c.o saa7146_core.o
+saa7146_vv-objs := saa7146_fops.o saa7146_video.o saa7146_hlp.o saa7146_vbi.o
+
+obj-$(CONFIG_VIDEO_SAA7146) += saa7146.o
+obj-$(CONFIG_VIDEO_SAA7146_VV) += saa7146_vv.o
similarity index 98%
rename from drivers/media/common/saa7146_core.c
rename to drivers/media/common/saa7146/saa7146_core.c
index d6b1cf66042d196b40a7b99c18241fe186840d1d..bb6ee5191eb183a415c6de0350a3ae02877a3fd2 100644 (file)
@@ -23,9 +23,6 @@
 #include <media/saa7146.h>
 #include <linux/module.h>
 
-LIST_HEAD(saa7146_devices);
-DEFINE_MUTEX(saa7146_devices_lock);
-
 static int saa7146_num;
 
 unsigned int saa7146_debug;
@@ -482,8 +479,6 @@ static int saa7146_init_one(struct pci_dev *pci, const struct pci_device_id *ent
           set it explicitly. */
        pci_set_drvdata(pci, &dev->v4l2_dev);
 
-       INIT_LIST_HEAD(&dev->item);
-       list_add_tail(&dev->item,&saa7146_devices);
        saa7146_num++;
 
        err = 0;
@@ -545,7 +540,6 @@ static void saa7146_remove_one(struct pci_dev *pdev)
 
        iounmap(dev->mem);
        pci_release_region(pdev, 0);
-       list_del(&dev->item);
        pci_disable_device(pdev);
        kfree(dev);
 
@@ -592,8 +586,6 @@ EXPORT_SYMBOL_GPL(saa7146_setgpio);
 EXPORT_SYMBOL_GPL(saa7146_i2c_adapter_prepare);
 
 EXPORT_SYMBOL_GPL(saa7146_debug);
-EXPORT_SYMBOL_GPL(saa7146_devices);
-EXPORT_SYMBOL_GPL(saa7146_devices_lock);
 
 MODULE_AUTHOR("Michael Hunold <michael@mihu.de>");
 MODULE_DESCRIPTION("driver for generic saa7146-based hardware");
similarity index 94%
rename from drivers/media/common/saa7146_fops.c
rename to drivers/media/common/saa7146/saa7146_fops.c
index 0cdbd742974ae0404ccf724d734ea5da08a6f821..b3890bd49df6089fa0871f70d7b09abc47375b4c 100644 (file)
@@ -201,7 +201,7 @@ static int fops_open(struct file *file)
 
        DEB_EE("file:%p, dev:%s\n", file, video_device_node_name(vdev));
 
-       if (mutex_lock_interruptible(&saa7146_devices_lock))
+       if (mutex_lock_interruptible(vdev->lock))
                return -ERESTARTSYS;
 
        DEB_D("using: %p\n", dev);
@@ -253,7 +253,7 @@ out:
                kfree(fh);
                file->private_data = NULL;
        }
-       mutex_unlock(&saa7146_devices_lock);
+       mutex_unlock(vdev->lock);
        return result;
 }
 
@@ -265,7 +265,7 @@ static int fops_release(struct file *file)
 
        DEB_EE("file:%p\n", file);
 
-       if (mutex_lock_interruptible(&saa7146_devices_lock))
+       if (mutex_lock_interruptible(vdev->lock))
                return -ERESTARTSYS;
 
        if (vdev->vfl_type == VFL_TYPE_VBI) {
@@ -283,7 +283,7 @@ static int fops_release(struct file *file)
        file->private_data = NULL;
        kfree(fh);
 
-       mutex_unlock(&saa7146_devices_lock);
+       mutex_unlock(vdev->lock);
 
        return 0;
 }
@@ -293,6 +293,7 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
        struct video_device *vdev = video_devdata(file);
        struct saa7146_fh *fh = file->private_data;
        struct videobuf_queue *q;
+       int res;
 
        switch (vdev->vfl_type) {
        case VFL_TYPE_GRABBER: {
@@ -314,10 +315,14 @@ static int fops_mmap(struct file *file, struct vm_area_struct * vma)
                return 0;
        }
 
-       return videobuf_mmap_mapper(q,vma);
+       if (mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
+       res = videobuf_mmap_mapper(q, vma);
+       mutex_unlock(vdev->lock);
+       return res;
 }
 
-static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
+static unsigned int __fops_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7146_fh *fh = file->private_data;
@@ -356,10 +361,22 @@ static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
        return res;
 }
 
+static unsigned int fops_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct video_device *vdev = video_devdata(file);
+       unsigned int res;
+
+       mutex_lock(vdev->lock);
+       res = __fops_poll(file, wait);
+       mutex_unlock(vdev->lock);
+       return res;
+}
+
 static ssize_t fops_read(struct file *file, char __user *data, size_t count, loff_t *ppos)
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7146_fh *fh = file->private_data;
+       int ret;
 
        switch (vdev->vfl_type) {
        case VFL_TYPE_GRABBER:
@@ -373,8 +390,13 @@ static ssize_t fops_read(struct file *file, char __user *data, size_t count, lof
                DEB_EE("V4L2_BUF_TYPE_VBI_CAPTURE: file:%p, data:%p, count:%lu\n",
                       file, data, (unsigned long)count);
 */
-               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE)
-                       return saa7146_vbi_uops.read(file,data,count,ppos);
+               if (fh->dev->ext_vv_data->capabilities & V4L2_CAP_VBI_CAPTURE) {
+                       if (mutex_lock_interruptible(vdev->lock))
+                               return -ERESTARTSYS;
+                       ret = saa7146_vbi_uops.read(file, data, count, ppos);
+                       mutex_unlock(vdev->lock);
+                       return ret;
+               }
                return -EINVAL;
        default:
                BUG();
@@ -386,15 +408,20 @@ static ssize_t fops_write(struct file *file, const char __user *data, size_t cou
 {
        struct video_device *vdev = video_devdata(file);
        struct saa7146_fh *fh = file->private_data;
+       int ret;
 
        switch (vdev->vfl_type) {
        case VFL_TYPE_GRABBER:
                return -EINVAL;
        case VFL_TYPE_VBI:
-               if (fh->dev->ext_vv_data->vbi_fops.write)
-                       return fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
-               else
-                       return -EINVAL;
+               if (fh->dev->ext_vv_data->vbi_fops.write) {
+                       if (mutex_lock_interruptible(vdev->lock))
+                               return -ERESTARTSYS;
+                       ret = fh->dev->ext_vv_data->vbi_fops.write(file, data, count, ppos);
+                       mutex_unlock(vdev->lock);
+                       return ret;
+               }
+               return -EINVAL;
        default:
                BUG();
                return -EINVAL;
@@ -584,10 +611,6 @@ int saa7146_register_device(struct video_device **vid, struct saa7146_dev* dev,
        else
                vfd->ioctl_ops = &dev->ext_vv_data->vbi_ops;
        vfd->release = video_device_release;
-       /* Locking in file operations other than ioctl should be done by
-          the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->lock = &dev->v4l2_lock;
        vfd->v4l2_dev = &dev->v4l2_dev;
        vfd->tvnorms = 0;
similarity index 99%
rename from drivers/media/common/saa7146_video.c
rename to drivers/media/common/saa7146/saa7146_video.c
index 6d14785d47471fd1c290c5ee43cf792ac30245f7..4143d61f79b1013b54156e7ee88a4d82234dc9ed 100644 (file)
@@ -479,7 +479,7 @@ static int vidioc_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *f
        return 0;
 }
 
-static int vidioc_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+static int vidioc_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
 {
        struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
        struct saa7146_vv *vv = dev->vv_data;
diff --git a/drivers/media/common/siano/Kconfig b/drivers/media/common/siano/Kconfig
new file mode 100644 (file)
index 0000000..425aead
--- /dev/null
@@ -0,0 +1,17 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config SMS_SIANO_MDTV
+       tristate
+       depends on DVB_CORE && RC_CORE && HAS_DMA
+       depends on SMS_USB_DRV || SMS_SDIO_DRV
+       default y
+       ---help---
+         Choose Y or M here if you have MDTV receiver with a Siano chipset.
+
+         To compile this driver as a module, choose M here
+         (The module will be called smsmdtv).
+
+         Further documentation on this driver can be found on the WWW
+         at http://www.siano-ms.com/
similarity index 57%
rename from drivers/media/dvb/siano/Makefile
rename to drivers/media/common/siano/Makefile
index f233b57c86fb61144a6a32c11ed82e10c823d1c0..2a09279e0648edd912897140084e001820cbbbb0 100644 (file)
@@ -1,11 +1,7 @@
-
 smsmdtv-objs := smscoreapi.o sms-cards.o smsendian.o smsir.o
 
 obj-$(CONFIG_SMS_SIANO_MDTV) += smsmdtv.o smsdvb.o
-obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
-obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core
 
+ccflags-y += -Idrivers/media/dvb-core
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
 
diff --git a/drivers/media/dvb-core/Kconfig b/drivers/media/dvb-core/Kconfig
new file mode 100644 (file)
index 0000000..fa7a249
--- /dev/null
@@ -0,0 +1,29 @@
+#
+# DVB device configuration
+#
+
+config DVB_MAX_ADAPTERS
+       int "maximum number of DVB/ATSC adapters"
+       depends on DVB_CORE
+       default 8
+       range 1 255
+       help
+         Maximum number of DVB/ATSC adapters. Increasing this number
+         increases the memory consumption of the DVB subsystem even
+         if a much lower number of DVB/ATSC adapters is present.
+         Only values in the range 4-32 are tested.
+
+         If you are unsure about this, use the default value 8
+
+config DVB_DYNAMIC_MINORS
+       bool "Dynamic DVB minor allocation"
+       depends on DVB_CORE
+       default n
+       help
+         If you say Y here, the DVB subsystem will use dynamic minor
+         allocation for any device that uses the DVB major number.
+         This means that you can have more than 4 of a single type
+         of device (like demuxes and frontends) per adapter, but udev
+         will be required to manage the device nodes.
+
+         If you are unsure about this, say N here.
similarity index 99%
rename from drivers/media/dvb/dvb-core/dmxdev.c
rename to drivers/media/dvb-core/dmxdev.c
index 73970cd97af1356e1fdeaea9dd733aab94a5f5c7..889c9c16c6df81ec7e2175a3d4c1f858ef4f61c2 100644 (file)
@@ -370,9 +370,7 @@ static int dvb_dmxdev_section_callback(const u8 *buffer1, size_t buffer1_len,
                return 0;
        }
        del_timer(&dmxdevfilter->timer);
-       dprintk("dmxdev: section callback %02x %02x %02x %02x %02x %02x\n",
-               buffer1[0], buffer1[1],
-               buffer1[2], buffer1[3], buffer1[4], buffer1[5]);
+       dprintk("dmxdev: section callback %*ph\n", 6, buffer1);
        ret = dvb_dmxdev_buffer_write(&dmxdevfilter->buffer, buffer1,
                                      buffer1_len);
        if (ret == buffer1_len) {
similarity index 99%
rename from drivers/media/dvb/dvb-usb/dvb-usb-ids.h
rename to drivers/media/dvb-core/dvb-usb-ids.h
index 26c44818a5abf23d96f344fd0e83de75b20a47b4..58e0220447c012a5b9fc7bee807bda26468fb087 100644 (file)
@@ -24,6 +24,7 @@
 #define USB_VID_COMPRO_UNK                     0x145f
 #define USB_VID_CONEXANT                       0x0572
 #define USB_VID_CYPRESS                                0x04b4
+#define USB_VID_DEXATEK                                0x1d19
 #define USB_VID_DIBCOM                         0x10b8
 #define USB_VID_DPOSH                          0x1498
 #define USB_VID_DVICO                          0x0fe9
@@ -82,6 +83,7 @@
 #define USB_PID_AFATECH_AF9035_1003                    0x1003
 #define USB_PID_AFATECH_AF9035_9035                    0x9035
 #define USB_PID_TREKSTOR_DVBT                          0x901b
+#define USB_PID_TREKSTOR_TERRES_2_0                    0xC803
 #define USB_VID_ALINK_DTU                              0xf170
 #define USB_PID_ANSONIC_DVBT_USB                       0x6000
 #define USB_PID_ANYSEE                                 0x861f
 #define USB_PID_ASUS_U3000                             0x171f
 #define USB_PID_ASUS_U3000H                            0x1736
 #define USB_PID_ASUS_U3100                             0x173f
+#define USB_PID_ASUS_U3100MINI_PLUS                    0x1779
 #define USB_PID_YUAN_EC372S                            0x1edc
 #define USB_PID_YUAN_STK7700PH                         0x1f08
 #define USB_PID_YUAN_PD378S                            0x2edc
similarity index 98%
rename from drivers/media/dvb/dvb-core/dvb_demux.c
rename to drivers/media/dvb-core/dvb_demux.c
index d82469f842e2e023a85c88f8917081b5bce2c776..d319717eb535fcefcdd983b18fd39f3d6d1c9c24 100644 (file)
@@ -50,6 +50,11 @@ module_param(dvb_demux_speedcheck, int, 0644);
 MODULE_PARM_DESC(dvb_demux_speedcheck,
                "enable transport stream speed check");
 
+static int dvb_demux_feed_err_pkts = 1;
+module_param(dvb_demux_feed_err_pkts, int, 0644);
+MODULE_PARM_DESC(dvb_demux_feed_err_pkts,
+                "when set to 0, drop packets with the TEI bit set (1 by default)");
+
 #define dprintk_tscheck(x...) do {                              \
                if (dvb_demux_tscheck && printk_ratelimit())    \
                        printk(x);                              \
@@ -419,21 +424,25 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                                printk(KERN_INFO "TS speed %llu Kbits/sec \n",
                                                div64_u64(speed_bytes,
                                                        speed_timedelta));
-                       };
+                       }
 
                        demux->speed_last_time = cur_time;
                        demux->speed_pkts_cnt = 0;
-               };
-       };
+               }
+       }
 
+       if (buf[1] & 0x80) {
+               dprintk_tscheck("TEI detected. "
+                               "PID=0x%x data1=0x%x\n",
+                               pid, buf[1]);
+               /* data in this packet cant be trusted - drop it unless
+                * module option dvb_demux_feed_err_pkts is set */
+               if (!dvb_demux_feed_err_pkts)
+                       return;
+       } else /* if TEI bit is set, pid may be wrong- skip pkt counter */
        if (demux->cnt_storage && dvb_demux_tscheck) {
                /* check pkt counter */
                if (pid < MAX_PID) {
-                       if (buf[1] & 0x80)
-                               dprintk_tscheck("TEI detected. "
-                                               "PID=0x%x data1=0x%x\n",
-                                               pid, buf[1]);
-
                        if ((buf[3] & 0xf) != demux->cnt_storage[pid])
                                dprintk_tscheck("TS packet counter mismatch. "
                                                "PID=0x%x expected 0x%x "
@@ -442,9 +451,9 @@ static void dvb_dmx_swfilter_packet(struct dvb_demux *demux, const u8 *buf)
                                                buf[3] & 0xf);
 
                        demux->cnt_storage[pid] = ((buf[3] & 0xf) + 1)&0xf;
-               };
+               }
                /* end check */
-       };
+       }
 
        list_for_each_entry(feed, &demux->feed_list, list_head) {
                if ((feed->pid != pid) && (feed->pid != 0x2000))
similarity index 89%
rename from drivers/media/dvb/dvb-core/dvb_frontend.c
rename to drivers/media/dvb-core/dvb_frontend.c
index aebcdf221ddacece9fd1413aa2c9906c836c88ba..8f58f241c10dfa7047f92423cb917c67d908f4b1 100644 (file)
@@ -66,8 +66,6 @@ MODULE_PARM_DESC(dvb_powerdown_on_sleep, "0: do not power down, 1: turn LNB volt
 module_param(dvb_mfe_wait_time, int, 0644);
 MODULE_PARM_DESC(dvb_mfe_wait_time, "Wait up to <mfe_wait_time> seconds on open() for multi-frontend to become available (default:5 seconds)");
 
-#define dprintk if (dvb_frontend_debug) printk
-
 #define FESTATE_IDLE 1
 #define FESTATE_RETUNE 2
 #define FESTATE_TUNING_FAST 4
@@ -179,7 +177,7 @@ static enum dvbv3_emulation_type dvbv3_type(u32 delivery_system)
        case SYS_DVBT:
        case SYS_DVBT2:
        case SYS_ISDBT:
-       case SYS_DMBTH:
+       case SYS_DTMB:
                return DVBV3_OFDM;
        case SYS_ATSC:
        case SYS_ATSCMH:
@@ -207,7 +205,7 @@ static void dvb_frontend_add_event(struct dvb_frontend *fe, fe_status_t status)
        struct dvb_frontend_event *e;
        int wp;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if ((status & FE_HAS_LOCK) && has_get_frontend(fe))
                dtv_get_frontend(fe, &fepriv->parameters_out);
@@ -237,7 +235,7 @@ static int dvb_frontend_get_event(struct dvb_frontend *fe,
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dvb_fe_events *events = &fepriv->events;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if (events->overflow) {
                events->overflow = 0;
@@ -282,10 +280,9 @@ static void dvb_frontend_clear_events(struct dvb_frontend *fe)
 
 static void dvb_frontend_init(struct dvb_frontend *fe)
 {
-       dprintk ("DVB: initialising adapter %i frontend %i (%s)...\n",
-                fe->dvb->num,
-                fe->id,
-                fe->ops.info.name);
+       dev_dbg(fe->dvb->device,
+                       "%s: initialising adapter %i frontend %i (%s)...\n",
+                       __func__, fe->dvb->num, fe->id, fe->ops.info.name);
 
        if (fe->ops.init)
                fe->ops.init(fe);
@@ -310,8 +307,9 @@ EXPORT_SYMBOL(dvb_frontend_reinitialise);
 static void dvb_frontend_swzigzag_update_delay(struct dvb_frontend_private *fepriv, int locked)
 {
        int q2;
+       struct dvb_frontend *fe = fepriv->dvbdev->priv;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if (locked)
                (fepriv->quality) = (fepriv->quality * 220 + 36*256) / 256;
@@ -403,10 +401,11 @@ static int dvb_frontend_swzigzag_autotune(struct dvb_frontend *fe, int check_wra
                return 1;
        }
 
-       dprintk("%s: drift:%i inversion:%i auto_step:%i "
-               "auto_sub_step:%i started_auto_step:%i\n",
-               __func__, fepriv->lnb_drift, fepriv->inversion,
-               fepriv->auto_step, fepriv->auto_sub_step, fepriv->started_auto_step);
+       dev_dbg(fe->dvb->device, "%s: drift:%i inversion:%i auto_step:%i " \
+                       "auto_sub_step:%i started_auto_step:%i\n",
+                       __func__, fepriv->lnb_drift, fepriv->inversion,
+                       fepriv->auto_step, fepriv->auto_sub_step,
+                       fepriv->started_auto_step);
 
        /* set the frontend itself */
        c->frequency += fepriv->lnb_drift;
@@ -605,7 +604,7 @@ static int dvb_frontend_thread(void *data)
 
        bool re_tune = false;
 
-       dprintk("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        fepriv->check_wrapped = 0;
        fepriv->quality = 0;
@@ -651,10 +650,10 @@ restart:
                        algo = fe->ops.get_frontend_algo(fe);
                        switch (algo) {
                        case DVBFE_ALGO_HW:
-                               dprintk("%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
+                               dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_HW\n", __func__);
 
                                if (fepriv->state & FESTATE_RETUNE) {
-                                       dprintk("%s: Retune requested, FESTATE_RETUNE\n", __func__);
+                                       dev_dbg(fe->dvb->device, "%s: Retune requested, FESTATE_RETUNE\n", __func__);
                                        re_tune = true;
                                        fepriv->state = FESTATE_TUNED;
                                } else {
@@ -665,19 +664,19 @@ restart:
                                        fe->ops.tune(fe, re_tune, fepriv->tune_mode_flags, &fepriv->delay, &s);
 
                                if (s != fepriv->status && !(fepriv->tune_mode_flags & FE_TUNE_MODE_ONESHOT)) {
-                                       dprintk("%s: state changed, adding current state\n", __func__);
+                                       dev_dbg(fe->dvb->device, "%s: state changed, adding current state\n", __func__);
                                        dvb_frontend_add_event(fe, s);
                                        fepriv->status = s;
                                }
                                break;
                        case DVBFE_ALGO_SW:
-                               dprintk("%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
+                               dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_SW\n", __func__);
                                dvb_frontend_swzigzag(fe);
                                break;
                        case DVBFE_ALGO_CUSTOM:
-                               dprintk("%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
+                               dev_dbg(fe->dvb->device, "%s: Frontend ALGO = DVBFE_ALGO_CUSTOM, state=%d\n", __func__, fepriv->state);
                                if (fepriv->state & FESTATE_RETUNE) {
-                                       dprintk("%s: Retune requested, FESTAT_RETUNE\n", __func__);
+                                       dev_dbg(fe->dvb->device, "%s: Retune requested, FESTAT_RETUNE\n", __func__);
                                        fepriv->state = FESTATE_TUNED;
                                }
                                /* Case where we are going to search for a carrier
@@ -713,7 +712,7 @@ restart:
                                }
                                break;
                        default:
-                               dprintk("%s: UNDEFINED ALGO !\n", __func__);
+                               dev_dbg(fe->dvb->device, "%s: UNDEFINED ALGO !\n", __func__);
                                break;
                        }
                } else {
@@ -750,7 +749,7 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        fepriv->exit = DVB_FE_NORMAL_EXIT;
        mb();
@@ -765,7 +764,8 @@ static void dvb_frontend_stop(struct dvb_frontend *fe)
 
        /* paranoia check in case a signal arrived */
        if (fepriv->thread)
-               printk("dvb_frontend_stop: warning: thread %p won't exit\n",
+               dev_warn(fe->dvb->device,
+                               "dvb_frontend_stop: warning: thread %p won't exit\n",
                                fepriv->thread);
 }
 
@@ -818,7 +818,7 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct task_struct *fe_thread;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if (fepriv->thread) {
                if (fepriv->exit == DVB_FE_NO_EXIT)
@@ -841,7 +841,9 @@ static int dvb_frontend_start(struct dvb_frontend *fe)
                "kdvb-ad-%i-fe-%i", fe->dvb->num,fe->id);
        if (IS_ERR(fe_thread)) {
                ret = PTR_ERR(fe_thread);
-               printk("dvb_frontend_start: failed to start kthread (%d)\n", ret);
+               dev_warn(fe->dvb->device,
+                               "dvb_frontend_start: failed to start kthread (%d)\n",
+                               ret);
                up(&fepriv->sem);
                return ret;
        }
@@ -862,8 +864,8 @@ static void dvb_frontend_get_frequency_limits(struct dvb_frontend *fe,
                *freq_max = min(fe->ops.info.frequency_max, fe->ops.tuner_ops.info.frequency_max);
 
        if (*freq_min == 0 || *freq_max == 0)
-               printk(KERN_WARNING "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
-                      fe->dvb->num,fe->id);
+               dev_warn(fe->dvb->device, "DVB: adapter %i frontend %u frequency limits undefined - fix the driver\n",
+                               fe->dvb->num, fe->id);
 }
 
 static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
@@ -876,8 +878,9 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
        dvb_frontend_get_frequency_limits(fe, &freq_min, &freq_max);
        if ((freq_min && c->frequency < freq_min) ||
            (freq_max && c->frequency > freq_max)) {
-               printk(KERN_WARNING "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
-                      fe->dvb->num, fe->id, c->frequency, freq_min, freq_max);
+               dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i frequency %u out of range (%u..%u)\n",
+                               fe->dvb->num, fe->id, c->frequency,
+                               freq_min, freq_max);
                return -EINVAL;
        }
 
@@ -892,10 +895,10 @@ static int dvb_frontend_check_parameters(struct dvb_frontend *fe)
                     c->symbol_rate < fe->ops.info.symbol_rate_min) ||
                    (fe->ops.info.symbol_rate_max &&
                     c->symbol_rate > fe->ops.info.symbol_rate_max)) {
-                       printk(KERN_WARNING "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
-                              fe->dvb->num, fe->id, c->symbol_rate,
-                              fe->ops.info.symbol_rate_min,
-                              fe->ops.info.symbol_rate_max);
+                       dev_warn(fe->dvb->device, "DVB: adapter %i frontend %i symbol rate %u out of range (%u..%u)\n",
+                                       fe->dvb->num, fe->id, c->symbol_rate,
+                                       fe->ops.info.symbol_rate_min,
+                                       fe->ops.info.symbol_rate_max);
                        return -EINVAL;
                }
        default:
@@ -917,8 +920,8 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
 
        c->state = DTV_CLEAR;
 
-       dprintk("%s() Clearing cache for delivery system %d\n", __func__,
-               c->delivery_system);
+       dev_dbg(fe->dvb->device, "%s: Clearing cache for delivery system %d\n",
+                       __func__, c->delivery_system);
 
        c->transmission_mode = TRANSMISSION_MODE_AUTO;
        c->bandwidth_hz = 0;    /* AUTO */
@@ -946,8 +949,7 @@ static int dvb_frontend_clear_cache(struct dvb_frontend *fe)
                c->layer[i].segment_count = 0;
        }
 
-       c->isdbs_ts_id = 0;
-       c->dvbt2_plp_id = 0;
+       c->stream_id = NO_STREAM_ID_FILTER;
 
        switch (c->delivery_system) {
        case SYS_DVBS:
@@ -997,6 +999,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_CODE_RATE_LP, 1, 0),
        _DTV_CMD(DTV_GUARD_INTERVAL, 1, 0),
        _DTV_CMD(DTV_TRANSMISSION_MODE, 1, 0),
+       _DTV_CMD(DTV_INTERLEAVING, 1, 0),
 
        _DTV_CMD(DTV_ISDBT_PARTIAL_RECEPTION, 1, 0),
        _DTV_CMD(DTV_ISDBT_SOUND_BROADCASTING, 1, 0),
@@ -1017,8 +1020,9 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ISDBT_LAYERC_SEGMENT_COUNT, 1, 0),
        _DTV_CMD(DTV_ISDBT_LAYERC_TIME_INTERLEAVING, 1, 0),
 
-       _DTV_CMD(DTV_ISDBS_TS_ID, 1, 0),
-       _DTV_CMD(DTV_DVBT2_PLP_ID, 1, 0),
+       _DTV_CMD(DTV_STREAM_ID, 1, 0),
+       _DTV_CMD(DTV_DVBT2_PLP_ID_LEGACY, 1, 0),
+       _DTV_CMD(DTV_LNA, 1, 0),
 
        /* Get */
        _DTV_CMD(DTV_DISEQC_SLAVE_REPLY, 0, 1),
@@ -1028,6 +1032,7 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_GUARD_INTERVAL, 0, 0),
        _DTV_CMD(DTV_TRANSMISSION_MODE, 0, 0),
        _DTV_CMD(DTV_HIERARCHY, 0, 0),
+       _DTV_CMD(DTV_INTERLEAVING, 0, 0),
 
        _DTV_CMD(DTV_ENUM_DELSYS, 0, 0),
 
@@ -1051,35 +1056,31 @@ static struct dtv_cmds_h dtv_cmds[DTV_MAX_COMMAND + 1] = {
        _DTV_CMD(DTV_ATSCMH_SCCC_CODE_MODE_D, 0, 0),
 };
 
-static void dtv_property_dump(struct dtv_property *tvp)
+static void dtv_property_dump(struct dvb_frontend *fe, struct dtv_property *tvp)
 {
        int i;
 
        if (tvp->cmd <= 0 || tvp->cmd > DTV_MAX_COMMAND) {
-               printk(KERN_WARNING "%s: tvp.cmd = 0x%08x undefined\n",
-                       __func__, tvp->cmd);
+               dev_warn(fe->dvb->device, "%s: tvp.cmd = 0x%08x undefined\n",
+                               __func__, tvp->cmd);
                return;
        }
 
-       dprintk("%s() tvp.cmd    = 0x%08x (%s)\n"
-               ,__func__
-               ,tvp->cmd
-               ,dtv_cmds[ tvp->cmd ].name);
-
-       if(dtv_cmds[ tvp->cmd ].buffer) {
+       dev_dbg(fe->dvb->device, "%s: tvp.cmd    = 0x%08x (%s)\n", __func__,
+                       tvp->cmd, dtv_cmds[tvp->cmd].name);
 
-               dprintk("%s() tvp.u.buffer.len = 0x%02x\n"
-                       ,__func__
-                       ,tvp->u.buffer.len);
+       if (dtv_cmds[tvp->cmd].buffer) {
+               dev_dbg(fe->dvb->device, "%s: tvp.u.buffer.len = 0x%02x\n",
+                       __func__, tvp->u.buffer.len);
 
                for(i = 0; i < tvp->u.buffer.len; i++)
-                       dprintk("%s() tvp.u.buffer.data[0x%02x] = 0x%02x\n"
-                               ,__func__
-                               ,i
-                               ,tvp->u.buffer.data[i]);
-
-       } else
-               dprintk("%s() tvp.u.data = 0x%08x\n", __func__, tvp->u.data);
+                       dev_dbg(fe->dvb->device,
+                                       "%s: tvp.u.buffer.data[0x%02x] = 0x%02x\n",
+                                       __func__, i, tvp->u.buffer.data[i]);
+       } else {
+               dev_dbg(fe->dvb->device, "%s: tvp.u.data = 0x%08x\n", __func__,
+                               tvp->u.data);
+       }
 }
 
 /* Synchronise the legacy tuning parameters into the cache, so that demodulator
@@ -1095,18 +1096,19 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
 
        switch (dvbv3_type(c->delivery_system)) {
        case DVBV3_QPSK:
-               dprintk("%s() Preparing QPSK req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
                c->symbol_rate = p->u.qpsk.symbol_rate;
                c->fec_inner = p->u.qpsk.fec_inner;
                break;
        case DVBV3_QAM:
-               dprintk("%s() Preparing QAM req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__);
                c->symbol_rate = p->u.qam.symbol_rate;
                c->fec_inner = p->u.qam.fec_inner;
                c->modulation = p->u.qam.modulation;
                break;
        case DVBV3_OFDM:
-               dprintk("%s() Preparing OFDM req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__);
+
                switch (p->u.ofdm.bandwidth) {
                case BANDWIDTH_10_MHZ:
                        c->bandwidth_hz = 10000000;
@@ -1138,7 +1140,7 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
                c->hierarchy = p->u.ofdm.hierarchy_information;
                break;
        case DVBV3_ATSC:
-               dprintk("%s() Preparing ATSC req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing ATSC req\n", __func__);
                c->modulation = p->u.vsb.modulation;
                if (c->delivery_system == SYS_ATSCMH)
                        break;
@@ -1148,9 +1150,9 @@ static int dtv_property_cache_sync(struct dvb_frontend *fe,
                        c->delivery_system = SYS_DVBC_ANNEX_B;
                break;
        case DVBV3_UNKNOWN:
-               printk(KERN_ERR
-                      "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-                      __func__, c->delivery_system);
+               dev_err(fe->dvb->device,
+                               "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                               __func__, c->delivery_system);
                return -EINVAL;
        }
 
@@ -1170,24 +1172,23 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
 
        switch (dvbv3_type(c->delivery_system)) {
        case DVBV3_UNKNOWN:
-               printk(KERN_ERR
-                      "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-                      __func__, c->delivery_system);
+               dev_err(fe->dvb->device,
+                               "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                               __func__, c->delivery_system);
                return -EINVAL;
        case DVBV3_QPSK:
-               dprintk("%s() Preparing QPSK req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing QPSK req\n", __func__);
                p->u.qpsk.symbol_rate = c->symbol_rate;
                p->u.qpsk.fec_inner = c->fec_inner;
                break;
        case DVBV3_QAM:
-               dprintk("%s() Preparing QAM req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing QAM req\n", __func__);
                p->u.qam.symbol_rate = c->symbol_rate;
                p->u.qam.fec_inner = c->fec_inner;
                p->u.qam.modulation = c->modulation;
                break;
        case DVBV3_OFDM:
-               dprintk("%s() Preparing OFDM req\n", __func__);
-
+               dev_dbg(fe->dvb->device, "%s: Preparing OFDM req\n", __func__);
                switch (c->bandwidth_hz) {
                case 10000000:
                        p->u.ofdm.bandwidth = BANDWIDTH_10_MHZ;
@@ -1219,7 +1220,7 @@ static int dtv_property_legacy_params_sync(struct dvb_frontend *fe,
                p->u.ofdm.hierarchy_information = c->hierarchy;
                break;
        case DVBV3_ATSC:
-               dprintk("%s() Preparing VSB req\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Preparing VSB req\n", __func__);
                p->u.vsb.modulation = c->modulation;
                break;
        }
@@ -1326,6 +1327,9 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
        case DTV_HIERARCHY:
                tvp->u.data = c->hierarchy;
                break;
+       case DTV_INTERLEAVING:
+               tvp->u.data = c->interleaving;
+               break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
@@ -1382,11 +1386,11 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
        case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
                tvp->u.data = c->layer[2].interleaving;
                break;
-       case DTV_ISDBS_TS_ID:
-               tvp->u.data = c->isdbs_ts_id;
-               break;
-       case DTV_DVBT2_PLP_ID:
-               tvp->u.data = c->dvbt2_plp_id;
+
+       /* Multistream support */
+       case DTV_STREAM_ID:
+       case DTV_DVBT2_PLP_ID_LEGACY:
+               tvp->u.data = c->stream_id;
                break;
 
        /* ATSC-MH */
@@ -1447,7 +1451,7 @@ static int dtv_property_process_get(struct dvb_frontend *fe,
                        return r;
        }
 
-       dtv_property_dump(tvp);
+       dtv_property_dump(fe, tvp);
 
        return 0;
 }
@@ -1492,8 +1496,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                 * DVBv3 system that matches the delivery system.
                 */
                if (is_dvbv3_delsys(c->delivery_system)) {
-                       dprintk("%s() Using delivery system to %d\n",
-                               __func__, c->delivery_system);
+                       dev_dbg(fe->dvb->device,
+                                       "%s: Using delivery system to %d\n",
+                                       __func__, c->delivery_system);
                        return 0;
                }
                type = dvbv3_type(c->delivery_system);
@@ -1511,8 +1516,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                        desired_system = SYS_DVBT;
                        break;
                default:
-                       dprintk("%s(): This frontend doesn't support DVBv3 calls\n",
-                               __func__);
+                       dev_dbg(fe->dvb->device, "%s: This frontend doesn't support DVBv3 calls\n",
+                                       __func__);
                        return -EINVAL;
                }
                /*
@@ -1534,8 +1539,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                        ncaps++;
                }
                if (delsys == SYS_UNDEFINED) {
-                       dprintk("%s() Couldn't find a delivery system that matches %d\n",
-                               __func__, desired_system);
+                       dev_dbg(fe->dvb->device, "%s: Couldn't find a delivery system that matches %d\n",
+                                       __func__, desired_system);
                }
        } else {
                /*
@@ -1548,8 +1553,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                while (fe->ops.delsys[ncaps] && ncaps < MAX_DELSYS) {
                        if (fe->ops.delsys[ncaps] == desired_system) {
                                c->delivery_system = desired_system;
-                               dprintk("%s() Changing delivery system to %d\n",
-                                       __func__, desired_system);
+                               dev_dbg(fe->dvb->device,
+                                               "%s: Changing delivery system to %d\n",
+                                               __func__, desired_system);
                                return 0;
                        }
                        ncaps++;
@@ -1563,8 +1569,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                 * DVBv3 delivery systems
                 */
                if (!is_dvbv3_delsys(desired_system)) {
-                       dprintk("%s() can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
-                               __func__);
+                       dev_dbg(fe->dvb->device,
+                                       "%s: can't use a DVBv3 FE_SET_FRONTEND call on this frontend\n",
+                                       __func__);
                        return -EINVAL;
                }
 
@@ -1581,8 +1588,9 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                }
                /* There's nothing compatible with the desired delivery system */
                if (delsys == SYS_UNDEFINED) {
-                       dprintk("%s() Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
-                               __func__);
+                       dev_dbg(fe->dvb->device,
+                                       "%s: Incompatible DVBv3 FE_SET_FRONTEND call for this frontend\n",
+                                       __func__);
                        return -EINVAL;
                }
        }
@@ -1593,13 +1601,14 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
         * The DVBv3 or DVBv5 call is requesting a different system. So,
         * emulation is needed.
         *
-        * Emulate newer delivery systems like ISDBT, DVBT and DMBTH
+        * Emulate newer delivery systems like ISDBT, DVBT and DTMB
         * for older DVBv5 applications. The emulation will try to use
         * the auto mode for most things, and will assume that the desired
         * delivery system is the last one at the ops.delsys[] array
         */
-       dprintk("%s() Using delivery system %d emulated as if it were a %d\n",
-               __func__, delsys, desired_system);
+       dev_dbg(fe->dvb->device,
+                       "%s: Using delivery system %d emulated as if it were a %d\n",
+                       __func__, delsys, desired_system);
 
        /*
         * For now, handles ISDB-T calls. More code may be needed here for the
@@ -1607,8 +1616,10 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
         */
        if (type == DVBV3_OFDM) {
                if (c->delivery_system == SYS_ISDBT) {
-                       dprintk("%s() Using defaults for SYS_ISDBT\n",
-                               __func__);
+                       dev_dbg(fe->dvb->device,
+                                       "%s: Using defaults for SYS_ISDBT\n",
+                                       __func__);
+
                        if (!c->bandwidth_hz)
                                c->bandwidth_hz = 6000000;
 
@@ -1626,7 +1637,8 @@ static int set_delivery_system(struct dvb_frontend *fe, u32 desired_system)
                        }
                }
        }
-       dprintk("change delivery system on cache to %d\n", c->delivery_system);
+       dev_dbg(fe->dvb->device, "%s: change delivery system on cache to %d\n",
+                       __func__, c->delivery_system);
 
        return 0;
 }
@@ -1659,7 +1671,8 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
                 * ioctl.
                 */
                c->state = tvp->cmd;
-               dprintk("%s() Finalised property cache\n", __func__);
+               dev_dbg(fe->dvb->device, "%s: Finalised property cache\n",
+                               __func__);
 
                r = dtv_set_frontend(fe);
                break;
@@ -1715,6 +1728,13 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
        case DTV_HIERARCHY:
                c->hierarchy = tvp->u.data;
                break;
+       case DTV_INTERLEAVING:
+               c->interleaving = tvp->u.data;
+               break;
+       case DTV_LNA:
+               if (fe->ops.set_lna)
+                       r = fe->ops.set_lna(fe, tvp->u.data);
+               break;
 
        /* ISDB-T Support here */
        case DTV_ISDBT_PARTIAL_RECEPTION:
@@ -1771,11 +1791,11 @@ static int dtv_property_process_set(struct dvb_frontend *fe,
        case DTV_ISDBT_LAYERC_TIME_INTERLEAVING:
                c->layer[2].interleaving = tvp->u.data;
                break;
-       case DTV_ISDBS_TS_ID:
-               c->isdbs_ts_id = tvp->u.data;
-               break;
-       case DTV_DVBT2_PLP_ID:
-               c->dvbt2_plp_id = tvp->u.data;
+
+       /* Multistream support */
+       case DTV_STREAM_ID:
+       case DTV_DVBT2_PLP_ID_LEGACY:
+               c->stream_id = tvp->u.data;
                break;
 
        /* ATSC-MH */
@@ -1800,10 +1820,9 @@ static int dvb_frontend_ioctl(struct file *file,
        struct dvb_frontend *fe = dvbdev->priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       int err = -EOPNOTSUPP;
-
-       dprintk("%s (%d)\n", __func__, _IOC_NR(cmd));
+       int err = -ENOTTY;
 
+       dev_dbg(fe->dvb->device, "%s: (%d)\n", __func__, _IOC_NR(cmd));
        if (fepriv->exit != DVB_FE_NO_EXIT)
                return -ENODEV;
 
@@ -1839,13 +1858,13 @@ static int dvb_frontend_ioctl_properties(struct file *file,
        struct dtv_property *tvp = NULL;
        int i;
 
-       dprintk("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if(cmd == FE_SET_PROPERTY) {
                tvps = (struct dtv_properties __user *)parg;
 
-               dprintk("%s() properties.num = %d\n", __func__, tvps->num);
-               dprintk("%s() properties.props = %p\n", __func__, tvps->props);
+               dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
+               dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
 
                /* Put an arbitrary limit on the number of messages that can
                 * be sent at once */
@@ -1871,14 +1890,14 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                }
 
                if (c->state == DTV_TUNE)
-                       dprintk("%s() Property cache is full, tuning\n", __func__);
+                       dev_dbg(fe->dvb->device, "%s: Property cache is full, tuning\n", __func__);
 
        } else
        if(cmd == FE_GET_PROPERTY) {
                tvps = (struct dtv_properties __user *)parg;
 
-               dprintk("%s() properties.num = %d\n", __func__, tvps->num);
-               dprintk("%s() properties.props = %p\n", __func__, tvps->props);
+               dev_dbg(fe->dvb->device, "%s: properties.num = %d\n", __func__, tvps->num);
+               dev_dbg(fe->dvb->device, "%s: properties.props = %p\n", __func__, tvps->props);
 
                /* Put an arbitrary limit on the number of messages that can
                 * be sent at once */
@@ -1919,7 +1938,7 @@ static int dvb_frontend_ioctl_properties(struct file *file,
                }
 
        } else
-               err = -EOPNOTSUPP;
+               err = -ENOTTY;
 
 out:
        kfree(tvp);
@@ -2012,7 +2031,7 @@ static int dtv_set_frontend(struct dvb_frontend *fe)
                case SYS_DVBT:
                case SYS_DVBT2:
                case SYS_ISDBT:
-               case SYS_DMBTH:
+               case SYS_DTMB:
                        fepriv->min_delay = HZ / 20;
                        fepriv->step_size = fe->ops.info.frequency_stepsize * 2;
                        fepriv->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
@@ -2052,18 +2071,7 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int cb_err, err = -EOPNOTSUPP;
-
-       if (fe->dvb->fe_ioctl_override) {
-               cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
-                                                   DVB_FE_IOCTL_PRE);
-               if (cb_err < 0)
-                       return cb_err;
-               if (cb_err > 0)
-                       return 0;
-               /* fe_ioctl_override returning 0 allows
-                * dvb-core to continue handling the ioctl */
-       }
+       int err = -ENOTTY;
 
        switch (cmd) {
        case FE_GET_INFO: {
@@ -2097,13 +2105,13 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                        info->type = FE_OFDM;
                        break;
                default:
-                       printk(KERN_ERR
-                              "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
-                              __func__, c->delivery_system);
+                       dev_err(fe->dvb->device,
+                                       "%s: doesn't know how to handle a DVBv3 call to delivery system %i\n",
+                                       __func__, c->delivery_system);
                        fe->ops.info.type = FE_OFDM;
                }
-               dprintk("current delivery system on cache: %d, V3 type: %d\n",
-                       c->delivery_system, fe->ops.info.type);
+               dev_dbg(fe->dvb->device, "%s: current delivery system on cache: %d, V3 type: %d\n",
+                                __func__, c->delivery_system, fe->ops.info.type);
 
                /* Force the CAN_INVERSION_AUTO bit on. If the frontend doesn't
                 * do it, it is done for it. */
@@ -2128,27 +2136,43 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                        err = fe->ops.read_status(fe, status);
                break;
        }
+
        case FE_READ_BER:
-               if (fe->ops.read_ber)
-                       err = fe->ops.read_ber(fe, (__u32*) parg);
+               if (fe->ops.read_ber) {
+                       if (fepriv->thread)
+                               err = fe->ops.read_ber(fe, (__u32 *) parg);
+                       else
+                               err = -EAGAIN;
+               }
                break;
 
        case FE_READ_SIGNAL_STRENGTH:
-               if (fe->ops.read_signal_strength)
-                       err = fe->ops.read_signal_strength(fe, (__u16*) parg);
+               if (fe->ops.read_signal_strength) {
+                       if (fepriv->thread)
+                               err = fe->ops.read_signal_strength(fe, (__u16 *) parg);
+                       else
+                               err = -EAGAIN;
+               }
                break;
 
        case FE_READ_SNR:
-               if (fe->ops.read_snr)
-                       err = fe->ops.read_snr(fe, (__u16*) parg);
+               if (fe->ops.read_snr) {
+                       if (fepriv->thread)
+                               err = fe->ops.read_snr(fe, (__u16 *) parg);
+                       else
+                               err = -EAGAIN;
+               }
                break;
 
        case FE_READ_UNCORRECTED_BLOCKS:
-               if (fe->ops.read_ucblocks)
-                       err = fe->ops.read_ucblocks(fe, (__u32*) parg);
+               if (fe->ops.read_ucblocks) {
+                       if (fepriv->thread)
+                               err = fe->ops.read_ucblocks(fe, (__u32 *) parg);
+                       else
+                               err = -EAGAIN;
+               }
                break;
 
-
        case FE_DISEQC_RESET_OVERLOAD:
                if (fe->ops.diseqc_reset_overload) {
                        err = fe->ops.diseqc_reset_overload(fe);
@@ -2287,13 +2311,6 @@ static int dvb_frontend_ioctl_legacy(struct file *file,
                break;
        };
 
-       if (fe->dvb->fe_ioctl_override) {
-               cb_err = fe->dvb->fe_ioctl_override(fe, cmd, parg,
-                                                   DVB_FE_IOCTL_POST);
-               if (cb_err < 0)
-                       return cb_err;
-       }
-
        return err;
 }
 
@@ -2304,7 +2321,7 @@ static unsigned int dvb_frontend_poll(struct file *file, struct poll_table_struc
        struct dvb_frontend *fe = dvbdev->priv;
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg_ratelimited(fe->dvb->device, "%s:\n", __func__);
 
        poll_wait (file, &fepriv->events.wait_queue, wait);
 
@@ -2322,7 +2339,7 @@ static int dvb_frontend_open(struct inode *inode, struct file *file)
        struct dvb_adapter *adapter = fe->dvb;
        int ret;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
        if (fepriv->exit == DVB_FE_DEVICE_REMOVED)
                return -ENODEV;
 
@@ -2417,7 +2434,7 @@ static int dvb_frontend_release(struct inode *inode, struct file *file)
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
        int ret;
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        if ((file->f_flags & O_ACCMODE) != O_RDONLY) {
                fepriv->release_jiffies = jiffies;
@@ -2449,6 +2466,44 @@ static const struct file_operations dvb_frontend_fops = {
        .llseek         = noop_llseek,
 };
 
+int dvb_frontend_suspend(struct dvb_frontend *fe)
+{
+       int ret = 0;
+
+       dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
+                       fe->id);
+
+       if (fe->ops.tuner_ops.sleep)
+               ret = fe->ops.tuner_ops.sleep(fe);
+
+       if (fe->ops.sleep)
+               ret = fe->ops.sleep(fe);
+
+       return ret;
+}
+EXPORT_SYMBOL(dvb_frontend_suspend);
+
+int dvb_frontend_resume(struct dvb_frontend *fe)
+{
+       struct dvb_frontend_private *fepriv = fe->frontend_priv;
+       int ret = 0;
+
+       dev_dbg(fe->dvb->device, "%s: adap=%d fe=%d\n", __func__, fe->dvb->num,
+                       fe->id);
+
+       if (fe->ops.init)
+               ret = fe->ops.init(fe);
+
+       if (fe->ops.tuner_ops.init)
+               ret = fe->ops.tuner_ops.init(fe);
+
+       fepriv->state = FESTATE_RETUNE;
+       dvb_frontend_wakeup(fe);
+
+       return ret;
+}
+EXPORT_SYMBOL(dvb_frontend_resume);
+
 int dvb_register_frontend(struct dvb_adapter* dvb,
                          struct dvb_frontend* fe)
 {
@@ -2461,7 +2516,7 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
                .kernel_ioctl = dvb_frontend_ioctl
        };
 
-       dprintk ("%s\n", __func__);
+       dev_dbg(dvb->device, "%s:\n", __func__);
 
        if (mutex_lock_interruptible(&frontend_mutex))
                return -ERESTARTSYS;
@@ -2480,10 +2535,9 @@ int dvb_register_frontend(struct dvb_adapter* dvb,
        fe->dvb = dvb;
        fepriv->inversion = INVERSION_OFF;
 
-       printk ("DVB: registering adapter %i frontend %i (%s)...\n",
-               fe->dvb->num,
-               fe->id,
-               fe->ops.info.name);
+       dev_info(fe->dvb->device,
+                       "DVB: registering adapter %i frontend %i (%s)...\n",
+                       fe->dvb->num, fe->id, fe->ops.info.name);
 
        dvb_register_device (fe->dvb, &fepriv->dvbdev, &dvbdev_template,
                             fe, DVB_DEVICE_FRONTEND);
@@ -2504,7 +2558,7 @@ EXPORT_SYMBOL(dvb_register_frontend);
 int dvb_unregister_frontend(struct dvb_frontend* fe)
 {
        struct dvb_frontend_private *fepriv = fe->frontend_priv;
-       dprintk ("%s\n", __func__);
+       dev_dbg(fe->dvb->device, "%s:\n", __func__);
 
        mutex_lock(&frontend_mutex);
        dvb_frontend_stop (fe);
similarity index 98%
rename from drivers/media/dvb/dvb-core/dvb_frontend.h
rename to drivers/media/dvb-core/dvb_frontend.h
index 7c64c09103a94d1e15f7b57c32ae21da4720e716..44a445cee74f53b2fe5aa010323bd09308f293b1 100644 (file)
@@ -303,6 +303,7 @@ struct dvb_frontend_ops {
        int (*dishnetwork_send_legacy_command)(struct dvb_frontend* fe, unsigned long cmd);
        int (*i2c_gate_ctrl)(struct dvb_frontend* fe, int enable);
        int (*ts_bus_ctrl)(struct dvb_frontend* fe, int acquire);
+       int (*set_lna)(struct dvb_frontend *, int);
 
        /* These callbacks are for devices that implement their own
         * tuning algorithms, rather than a simple swzigzag
@@ -354,6 +355,8 @@ struct dtv_frontend_properties {
 
        fe_delivery_system_t    delivery_system;
 
+       enum fe_interleaving    interleaving;
+
        /* ISDB-T specifics */
        u8                      isdbt_partial_reception;
        u8                      isdbt_sb_mode;
@@ -368,11 +371,8 @@ struct dtv_frontend_properties {
            u8                  interleaving;
        } layer[3];
 
-       /* ISDB-T specifics */
-       u32                     isdbs_ts_id;
-
-       /* DVB-T2 specifics */
-       u32                     dvbt2_plp_id;
+       /* Multistream specifics */
+       u32                     stream_id;
 
        /* ATSC-MH specifics */
        u8                      atscmh_fic_ver;
@@ -416,6 +416,8 @@ extern int dvb_unregister_frontend(struct dvb_frontend *fe);
 extern void dvb_frontend_detach(struct dvb_frontend *fe);
 
 extern void dvb_frontend_reinitialise(struct dvb_frontend *fe);
+extern int dvb_frontend_suspend(struct dvb_frontend *fe);
+extern int dvb_frontend_resume(struct dvb_frontend *fe);
 
 extern void dvb_frontend_sleep_until(struct timeval *waketime, u32 add_usec);
 extern s32 timeval_usec_diff(struct timeval lasttime, struct timeval curtime);
similarity index 99%
rename from drivers/media/dvb/dvb-core/dvbdev.c
rename to drivers/media/dvb-core/dvbdev.c
index 39eab73b01ae9bb5e0a9c4d9667e3c99b4b51415..d33101aaf0b5e6bb51e55baef9b21ba0d53c4e9a 100644 (file)
@@ -420,7 +420,7 @@ int dvb_usercopy(struct file *file,
        /* call driver */
        mutex_lock(&dvbdev_mutex);
        if ((err = func(file, cmd, parg)) == -ENOIOCTLCMD)
-               err = -EINVAL;
+               err = -ENOTTY;
        mutex_unlock(&dvbdev_mutex);
 
        if (err < 0)
similarity index 80%
rename from drivers/media/dvb/dvb-core/dvbdev.h
rename to drivers/media/dvb-core/dvbdev.h
index fcc6ae98745e018588d21d83af953c6765aad85c..93a9470d3f0c7c19d3d9391bdc37a27ac66a7e6e 100644 (file)
@@ -71,32 +71,6 @@ struct dvb_adapter {
        int mfe_shared;                 /* indicates mutually exclusive frontends */
        struct dvb_device *mfe_dvbdev;  /* frontend device in use */
        struct mutex mfe_lock;          /* access lock for thread creation */
-
-       /* Allow the adapter/bridge driver to perform an action before and/or
-        * after the core handles an ioctl:
-        *
-        * DVB_FE_IOCTL_PRE indicates that the ioctl has not yet been handled.
-        * DVB_FE_IOCTL_POST indicates that the ioctl has been handled.
-        *
-        * When DVB_FE_IOCTL_PRE is passed to the callback as the stage arg:
-        *
-        * return 0 to allow dvb-core to handle the ioctl.
-        * return a positive int to prevent dvb-core from handling the ioctl,
-        *      and exit without error.
-        * return a negative int to prevent dvb-core from handling the ioctl,
-        *      and return that value as an error.
-        *
-        * When DVB_FE_IOCTL_POST is passed to the callback as the stage arg:
-        *
-        * return 0 to allow the dvb_frontend ioctl handler to exit normally.
-        * return a negative int to cause the dvb_frontend ioctl handler to
-        *      return that value as an error.
-        */
-#define DVB_FE_IOCTL_PRE 0
-#define DVB_FE_IOCTL_POST 1
-       int (*fe_ioctl_override)(struct dvb_frontend *fe,
-                                unsigned int cmd, void *parg,
-                                unsigned int stage);
 };
 
 
similarity index 83%
rename from drivers/media/dvb/frontends/Kconfig
rename to drivers/media/dvb-frontends/Kconfig
index a08c2152d0eeb98c591278731f140a02cc244b03..5efec73a32d28893f04f48b5e9f0be1e99b39aea 100644 (file)
@@ -1,20 +1,5 @@
-config DVB_FE_CUSTOMISE
-       bool "Customise the frontend modules to build"
-       depends on DVB_CORE
-       depends on EXPERT
-       default y if EXPERT
-       help
-         This allows the user to select/deselect frontend drivers for their
-         hardware from the build.
-
-         Use this option with care as deselecting frontends which are in fact
-         necessary will result in DVB devices which cannot be tuned due to lack
-         of driver support.
-
-         If unsure say N.
-
 menu "Customise DVB Frontends"
-       visible if DVB_FE_CUSTOMISE
+       visible if !MEDIA_SUBDRV_AUTOSELECT
 
 comment "Multistandard (satellite) frontends"
        depends on DVB_CORE
@@ -22,7 +7,7 @@ comment "Multistandard (satellite) frontends"
 config DVB_STB0899
        tristate "STB0899 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S/S2/DSS Multistandard demodulator. Say Y when you want
          to support this demodulator based frontends
@@ -30,7 +15,7 @@ config DVB_STB0899
 config DVB_STB6100
        tristate "STB6100 based tuners"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A Silicon tuner from ST used in conjunction with the STB0899
          demodulator. Say Y when you want to support this tuner.
@@ -38,7 +23,7 @@ config DVB_STB6100
 config DVB_STV090x
        tristate "STV0900/STV0903(A/B) based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          DVB-S/S2/DSS Multistandard Professional/Broadcast demodulators.
          Say Y when you want to support these frontends.
@@ -46,7 +31,7 @@ config DVB_STV090x
 config DVB_STV6110x
        tristate "STV6110/(A) based tuners"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A Silicon tuner that supports DVB-S and DVB-S2 modes
 
@@ -56,7 +41,7 @@ comment "Multistandard (cable + terrestrial) frontends"
 config DVB_DRXK
        tristate "Micronas DRXK based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Micronas DRX-K DVB-C/T demodulator.
 
@@ -65,7 +50,7 @@ config DVB_DRXK
 config DVB_TDA18271C2DD
        tristate "NXP TDA18271C2 silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          NXP TDA18271 silicon tuner.
 
@@ -77,119 +62,119 @@ comment "DVB-S (satellite) frontends"
 config DVB_CX24110
        tristate "Conexant CX24110 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX24123
        tristate "Conexant CX24123 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT312
        tristate "Zarlink VP310/MT312/ZL10313 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_ZL10036
        tristate "Zarlink ZL10036 silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_ZL10039
        tristate "Zarlink ZL10039 silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_S5H1420
        tristate "Samsung S5H1420 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_STV0288
        tristate "ST STV0288 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_STB6000
        tristate "ST STB6000 silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
          help
          A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
 config DVB_STV0299
        tristate "ST STV0299 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_STV6110
        tristate "ST STV6110 silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
          help
          A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
 config DVB_STV0900
        tristate "ST STV0900 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S/S2 demodulator. Say Y when you want to support this frontend.
 
 config DVB_TDA8083
        tristate "Philips TDA8083 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA10086
        tristate "Philips TDA10086 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA8261
        tristate "Philips TDA8261 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_VES1X93
        tristate "VLSI VES1893 or VES1993 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TUNER_ITD1000
        tristate "Integrant ITD1000 Zero IF tuner for DVB-S/DSS"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_TUNER_CX24113
        tristate "Conexant CX24113/CX24128 tuner for DVB-S/DSS"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
@@ -197,42 +182,42 @@ config DVB_TUNER_CX24113
 config DVB_TDA826X
        tristate "Philips TDA826X silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S silicon tuner module. Say Y when you want to support this tuner.
 
 config DVB_TUA6100
        tristate "Infineon TUA6100 PLL"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S PLL chip.
 
 config DVB_CX24116
        tristate "Conexant CX24116 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
 
 config DVB_SI21XX
        tristate "Silicon Labs SI21XX based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_DS3000
        tristate "Montage Tehnology DS3000 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S/S2 tuner module. Say Y when you want to support this frontend.
 
 config DVB_MB86A16
        tristate "Fujitsu MB86A16 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S/DSS Direct Conversion reveiver.
          Say Y when you want to support this frontend.
@@ -240,7 +225,7 @@ config DVB_MB86A16
 config DVB_TDA10071
        tristate "NXP TDA10071"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
@@ -250,7 +235,7 @@ comment "DVB-T (terrestrial) frontends"
 config DVB_SP8870
        tristate "Spase sp8870 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -262,7 +247,7 @@ config DVB_SP8870
 config DVB_SP887X
        tristate "Spase sp887x based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -274,28 +259,28 @@ config DVB_SP887X
 config DVB_CX22700
        tristate "Conexant CX22700 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_CX22702
        tristate "Conexant cx22702 demodulator (OFDM)"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_S5H1432
        tristate "Samsung s5h1432 demodulator (OFDM)"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_DRXD
        tristate "Micronas DRXD driver"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -306,14 +291,14 @@ config DVB_DRXD
 config DVB_L64781
        tristate "LSI L64781"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA1004X
        tristate "Philips TDA10045H/TDA10046H based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
@@ -326,28 +311,28 @@ config DVB_TDA1004X
 config DVB_NXT6000
        tristate "NxtWave Communications NXT6000 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_MT352
        tristate "Zarlink MT352 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_ZL10353
        tristate "Zarlink ZL10353 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_DIB3000MB
        tristate "DiBcom 3000M-B"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -355,7 +340,7 @@ config DVB_DIB3000MB
 config DVB_DIB3000MC
        tristate "DiBcom 3000P/M-C"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -363,7 +348,7 @@ config DVB_DIB3000MC
 config DVB_DIB7000M
        tristate "DiBcom 7000MA/MB/PA/PB/MC"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -371,7 +356,7 @@ config DVB_DIB7000M
 config DVB_DIB7000P
        tristate "DiBcom 7000PC"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -379,7 +364,7 @@ config DVB_DIB7000P
 config DVB_DIB9000
        tristate "DiBcom 9000"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Designed for mobile usage. Say Y when you want
          to support this frontend.
@@ -387,56 +372,56 @@ config DVB_DIB9000
 config DVB_TDA10048
        tristate "Philips TDA10048HN based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module. Say Y when you want to support this frontend.
 
 config DVB_AF9013
        tristate "Afatech AF9013 demodulator"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
 config DVB_EC100
        tristate "E3C EC100"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
 config DVB_HD29L2
        tristate "HDIC HD29L2"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
 config DVB_STV0367
        tristate "ST STV0367 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T/C tuner module. Say Y when you want to support this frontend.
 
 config DVB_CXD2820R
        tristate "Sony CXD2820R"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
 config DVB_RTL2830
        tristate "Realtek RTL2830 DVB-T"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
 config DVB_RTL2832
        tristate "Realtek RTL2832 DVB-T"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y when you want to support this frontend.
 
@@ -446,28 +431,28 @@ comment "DVB-C (cable) frontends"
 config DVB_VES1820
        tristate "VLSI VES1820 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA10021
        tristate "Philips TDA10021 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA10023
        tristate "Philips TDA10023 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
 config DVB_STV0297
        tristate "ST STV0297 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-C tuner module. Say Y when you want to support this frontend.
 
@@ -477,7 +462,7 @@ comment "ATSC (North American/Korean Terrestrial/Cable DTV) frontends"
 config DVB_NXT200X
        tristate "NxtWave Communications NXT2002/NXT2004 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -491,7 +476,7 @@ config DVB_NXT200X
 config DVB_OR51211
        tristate "Oren OR51211 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB tuner module. Say Y when you want to support this frontend.
 
@@ -503,7 +488,7 @@ config DVB_OR51211
 config DVB_OR51132
        tristate "Oren OR51132 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -518,7 +503,7 @@ config DVB_OR51132
 config DVB_BCM3510
        tristate "Broadcom BCM3510"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB/16VSB and QAM64/256 tuner module. Say Y when you want to
          support this frontend.
@@ -526,7 +511,7 @@ config DVB_BCM3510
 config DVB_LGDT330X
        tristate "LG Electronics LGDT3302/LGDT3303 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -534,7 +519,7 @@ config DVB_LGDT330X
 config DVB_LGDT3305
        tristate "LG Electronics LGDT3304 and LGDT3305 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -542,7 +527,7 @@ config DVB_LGDT3305
 config DVB_LG2160
        tristate "LG Electronics LG216x based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC/MH demodulator module. Say Y when you want
          to support this frontend.
@@ -550,7 +535,7 @@ config DVB_LG2160
 config DVB_S5H1409
        tristate "Samsung S5H1409 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -563,7 +548,7 @@ config DVB_AU8522_DTV
        tristate "Auvitek AU8522 based DTV demod"
        depends on DVB_CORE && I2C
        select DVB_AU8522
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
          you want to enable DTV demodulation support for this frontend.
@@ -572,7 +557,7 @@ config DVB_AU8522_V4L
        tristate "Auvitek AU8522 based ATV demod"
        depends on VIDEO_V4L2 && I2C
        select DVB_AU8522
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB, QAM64/256 & NTSC demodulator module. Say Y when
          you want to enable ATV demodulation support for this frontend.
@@ -580,7 +565,7 @@ config DVB_AU8522_V4L
 config DVB_S5H1411
        tristate "Samsung S5H1411 based"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An ATSC 8VSB and QAM64/256 tuner module. Say Y when you want
          to support this frontend.
@@ -591,7 +576,7 @@ comment "ISDB-T (terrestrial) frontends"
 config DVB_S921
        tristate "Sharp S921 frontend"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          AN ISDB-T DQPSK, QPSK, 16QAM and 64QAM 1seg tuner module.
          Say Y when you want to support this frontend.
@@ -599,7 +584,7 @@ config DVB_S921
 config DVB_DIB8000
        tristate "DiBcom 8000MB/MC"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for DiBcom's DiB8000 ISDB-T/ISDB-Tsb demodulator.
          Say Y when you want to support this frontend.
@@ -607,7 +592,7 @@ config DVB_DIB8000
 config DVB_MB86A20S
        tristate "Fujitsu mb86a20s"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for Fujitsu mb86a20s ISDB-T/ISDB-Tsb demodulator.
          Say Y when you want to support this frontend.
@@ -618,7 +603,7 @@ comment "Digital terrestrial only tuners/PLL"
 config DVB_PLL
        tristate "Generic I2C PLL based tuners"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          This module drives a number of tuners based on PLL chips with a
          common I2C interface. Say Y when you want to support these tuners.
@@ -626,7 +611,7 @@ config DVB_PLL
 config DVB_TUNER_DIB0070
        tristate "DiBcom DiB0070 silicon base-band tuner"
        depends on I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon baseband tuner DiB0070 from DiBcom.
          This device is only used inside a SiP called together with a
@@ -635,7 +620,7 @@ config DVB_TUNER_DIB0070
 config DVB_TUNER_DIB0090
        tristate "DiBcom DiB0090 silicon base-band tuner"
        depends on I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon baseband tuner DiB0090 from DiBcom.
          This device is only used inside a SiP called together with a
@@ -647,14 +632,14 @@ comment "SEC control devices for DVB-S"
 config DVB_LNBP21
        tristate "LNBP21/LNBH24 SEC controllers"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An SEC control chips.
 
 config DVB_LNBP22
        tristate "LNBP22 SEC controllers"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          LNB power supply and control voltage
          regulator chip with step-up converter
@@ -664,33 +649,33 @@ config DVB_LNBP22
 config DVB_ISL6405
        tristate "ISL6405 SEC controller"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An SEC control chip.
 
 config DVB_ISL6421
        tristate "ISL6421 SEC controller"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          An SEC control chip.
 
 config DVB_ISL6423
        tristate "ISL6423 SEC controller"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A SEC controller chip from Intersil
 
 config DVB_A8293
        tristate "Allegro A8293"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
 
 config DVB_LGS8GL5
        tristate "Silicon Legend LGS-8GL5 demodulator (OFDM)"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DMB-TH tuner module. Say Y when you want to support this frontend.
 
@@ -698,21 +683,21 @@ config DVB_LGS8GXX
        tristate "Legend Silicon LGS8913/LGS8GL5/LGS8GXX DMB-TH demodulator"
        depends on DVB_CORE && I2C
        select FW_LOADER
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DMB-TH tuner module. Say Y when you want to support this frontend.
 
 config DVB_ATBM8830
        tristate "AltoBeam ATBM8830/8831 DMB-TH demodulator"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DMB-TH tuner module. Say Y when you want to support this frontend.
 
 config DVB_TDA665x
        tristate "TDA665x tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Support for tuner modules based on Philips TDA6650/TDA6651 chips.
          Say Y when you want to support this chip.
@@ -723,14 +708,14 @@ config DVB_TDA665x
 config DVB_IX2505V
        tristate "Sharp IX2505V silicon tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module. Say Y when you want to support this frontend.
 
 config DVB_IT913X_FE
        tristate "it913x frontend and it9137 tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T tuner module.
          Say Y when you want to support this frontend.
@@ -738,7 +723,7 @@ config DVB_IT913X_FE
 config DVB_M88RS2000
        tristate "M88RS2000 DVB-S demodulator and tuner"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-S tuner module.
          Say Y when you want to support this frontend.
@@ -746,7 +731,7 @@ config DVB_M88RS2000
 config DVB_AF9033
        tristate "Afatech AF9033 DVB-T demodulator"
        depends on DVB_CORE && I2C
-       default m if DVB_FE_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
 
 comment "Tools to develop new frontends"
 
similarity index 92%
rename from drivers/media/dvb/frontends/Makefile
rename to drivers/media/dvb-frontends/Makefile
index 185bb8b51952ec0190aa4a35c2c0bd0cbfbef42e..7eb73bbd2e26b631fdb45dcd27edf28b24132652 100644 (file)
@@ -2,13 +2,13 @@
 # Makefile for the kernel DVB frontend device drivers.
 #
 
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core/
-ccflags-y += -I$(srctree)/drivers/media/common/tuners/
+ccflags-y += -I$(srctree)/drivers/media/dvb-core/
+ccflags-y += -I$(srctree)/drivers/media/tuners/
 
-stb0899-objs = stb0899_drv.o stb0899_algo.o
-stv0900-objs = stv0900_core.o stv0900_sw.o
-drxd-objs = drxd_firm.o drxd_hard.o
-cxd2820r-objs = cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
+stb0899-objs := stb0899_drv.o stb0899_algo.o
+stv0900-objs := stv0900_core.o stv0900_sw.o
+drxd-objs := drxd_firm.o drxd_hard.o
+cxd2820r-objs := cxd2820r_core.o cxd2820r_c.o cxd2820r_t.o cxd2820r_t2.o
 drxk-objs := drxk_hard.o
 
 obj-$(CONFIG_DVB_PLL) += dvb-pll.o
similarity index 86%
rename from drivers/media/dvb/frontends/af9013.c
rename to drivers/media/dvb-frontends/af9013.c
index 5bc570d7784669df4599555525f7586f69d52a81..e9f04a36577b582849f5f5d9ae29f7466462dac0 100644 (file)
 
 #include "af9013_priv.h"
 
-int af9013_debug;
-module_param_named(debug, af9013_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
 struct af9013_state {
        struct i2c_adapter *i2c;
        struct dvb_frontend fe;
@@ -73,7 +69,8 @@ static int af9013_wr_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed=%d reg=%04x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%04x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -107,7 +104,8 @@ static int af9013_rd_regs_i2c(struct af9013_state *priv, u8 mbox, u16 reg,
        if (ret == 2) {
                ret = 0;
        } else {
-               warn("i2c rd failed=%d reg=%04x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%04x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -220,7 +218,8 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
        u8 pos;
        u16 addr;
 
-       dbg("%s: gpio=%d gpioval=%02x", __func__, gpio, gpioval);
+       dev_dbg(&state->i2c->dev, "%s: gpio=%d gpioval=%02x\n",
+                       __func__, gpio, gpioval);
 
        /*
         * GPIO0 & GPIO1 0xd735
@@ -238,7 +237,8 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
                break;
 
        default:
-               err("invalid gpio:%d\n", gpio);
+               dev_err(&state->i2c->dev, "%s: invalid gpio=%d\n",
+                               KBUILD_MODNAME, gpio);
                ret = -EINVAL;
                goto err;
        };
@@ -261,15 +261,15 @@ static int af9013_set_gpio(struct af9013_state *state, u8 gpio, u8 gpioval)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-static u32 af913_div(u32 a, u32 b, u32 x)
+static u32 af9013_div(struct af9013_state *state, u32 a, u32 b, u32 x)
 {
        u32 r = 0, c = 0, i;
 
-       dbg("%s: a=%d b=%d x=%d", __func__, a, b, x);
+       dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
 
        if (a > b) {
                c = a / b;
@@ -286,7 +286,9 @@ static u32 af913_div(u32 a, u32 b, u32 x)
        }
        r = (c << (u32)x) + r;
 
-       dbg("%s: a=%d b=%d x=%d r=%x", __func__, a, b, x, r);
+       dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n",
+                       __func__, a, b, x, r, r);
+
        return r;
 }
 
@@ -295,7 +297,7 @@ static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
        int ret, i;
        u8 tmp;
 
-       dbg("%s: onoff=%d", __func__, onoff);
+       dev_dbg(&state->i2c->dev, "%s: onoff=%d\n", __func__, onoff);
 
        /* enable reset */
        ret = af9013_wr_reg_bits(state, 0xd417, 4, 1, 1);
@@ -340,7 +342,7 @@ static int af9013_power_ctrl(struct af9013_state *state, u8 onoff)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -349,7 +351,7 @@ static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
        struct af9013_state *state = fe->demodulator_priv;
        int ret;
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* reset and start BER counter */
        ret = af9013_wr_reg_bits(state, 0xd391, 4, 1, 1);
@@ -358,7 +360,7 @@ static int af9013_statistics_ber_unc_start(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -368,7 +370,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
        int ret;
        u8 buf[5];
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* check if error bit count is ready */
        ret = af9013_rd_reg_bits(state, 0xd391, 4, 1, &buf[0]);
@@ -376,7 +378,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
                goto err;
 
        if (!buf[0]) {
-               dbg("%s: not ready", __func__);
+               dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__);
                return 0;
        }
 
@@ -389,7 +391,7 @@ static int af9013_statistics_ber_unc_result(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -398,7 +400,7 @@ static int af9013_statistics_snr_start(struct dvb_frontend *fe)
        struct af9013_state *state = fe->demodulator_priv;
        int ret;
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* start SNR meas */
        ret = af9013_wr_reg_bits(state, 0xd2e1, 3, 1, 1);
@@ -407,7 +409,7 @@ static int af9013_statistics_snr_start(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -419,7 +421,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
        u32 snr_val;
        const struct af9013_snr *uninitialized_var(snr_lut);
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* check if SNR ready */
        ret = af9013_rd_reg_bits(state, 0xd2e1, 3, 1, &tmp);
@@ -427,7 +429,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
                goto err;
 
        if (!tmp) {
-               dbg("%s: not ready", __func__);
+               dev_dbg(&state->i2c->dev, "%s: not ready\n", __func__);
                return 0;
        }
 
@@ -471,7 +473,7 @@ static int af9013_statistics_snr_result(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -482,7 +484,7 @@ static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
        u8 buf[2], rf_gain, if_gain;
        int signal_strength;
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        if (!state->signal_strength_en)
                return 0;
@@ -508,7 +510,7 @@ static int af9013_statistics_signal_strength(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -578,8 +580,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
        u8 buf[6];
        u32 if_frequency, freq_cw;
 
-       dbg("%s: frequency=%d bandwidth_hz=%d", __func__,
-               c->frequency, c->bandwidth_hz);
+       dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+                       __func__, c->frequency, c->bandwidth_hz);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
@@ -606,6 +608,9 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                else
                        if_frequency = state->config.if_frequency;
 
+               dev_dbg(&state->i2c->dev, "%s: if_frequency=%d\n",
+                               __func__, if_frequency);
+
                sampling_freq = if_frequency;
 
                while (sampling_freq > (state->config.clock / 2))
@@ -618,7 +623,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                        spec_inv = !state->config.spec_inv;
                }
 
-               freq_cw = af913_div(sampling_freq, state->config.clock, 23);
+               freq_cw = af9013_div(state, sampling_freq, state->config.clock,
+                               23);
 
                if (spec_inv)
                        freq_cw = 0x800000 - freq_cw;
@@ -676,7 +682,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[0] |= (1 << 0);
                break;
        default:
-               dbg("%s: invalid transmission_mode", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid transmission_mode\n",
+                               __func__);
                auto_mode = 1;
        }
 
@@ -696,7 +703,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[0] |= (3 << 2);
                break;
        default:
-               dbg("%s: invalid guard_interval", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid guard_interval\n",
+                               __func__);
                auto_mode = 1;
        }
 
@@ -716,7 +724,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[0] |= (3 << 4);
                break;
        default:
-               dbg("%s: invalid hierarchy", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid hierarchy\n", __func__);
                auto_mode = 1;
        };
 
@@ -733,7 +741,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[1] |= (2 << 6);
                break;
        default:
-               dbg("%s: invalid modulation", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid modulation\n", __func__);
                auto_mode = 1;
        }
 
@@ -759,7 +767,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[2] |= (4 << 0);
                break;
        default:
-               dbg("%s: invalid code_rate_HP", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid code_rate_HP\n",
+                               __func__);
                auto_mode = 1;
        }
 
@@ -784,7 +793,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
        case FEC_NONE:
                break;
        default:
-               dbg("%s: invalid code_rate_LP", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid code_rate_LP\n",
+                               __func__);
                auto_mode = 1;
        }
 
@@ -798,7 +808,8 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                buf[1] |= (2 << 2);
                break;
        default:
-               dbg("%s: invalid bandwidth_hz", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n",
+                               __func__);
                ret = -EINVAL;
                goto err;
        }
@@ -813,7 +824,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                if (ret)
                        goto err;
 
-               dbg("%s: auto params", __func__);
+               dev_dbg(&state->i2c->dev, "%s: auto params\n", __func__);
        } else {
                /* set easy mode flag */
                ret = af9013_wr_reg(state, 0xaefd, 1);
@@ -824,7 +835,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
                if (ret)
                        goto err;
 
-               dbg("%s: manual params", __func__);
+               dev_dbg(&state->i2c->dev, "%s: manual params\n", __func__);
        }
 
        /* tune */
@@ -838,7 +849,7 @@ static int af9013_set_frontend(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -849,7 +860,7 @@ static int af9013_get_frontend(struct dvb_frontend *fe)
        int ret;
        u8 buf[3];
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        ret = af9013_rd_regs(state, 0xd3c0, buf, 3);
        if (ret)
@@ -955,7 +966,7 @@ static int af9013_get_frontend(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1005,7 +1016,7 @@ static int af9013_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1045,7 +1056,7 @@ static int af9013_init(struct dvb_frontend *fe)
        u32 adc_cw;
        const struct af9013_reg_bit *init;
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* power on */
        ret = af9013_power_ctrl(state, 1);
@@ -1077,11 +1088,12 @@ static int af9013_init(struct dvb_frontend *fe)
                tmp = 3;
                break;
        default:
-               err("invalid clock");
+               dev_err(&state->i2c->dev, "%s: invalid clock\n",
+                               KBUILD_MODNAME);
                return -EINVAL;
        }
 
-       adc_cw = af913_div(state->config.clock, 1000000ul, 19);
+       adc_cw = af9013_div(state, state->config.clock, 1000000ul, 19);
        buf[0] = (adc_cw >>  0) & 0xff;
        buf[1] = (adc_cw >>  8) & 0xff;
        buf[2] = (adc_cw >> 16) & 0xff;
@@ -1137,7 +1149,7 @@ static int af9013_init(struct dvb_frontend *fe)
                goto err;
 
        /* load OFSM settings */
-       dbg("%s: load ofsm settings", __func__);
+       dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
        len = ARRAY_SIZE(ofsm_init);
        init = ofsm_init;
        for (i = 0; i < len; i++) {
@@ -1148,7 +1160,8 @@ static int af9013_init(struct dvb_frontend *fe)
        }
 
        /* load tuner specific settings */
-       dbg("%s: load tuner specific settings", __func__);
+       dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
+                       __func__);
        switch (state->config.tuner) {
        case AF9013_TUNER_MXL5003D:
                len = ARRAY_SIZE(tuner_init_mxl5003d);
@@ -1259,7 +1272,7 @@ static int af9013_init(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1268,7 +1281,7 @@ static int af9013_sleep(struct dvb_frontend *fe)
        struct af9013_state *state = fe->demodulator_priv;
        int ret;
 
-       dbg("%s", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* stop statistics polling */
        cancel_delayed_work_sync(&state->statistics_work);
@@ -1285,7 +1298,7 @@ static int af9013_sleep(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1294,7 +1307,7 @@ static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        int ret;
        struct af9013_state *state = fe->demodulator_priv;
 
-       dbg("%s: enable=%d", __func__, enable);
+       dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable);
 
        /* gate already open or close */
        if (state->i2c_gate_state == enable)
@@ -1311,7 +1324,7 @@ static int af9013_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1330,7 +1343,7 @@ static int af9013_download_firmware(struct af9013_state *state)
        u16 checksum = 0;
        u8 val;
        u8 fw_params[4];
-       u8 *fw_file = AF9013_DEFAULT_FIRMWARE;
+       u8 *fw_file = AF9013_FIRMWARE;
 
        msleep(100);
        /* check whether firmware is already running */
@@ -1338,25 +1351,28 @@ static int af9013_download_firmware(struct af9013_state *state)
        if (ret)
                goto err;
        else
-               dbg("%s: firmware status=%02x", __func__, val);
+               dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n",
+                               __func__, val);
 
        if (val == 0x0c) /* fw is running, no need for download */
                goto exit;
 
-       info("found a '%s' in cold state, will try to load a firmware",
-               af9013_ops.info.name);
+       dev_info(&state->i2c->dev, "%s: found a '%s' in cold state, will try " \
+                       "to load a firmware\n",
+                       KBUILD_MODNAME, af9013_ops.info.name);
 
        /* request the firmware, this will block and timeout */
        ret = request_firmware(&fw, fw_file, state->i2c->dev.parent);
        if (ret) {
-               err("did not find the firmware file. (%s) "
-                       "Please see linux/Documentation/dvb/ for more details" \
-                       " on firmware-problems. (%d)",
-                       fw_file, ret);
+               dev_info(&state->i2c->dev, "%s: did not find the firmware " \
+                       "file. (%s) Please see linux/Documentation/dvb/ for " \
+                       "more details on firmware-problems. (%d)\n",
+                       KBUILD_MODNAME, fw_file, ret);
                goto err;
        }
 
-       info("downloading firmware from file '%s'", fw_file);
+       dev_info(&state->i2c->dev, "%s: downloading firmware from file '%s'\n",
+                       KBUILD_MODNAME, fw_file);
 
        /* calc checksum */
        for (i = 0; i < fw->size; i++)
@@ -1384,7 +1400,9 @@ static int af9013_download_firmware(struct af9013_state *state)
                        FW_ADDR + fw->size - remaining,
                        (u8 *) &fw->data[fw->size - remaining], len);
                if (ret) {
-                       err("firmware download failed:%d", ret);
+                       dev_err(&state->i2c->dev,
+                                       "%s: firmware download failed=%d\n",
+                                       KBUILD_MODNAME, ret);
                        goto err_release;
                }
        }
@@ -1402,17 +1420,20 @@ static int af9013_download_firmware(struct af9013_state *state)
                if (ret)
                        goto err_release;
 
-               dbg("%s: firmware status=%02x", __func__, val);
+               dev_dbg(&state->i2c->dev, "%s: firmware status=%02x\n",
+                               __func__, val);
 
                if (val == 0x0c || val == 0x04) /* success or fail */
                        break;
        }
 
        if (val == 0x04) {
-               err("firmware did not run");
+               dev_err(&state->i2c->dev, "%s: firmware did not run\n",
+                               KBUILD_MODNAME);
                ret = -ENODEV;
        } else if (val != 0x0c) {
-               err("firmware boot timeout");
+               dev_err(&state->i2c->dev, "%s: firmware boot timeout\n",
+                               KBUILD_MODNAME);
                ret = -ENODEV;
        }
 
@@ -1421,7 +1442,8 @@ err_release:
 err:
 exit:
        if (!ret)
-               info("found a '%s' in warm state.", af9013_ops.info.name);
+               dev_info(&state->i2c->dev, "%s: found a '%s' in warm state\n",
+                               KBUILD_MODNAME, af9013_ops.info.name);
        return ret;
 }
 
@@ -1453,7 +1475,8 @@ struct dvb_frontend *af9013_attach(const struct af9013_config *config,
        if (ret)
                goto err;
 
-       info("firmware version %d.%d.%d.%d", buf[0], buf[1], buf[2], buf[3]);
+       dev_info(&state->i2c->dev, "%s: firmware version %d.%d.%d.%d\n",
+                       KBUILD_MODNAME, buf[0], buf[1], buf[2], buf[3]);
 
        /* set GPIOs */
        for (i = 0; i < sizeof(state->config.gpio); i++) {
@@ -1522,3 +1545,4 @@ static struct dvb_frontend_ops af9013_ops = {
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Afatech AF9013 DVB-T demodulator driver");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(AF9013_FIRMWARE);
similarity index 97%
rename from drivers/media/dvb/frontends/af9013.h
rename to drivers/media/dvb-frontends/af9013.h
index b973fc5a03844d68db01ee8ed2743192688b9263..dc837d91327ae682ec3fae3c65e4875064017717 100644 (file)
@@ -110,7 +110,7 @@ extern struct dvb_frontend *af9013_attach(const struct af9013_config *config,
 static inline struct dvb_frontend *af9013_attach(
 const struct af9013_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif /* CONFIG_DVB_AF9013 */
similarity index 98%
rename from drivers/media/dvb/frontends/af9013_priv.h
rename to drivers/media/dvb-frontends/af9013_priv.h
index fa848af6e9b403fe6b8c7d9eec07d9b06647776b..8b9392cfc00dd13ddfb6d6834bbe370e6b474438 100644 (file)
 #include "af9013.h"
 #include <linux/firmware.h>
 
-#define LOG_PREFIX "af9013"
-
-#undef dbg
-#define dbg(f, arg...) \
-       if (af9013_debug) \
-               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#define AF9013_DEFAULT_FIRMWARE     "dvb-fe-af9013.fw"
+#define AF9013_FIRMWARE "dvb-fe-af9013.fw"
 
 struct af9013_reg_bit {
        u16 addr;
similarity index 86%
rename from drivers/media/dvb/frontends/af9033.c
rename to drivers/media/dvb-frontends/af9033.c
index a38998286260043f9fdc9fa294c3bab8ccdd7306..464ad878490bb5026dcd5a2ffd9ae95004c17366 100644 (file)
@@ -59,8 +59,8 @@ static int af9033_wr_regs(struct af9033_state *state, u32 reg, const u8 *val,
        if (ret == 1) {
                ret = 0;
        } else {
-               printk(KERN_WARNING "%s: i2c wr failed=%d reg=%06x len=%d\n",
-                               __func__, ret, reg, len);
+               dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%06x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -91,8 +91,8 @@ static int af9033_rd_regs(struct af9033_state *state, u32 reg, u8 *val, int len)
        if (ret == 2) {
                ret = 0;
        } else {
-               printk(KERN_WARNING "%s: i2c rd failed=%d reg=%06x len=%d\n",
-                               __func__, ret, reg, len);
+               dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%06x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -156,11 +156,11 @@ static int af9033_rd_reg_mask(struct af9033_state *state, u32 reg, u8 *val,
        return 0;
 }
 
-static u32 af9033_div(u32 a, u32 b, u32 x)
+static u32 af9033_div(struct af9033_state *state, u32 a, u32 b, u32 x)
 {
        u32 r = 0, c = 0, i;
 
-       pr_debug("%s: a=%d b=%d x=%d\n", __func__, a, b, x);
+       dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d\n", __func__, a, b, x);
 
        if (a > b) {
                c = a / b;
@@ -177,7 +177,8 @@ static u32 af9033_div(u32 a, u32 b, u32 x)
        }
        r = (c << (u32)x) + r;
 
-       pr_debug("%s: a=%d b=%d x=%d r=%d r=%x\n", __func__, a, b, x, r, r);
+       dev_dbg(&state->i2c->dev, "%s: a=%d b=%d x=%d r=%d r=%x\n",
+                       __func__, a, b, x, r, r);
 
        return r;
 }
@@ -225,14 +226,14 @@ static int af9033_init(struct dvb_frontend *fe)
        };
 
        /* program clock control */
-       clock_cw = af9033_div(state->cfg.clock, 1000000ul, 19ul);
+       clock_cw = af9033_div(state, state->cfg.clock, 1000000ul, 19ul);
        buf[0] = (clock_cw >>  0) & 0xff;
        buf[1] = (clock_cw >>  8) & 0xff;
        buf[2] = (clock_cw >> 16) & 0xff;
        buf[3] = (clock_cw >> 24) & 0xff;
 
-       pr_debug("%s: clock=%d clock_cw=%08x\n", __func__, state->cfg.clock,
-                       clock_cw);
+       dev_dbg(&state->i2c->dev, "%s: clock=%d clock_cw=%08x\n",
+                       __func__, state->cfg.clock, clock_cw);
 
        ret = af9033_wr_regs(state, 0x800025, buf, 4);
        if (ret < 0)
@@ -244,13 +245,13 @@ static int af9033_init(struct dvb_frontend *fe)
                        break;
        }
 
-       adc_cw = af9033_div(clock_adc_lut[i].adc, 1000000ul, 19ul);
+       adc_cw = af9033_div(state, clock_adc_lut[i].adc, 1000000ul, 19ul);
        buf[0] = (adc_cw >>  0) & 0xff;
        buf[1] = (adc_cw >>  8) & 0xff;
        buf[2] = (adc_cw >> 16) & 0xff;
 
-       pr_debug("%s: adc=%d adc_cw=%06x\n", __func__, clock_adc_lut[i].adc,
-                       adc_cw);
+       dev_dbg(&state->i2c->dev, "%s: adc=%d adc_cw=%06x\n",
+                       __func__, clock_adc_lut[i].adc, adc_cw);
 
        ret = af9033_wr_regs(state, 0x80f1cd, buf, 3);
        if (ret < 0)
@@ -284,7 +285,7 @@ static int af9033_init(struct dvb_frontend *fe)
        }
 
        /* load OFSM settings */
-       pr_debug("%s: load ofsm settings\n", __func__);
+       dev_dbg(&state->i2c->dev, "%s: load ofsm settings\n", __func__);
        len = ARRAY_SIZE(ofsm_init);
        init = ofsm_init;
        for (i = 0; i < len; i++) {
@@ -294,7 +295,7 @@ static int af9033_init(struct dvb_frontend *fe)
        }
 
        /* load tuner specific settings */
-       pr_debug("%s: load tuner specific settings\n",
+       dev_dbg(&state->i2c->dev, "%s: load tuner specific settings\n",
                        __func__);
        switch (state->cfg.tuner) {
        case AF9033_TUNER_TUA9001:
@@ -313,9 +314,13 @@ static int af9033_init(struct dvb_frontend *fe)
                len = ARRAY_SIZE(tuner_init_tda18218);
                init = tuner_init_tda18218;
                break;
+       case AF9033_TUNER_FC2580:
+               len = ARRAY_SIZE(tuner_init_fc2580);
+               init = tuner_init_fc2580;
+               break;
        default:
-               pr_debug("%s: unsupported tuner ID=%d\n", __func__,
-                               state->cfg.tuner);
+               dev_dbg(&state->i2c->dev, "%s: unsupported tuner ID=%d\n",
+                               __func__, state->cfg.tuner);
                ret = -ENODEV;
                goto err;
        }
@@ -331,7 +336,7 @@ static int af9033_init(struct dvb_frontend *fe)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -358,7 +363,7 @@ static int af9033_sleep(struct dvb_frontend *fe)
                usleep_range(200, 10000);
        }
 
-       pr_debug("%s: loop=%d\n", __func__, i);
+       dev_dbg(&state->i2c->dev, "%s: loop=%d\n", __func__, i);
 
        if (i == 0) {
                ret = -ETIMEDOUT;
@@ -384,7 +389,7 @@ static int af9033_sleep(struct dvb_frontend *fe)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -403,12 +408,12 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
 {
        struct af9033_state *state = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
-       int ret, i, spec_inv;
+       int ret, i, spec_inv, sampling_freq;
        u8 tmp, buf[3], bandwidth_reg_val;
        u32 if_frequency, freq_cw, adc_freq;
 
-       pr_debug("%s: frequency=%d bandwidth_hz=%d\n", __func__, c->frequency,
-                       c->bandwidth_hz);
+       dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+                       __func__, c->frequency, c->bandwidth_hz);
 
        /* check bandwidth */
        switch (c->bandwidth_hz) {
@@ -422,7 +427,8 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
                bandwidth_reg_val = 0x02;
                break;
        default:
-               pr_debug("%s: invalid bandwidth_hz\n", __func__);
+               dev_dbg(&state->i2c->dev, "%s: invalid bandwidth_hz\n",
+                               __func__);
                ret = -EINVAL;
                goto err;
        }
@@ -459,18 +465,20 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
                else
                        if_frequency = 0;
 
-               while (if_frequency > (adc_freq / 2))
-                       if_frequency -= adc_freq;
+               sampling_freq = if_frequency;
+
+               while (sampling_freq > (adc_freq / 2))
+                       sampling_freq -= adc_freq;
 
-               if (if_frequency >= 0)
+               if (sampling_freq >= 0)
                        spec_inv *= -1;
                else
-                       if_frequency *= -1;
+                       sampling_freq *= -1;
 
-               freq_cw = af9033_div(if_frequency, adc_freq, 23ul);
+               freq_cw = af9033_div(state, sampling_freq, adc_freq, 23ul);
 
                if (spec_inv == -1)
-                       freq_cw *= -1;
+                       freq_cw = 0x800000 - freq_cw;
 
                /* get adc multiplies */
                ret = af9033_rd_reg(state, 0x800045, &tmp);
@@ -522,7 +530,7 @@ static int af9033_set_frontend(struct dvb_frontend *fe)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -534,7 +542,7 @@ static int af9033_get_frontend(struct dvb_frontend *fe)
        int ret;
        u8 buf[8];
 
-       pr_debug("%s\n", __func__);
+       dev_dbg(&state->i2c->dev, "%s:\n", __func__);
 
        /* read all needed registers */
        ret = af9033_rd_regs(state, 0x80f900, buf, sizeof(buf));
@@ -649,7 +657,7 @@ static int af9033_get_frontend(struct dvb_frontend *fe)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -695,7 +703,7 @@ static int af9033_read_status(struct dvb_frontend *fe, fe_status_t *status)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -749,7 +757,7 @@ static int af9033_read_snr(struct dvb_frontend *fe, u16 *snr)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -771,7 +779,7 @@ static int af9033_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -815,7 +823,8 @@ static int af9033_update_ch_stat(struct af9033_state *state)
 
        return 0;
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
        return ret;
 }
 
@@ -852,7 +861,7 @@ static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        struct af9033_state *state = fe->demodulator_priv;
        int ret;
 
-       pr_debug("%s: enable=%d\n", __func__, enable);
+       dev_dbg(&state->i2c->dev, "%s: enable=%d\n", __func__, enable);
 
        ret = af9033_wr_reg_mask(state, 0x00fa04, enable, 0x01);
        if (ret < 0)
@@ -861,7 +870,7 @@ static int af9033_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -875,7 +884,7 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
        struct af9033_state *state;
        u8 buf[8];
 
-       pr_debug("%s:\n", __func__);
+       dev_dbg(&i2c->dev, "%s:\n", __func__);
 
        /* allocate memory for the internal state */
        state = kzalloc(sizeof(struct af9033_state), GFP_KERNEL);
@@ -887,9 +896,9 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
        memcpy(&state->cfg, config, sizeof(struct af9033_config));
 
        if (state->cfg.clock != 12000000) {
-               printk(KERN_INFO "af9033: unsupported clock=%d, only " \
-                               "12000000 Hz is supported currently\n",
-                               state->cfg.clock);
+               dev_err(&state->i2c->dev, "%s: af9033: unsupported clock=%d, " \
+                               "only 12000000 Hz is supported currently\n",
+                               KBUILD_MODNAME, state->cfg.clock);
                goto err;
        }
 
@@ -902,9 +911,18 @@ struct dvb_frontend *af9033_attach(const struct af9033_config *config,
        if (ret < 0)
                goto err;
 
-       printk(KERN_INFO "af9033: firmware version: LINK=%d.%d.%d.%d " \
-                       "OFDM=%d.%d.%d.%d\n", buf[0], buf[1], buf[2], buf[3],
-                       buf[4], buf[5], buf[6], buf[7]);
+       dev_info(&state->i2c->dev, "%s: firmware version: LINK=%d.%d.%d.%d " \
+                       "OFDM=%d.%d.%d.%d\n", KBUILD_MODNAME, buf[0], buf[1],
+                       buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]);
+
+       /* sleep */
+       ret = af9033_wr_reg(state, 0x80004c, 1);
+       if (ret < 0)
+               goto err;
+
+       ret = af9033_wr_reg(state, 0x800000, 0);
+       if (ret < 0)
+               goto err;
 
        /* configure internal TS mode */
        switch (state->cfg.ts_mode) {
similarity index 94%
rename from drivers/media/dvb/frontends/af9033.h
rename to drivers/media/dvb-frontends/af9033.h
index 9e302c3f0f7d1e91a780117c40c557603b1a20ca..bfa4313fde215ed00527358d8f80022394bf638d 100644 (file)
@@ -42,6 +42,7 @@ struct af9033_config {
 #define AF9033_TUNER_FC0011      0x28 /* Fitipower FC0011 */
 #define AF9033_TUNER_MXL5007T    0xa0 /* MaxLinear MxL5007T */
 #define AF9033_TUNER_TDA18218    0xa1 /* NXP TDA 18218HN */
+#define AF9033_TUNER_FC2580      0x32 /* FCI FC2580 */
        u8 tuner;
 
        /*
@@ -67,7 +68,7 @@ extern struct dvb_frontend *af9033_attach(const struct af9033_config *config,
 static inline struct dvb_frontend *af9033_attach(
        const struct af9033_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
similarity index 92%
rename from drivers/media/dvb/frontends/af9033_priv.h
rename to drivers/media/dvb-frontends/af9033_priv.h
index 0b783b9ed75ebc44b0ec5c5ae2aaa0ba102eb03f..34dddcd77538d69a6bbde558a85d4817a05f42d0 100644 (file)
@@ -466,5 +466,42 @@ static const struct reg_val tuner_init_tda18218[] = {
        {0x80f1e6, 0x00},
 };
 
+/* FCI FC2580 tuner init */
+static const struct reg_val tuner_init_fc2580[] = {
+       { 0x800046, 0x32 },
+       { 0x800057, 0x01 },
+       { 0x800058, 0x00 },
+       { 0x80005f, 0x00 },
+       { 0x800060, 0x00 },
+       { 0x800071, 0x05 },
+       { 0x800072, 0x02 },
+       { 0x800074, 0x01 },
+       { 0x800079, 0x01 },
+       { 0x800093, 0x00 },
+       { 0x800094, 0x00 },
+       { 0x800095, 0x00 },
+       { 0x800096, 0x05 },
+       { 0x8000b3, 0x01 },
+       { 0x8000c3, 0x01 },
+       { 0x8000c4, 0x00 },
+       { 0x80f007, 0x00 },
+       { 0x80f00c, 0x19 },
+       { 0x80f00d, 0x1A },
+       { 0x80f00e, 0x00 },
+       { 0x80f00f, 0x02 },
+       { 0x80f010, 0x00 },
+       { 0x80f011, 0x02 },
+       { 0x80f012, 0x00 },
+       { 0x80f013, 0x02 },
+       { 0x80f014, 0x00 },
+       { 0x80f015, 0x02 },
+       { 0x80f01f, 0x96 },
+       { 0x80f020, 0x00 },
+       { 0x80f029, 0x96 },
+       { 0x80f02a, 0x00 },
+       { 0x80f077, 0x01 },
+       { 0x80f1e6, 0x01 },
+};
+
 #endif /* AF9033_PRIV_H */
 
similarity index 99%
rename from drivers/media/dvb/frontends/atbm8830.c
rename to drivers/media/dvb-frontends/atbm8830.c
index a2261ea2cf82a3cf148dbb5515e3add5a309756d..4e11dc4b13350f7640b0374020af1c533800d6f2 100644 (file)
@@ -428,7 +428,7 @@ static int atbm8830_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 
 static struct dvb_frontend_ops atbm8830_ops = {
-       .delsys = { SYS_DMBTH },
+       .delsys = { SYS_DTMB },
        .info = {
                .name = "AltoBeam ATBM8830/8831 DMB-TH",
                .frequency_min = 474000000,
similarity index 93%
rename from drivers/media/dvb/frontends/au8522_common.c
rename to drivers/media/dvb-frontends/au8522_common.c
index 5cfe151ee394057cfac74059c10ed557494191f1..3559ff230045450ad885bf8e118aaa27a80c50df 100644 (file)
@@ -26,8 +26,6 @@
 #include "dvb_frontend.h"
 #include "au8522_priv.h"
 
-MODULE_LICENSE("GPL");
-
 static int debug;
 
 #define dprintk(arg...)\
@@ -101,6 +99,19 @@ int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 EXPORT_SYMBOL(au8522_i2c_gate_ctrl);
 
+int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
+{
+       struct au8522_state *state = fe->demodulator_priv;
+
+       dprintk("%s(%d)\n", __func__, enable);
+
+       if (enable)
+               return au8522_writereg(state, 0x106, 1);
+       else
+               return au8522_writereg(state, 0x106, 0);
+}
+EXPORT_SYMBOL(au8522_analog_i2c_gate_ctrl);
+
 /* Reset the demod hardware and reset all of the configuration registers
    to a default state. */
 int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
@@ -257,3 +268,10 @@ int au8522_sleep(struct dvb_frontend *fe)
        return 0;
 }
 EXPORT_SYMBOL(au8522_sleep);
+
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "Enable verbose debug messages");
+
+MODULE_DESCRIPTION("Auvitek AU8522 QAM-B/ATSC Demodulator driver");
+MODULE_AUTHOR("Steven Toth");
+MODULE_LICENSE("GPL");
similarity index 98%
rename from drivers/media/dvb/frontends/au8522_decoder.c
rename to drivers/media/dvb-frontends/au8522_decoder.c
index 55b6390198e34d3ac7b77a71194645cbf33d1951..5243ba6295cc1aabd93796aa23e90bdb300c59ad 100644 (file)
@@ -257,9 +257,11 @@ static void setup_decoder_defaults(struct au8522_state *state, u8 input_mode)
        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_CVBS13);
+                       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_CVBS13);
+                       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,
@@ -657,11 +659,6 @@ static int au8522_s_video_routing(struct v4l2_subdev *sd,
 
        au8522_reset(sd, 0);
 
-       /* Jam open the i2c gate to the tuner.  We do this here to handle the
-          case where the user went into digital mode (causing the gate to be
-          closed), and then came back to analog mode */
-       au8522_writereg(state, 0x106, 1);
-
        if (input == AU8522_COMPOSITE_CH1) {
                au8522_setup_cvbs_mode(state);
        } else if (input == AU8522_SVIDEO_CH13) {
similarity index 95%
rename from drivers/media/dvb/frontends/au8522_dig.c
rename to drivers/media/dvb-frontends/au8522_dig.c
index 5fc70d6cd04fad4e813d94c736d599d1cf22b3d3..a68974f6d7081f2bc877b43e3c9481d49de45dc9 100644 (file)
@@ -157,54 +157,54 @@ static struct mse2snr_tab qam64_mse2snr_tab[] = {
 
 /* QAM256 SNR lookup table */
 static struct mse2snr_tab qam256_mse2snr_tab[] = {
-       {  16,   0 },
-       {  17, 400 },
-       {  18, 398 },
-       {  19, 396 },
-       {  20, 394 },
-       {  21, 392 },
-       {  22, 390 },
-       {  23, 388 },
-       {  24, 386 },
-       {  25, 384 },
-       {  26, 382 },
-       {  27, 380 },
-       {  28, 379 },
-       {  29, 378 },
-       {  30, 377 },
-       {  31, 376 },
-       {  32, 375 },
-       {  33, 374 },
-       {  34, 373 },
-       {  35, 372 },
-       {  36, 371 },
-       {  37, 370 },
-       {  38, 362 },
-       {  39, 354 },
-       {  40, 346 },
-       {  41, 338 },
-       {  42, 330 },
-       {  43, 328 },
-       {  44, 326 },
-       {  45, 324 },
-       {  46, 322 },
-       {  47, 320 },
-       {  48, 319 },
-       {  49, 318 },
-       {  50, 317 },
-       {  51, 316 },
-       {  52, 315 },
-       {  53, 314 },
-       {  54, 313 },
-       {  55, 312 },
-       {  56, 311 },
-       {  57, 310 },
-       {  58, 308 },
-       {  59, 306 },
-       {  60, 304 },
-       {  61, 302 },
-       {  62, 300 },
-       {  63, 298 },
+       {  15,   0 },
+       {  16, 400 },
+       {  17, 398 },
+       {  18, 396 },
+       {  19, 394 },
+       {  20, 392 },
+       {  21, 390 },
+       {  22, 388 },
+       {  23, 386 },
+       {  24, 384 },
+       {  25, 382 },
+       {  26, 380 },
+       {  27, 379 },
+       {  28, 378 },
+       {  29, 377 },
+       {  30, 376 },
+       {  31, 375 },
+       {  32, 374 },
+       {  33, 373 },
+       {  34, 372 },
+       {  35, 371 },
+       {  36, 370 },
+       {  37, 362 },
+       {  38, 354 },
+       {  39, 346 },
+       {  40, 338 },
+       {  41, 330 },
+       {  42, 328 },
+       {  43, 326 },
+       {  44, 324 },
+       {  45, 322 },
+       {  46, 320 },
+       {  47, 319 },
+       {  48, 318 },
+       {  49, 317 },
+       {  50, 316 },
+       {  51, 315 },
+       {  52, 314 },
+       {  53, 313 },
+       {  54, 312 },
+       {  55, 311 },
+       {  56, 310 },
+       {  57, 308 },
+       {  58, 306 },
+       {  59, 304 },
+       {  60, 302 },
+       {  61, 300 },
+       {  62, 298 },
        {  65, 295 },
        {  68, 294 },
        {  70, 293 },
@@ -777,6 +777,8 @@ struct dvb_frontend *au8522_attach(const struct au8522_config *config,
               sizeof(struct dvb_frontend_ops));
        state->frontend.demodulator_priv = state;
 
+       state->frontend.ops.analog_ops.i2c_gate_ctrl = au8522_analog_i2c_gate_ctrl;
+
        if (au8522_init(&state->frontend) != 0) {
                printk(KERN_ERR "%s: Failed to initialize correctly\n",
                        __func__);
similarity index 93%
rename from drivers/media/dvb/frontends/au8522_priv.h
rename to drivers/media/dvb-frontends/au8522_priv.h
index 6e4a438732b569717a8f9e89bf78e6a532ab8c36..0529699a27bd64188f8c625d245db12278eb95e3 100644 (file)
@@ -82,6 +82,7 @@ int au8522_get_state(struct au8522_state **state, struct i2c_adapter *i2c,
                     u8 client_address);
 void au8522_release_state(struct au8522_state *state);
 int au8522_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
+int au8522_analog_i2c_gate_ctrl(struct dvb_frontend *fe, int enable);
 int au8522_led_ctrl(struct au8522_state *state, int led);
 
 /* REGISTERS */
@@ -325,6 +326,31 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
 
 /**************************************************************/
 
+/* Format control 1 */
+
+/* VCR Mode 7-6 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_YES         0x80
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_NO          0x40
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_VCR_MODE_AUTO                0x00
+/* Field len 5-4 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_625                0x20
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_525                0x10
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_FIELD_LEN_AUTO       0x00
+/* Line len (us) 3-2 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_64_000      0x0b
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_492      0x08
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_LINE_LEN_63_556      0x04
+/* Subcarrier freq 1-0 */
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_AUTO 0x03
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_443  0x02
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_MN   0x01
+#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_SUBCARRIER_NTSC_50   0x00
+
+/* Format control 2 */
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_AUTODETECT       0x00
+#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_STD_NTSC             0x01
+
+
 #define AU8522_INPUT_CONTROL_REG081H_ATSC                      0xC4
 #define AU8522_INPUT_CONTROL_REG081H_ATVRF                     0xC4
 #define AU8522_INPUT_CONTROL_REG081H_ATVRF13                   0xC4
@@ -385,9 +411,6 @@ int au8522_led_ctrl(struct au8522_state *state, int led);
 #define AU8522_TVDEC_COMB_MODE_REG015H_CVBS                    0x00
 #define AU8522_REG016H_CVBS                                    0x00
 #define AU8522_TVDED_DBG_MODE_REG060H_CVBS                     0x00
-#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS                 0x0B
-#define AU8522_TVDEC_FORMAT_CTRL1_REG061H_CVBS13               0x03
-#define AU8522_TVDEC_FORMAT_CTRL2_REG062H_CVBS13               0x00
 #define AU8522_TVDEC_VCR_DET_LLIM_REG063H_CVBS                 0x19
 #define AU8522_REG0F9H_AUDIO                                   0x20
 #define AU8522_TVDEC_VCR_DET_HLIM_REG064H_CVBS                 0xA7
similarity index 92%
rename from drivers/media/dvb/frontends/cxd2820r.h
rename to drivers/media/dvb-frontends/cxd2820r.h
index 5aa306ebb7ef93bd8f356e6bc98325735c88503c..6acc21c581c5fae20267bf771a48d453b140edd2 100644 (file)
@@ -62,14 +62,6 @@ struct cxd2820r_config {
         * Values: 0, 1
         */
        bool spec_inv;
-
-       /* GPIOs for all used modes.
-        * Default: none, disabled
-        * Values: <see above>
-        */
-       u8 gpio_dvbt[3];
-       u8 gpio_dvbt2[3];
-       u8 gpio_dvbc[3];
 };
 
 
@@ -77,12 +69,14 @@ struct cxd2820r_config {
        (defined(CONFIG_DVB_CXD2820R_MODULE) && defined(MODULE))
 extern struct dvb_frontend *cxd2820r_attach(
        const struct cxd2820r_config *config,
-       struct i2c_adapter *i2c
+       struct i2c_adapter *i2c,
+       int *gpio_chip_base
 );
 #else
 static inline struct dvb_frontend *cxd2820r_attach(
        const struct cxd2820r_config *config,
-       struct i2c_adapter *i2c
+       struct i2c_adapter *i2c,
+       int *gpio_chip_base
 )
 {
        printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
similarity index 89%
rename from drivers/media/dvb/frontends/cxd2820r_c.c
rename to drivers/media/dvb-frontends/cxd2820r_c.c
index ed3b0ba624dec672aaf350790731aa597027346b..125a44041011ca0ed17f99999a2bffaa5c1999a1 100644 (file)
@@ -47,12 +47,8 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
                { 0x10070, priv->cfg.ts_mode, 0xff },
        };
 
-       dbg("%s: RF=%d SR=%d", __func__, c->frequency, c->symbol_rate);
-
-       /* update GPIOs */
-       ret = cxd2820r_gpio(fe);
-       if (ret)
-               goto error;
+       dev_dbg(&priv->i2c->dev, "%s: frequency=%d symbol_rate=%d\n", __func__,
+                       c->frequency, c->symbol_rate);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
@@ -78,7 +74,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
        } else
                if_freq = 0;
 
-       dbg("%s: if_freq=%d", __func__, if_freq);
+       dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x4000;
@@ -100,7 +96,7 @@ int cxd2820r_set_frontend_c(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -150,7 +146,7 @@ int cxd2820r_get_frontend_c(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -184,7 +180,7 @@ int cxd2820r_read_ber_c(struct dvb_frontend *fe, u32 *ber)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -214,7 +210,7 @@ int cxd2820r_read_signal_strength_c(struct dvb_frontend *fe,
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -251,7 +247,7 @@ int cxd2820r_read_snr_c(struct dvb_frontend *fe, u16 *snr)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -283,11 +279,12 @@ int cxd2820r_read_status_c(struct dvb_frontend *fe, fe_status_t *status)
                }
        }
 
-       dbg("%s: lock=%02x %02x", __func__, buf[0], buf[1]);
+       dev_dbg(&priv->i2c->dev, "%s: lock=%02x %02x\n", __func__, buf[0],
+                       buf[1]);
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -302,7 +299,7 @@ int cxd2820r_init_c(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -318,7 +315,7 @@ int cxd2820r_sleep_c(struct dvb_frontend *fe)
                { 0x00080, 0x00, 0xff },
        };
 
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s\n", __func__);
 
        priv->delivery_system = SYS_UNDEFINED;
 
@@ -331,7 +328,7 @@ int cxd2820r_sleep_c(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
similarity index 70%
rename from drivers/media/dvb/frontends/cxd2820r_core.c
rename to drivers/media/dvb-frontends/cxd2820r_core.c
index 3bba37d74f5729d2684af249cb1d5c59e998ac33..42648643693e0ab1fe06bb6975a0d40f8db54968 100644 (file)
 
 #include "cxd2820r_priv.h"
 
-int cxd2820r_debug;
-module_param_named(debug, cxd2820r_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
 /* write multiple registers */
 static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
        u8 *val, int len)
@@ -47,7 +43,8 @@ static int cxd2820r_wr_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -78,7 +75,8 @@ static int cxd2820r_rd_regs_i2c(struct cxd2820r_priv *priv, u8 i2c, u8 reg,
                memcpy(val, buf, len);
                ret = 0;
        } else {
-               warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -170,27 +168,14 @@ int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
        return cxd2820r_wr_reg(priv, reg, val);
 }
 
-int cxd2820r_gpio(struct dvb_frontend *fe)
+int cxd2820r_gpio(struct dvb_frontend *fe, u8 *gpio)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret, i;
-       u8 *gpio, tmp0, tmp1;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       u8 tmp0, tmp1;
 
-       switch (fe->dtv_property_cache.delivery_system) {
-       case SYS_DVBT:
-               gpio = priv->cfg.gpio_dvbt;
-               break;
-       case SYS_DVBT2:
-               gpio = priv->cfg.gpio_dvbt2;
-               break;
-       case SYS_DVBC_ANNEX_AC:
-               gpio = priv->cfg.gpio_dvbc;
-               break;
-       default:
-               ret = -EINVAL;
-               goto error;
-       }
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
 
        /* update GPIOs only when needed */
        if (!memcmp(gpio, priv->gpio, sizeof(priv->gpio)))
@@ -217,10 +202,12 @@ int cxd2820r_gpio(struct dvb_frontend *fe)
                else
                        tmp1 |= (0 << (0 + i));
 
-               dbg("%s: GPIO i=%d %02x %02x", __func__, i, tmp0, tmp1);
+               dev_dbg(&priv->i2c->dev, "%s: gpio i=%d %02x %02x\n", __func__,
+                               i, tmp0, tmp1);
        }
 
-       dbg("%s: wr gpio=%02x %02x", __func__, tmp0, tmp1);
+       dev_dbg(&priv->i2c->dev, "%s: wr gpio=%02x %02x\n", __func__, tmp0,
+                       tmp1);
 
        /* write bits [7:2] */
        ret = cxd2820r_wr_reg_mask(priv, 0x00089, tmp0, 0xfc);
@@ -236,7 +223,7 @@ int cxd2820r_gpio(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -248,10 +235,13 @@ u32 cxd2820r_div_u64_round_closest(u64 dividend, u32 divisor)
 
 static int cxd2820r_set_frontend(struct dvb_frontend *fe)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (c->delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_init_t(fe);
@@ -278,7 +268,8 @@ static int cxd2820r_set_frontend(struct dvb_frontend *fe)
                        goto err;
                break;
        default:
-               dbg("%s: error state=%d", __func__, fe->dtv_property_cache.delivery_system);
+               dev_dbg(&priv->i2c->dev, "%s: error state=%d\n", __func__,
+                               fe->dtv_property_cache.delivery_system);
                ret = -EINVAL;
                break;
        }
@@ -287,9 +278,12 @@ err:
 }
 static int cxd2820r_read_status(struct dvb_frontend *fe, fe_status_t *status)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_read_status_t(fe, status);
@@ -312,7 +306,8 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe)
        struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
 
        if (priv->delivery_system == SYS_UNDEFINED)
                return 0;
@@ -336,9 +331,12 @@ static int cxd2820r_get_frontend(struct dvb_frontend *fe)
 
 static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_read_ber_t(fe, ber);
@@ -358,9 +356,12 @@ static int cxd2820r_read_ber(struct dvb_frontend *fe, u32 *ber)
 
 static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_read_signal_strength_t(fe, strength);
@@ -380,9 +381,12 @@ static int cxd2820r_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 
 static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_read_snr_t(fe, snr);
@@ -402,9 +406,12 @@ static int cxd2820r_read_snr(struct dvb_frontend *fe, u16 *snr)
 
 static int cxd2820r_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_read_ucblocks_t(fe, ucblocks);
@@ -429,9 +436,12 @@ static int cxd2820r_init(struct dvb_frontend *fe)
 
 static int cxd2820r_sleep(struct dvb_frontend *fe)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_sleep_t(fe);
@@ -452,9 +462,12 @@ static int cxd2820r_sleep(struct dvb_frontend *fe)
 static int cxd2820r_get_tune_settings(struct dvb_frontend *fe,
                                      struct dvb_frontend_tune_settings *s)
 {
+       struct cxd2820r_priv *priv = fe->demodulator_priv;
        int ret;
 
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
+
        switch (fe->dtv_property_cache.delivery_system) {
        case SYS_DVBT:
                ret = cxd2820r_get_tune_settings_t(fe, s);
@@ -478,7 +491,9 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret, i;
        fe_status_t status = 0;
-       dbg("%s: delsys=%d", __func__, fe->dtv_property_cache.delivery_system);
+
+       dev_dbg(&priv->i2c->dev, "%s: delsys=%d\n", __func__,
+                       fe->dtv_property_cache.delivery_system);
 
        /* switch between DVB-T and DVB-T2 when tune fails */
        if (priv->last_tune_failed) {
@@ -520,7 +535,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
 
        /* wait frontend lock */
        for (; i > 0; i--) {
-               dbg("%s: LOOP=%d", __func__, i);
+               dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
                msleep(50);
                ret = cxd2820r_read_status(fe, &status);
                if (ret)
@@ -540,7 +555,7 @@ static enum dvbfe_search cxd2820r_search(struct dvb_frontend *fe)
        }
 
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return DVBFE_ALGO_SEARCH_ERROR;
 }
 
@@ -552,8 +567,19 @@ static int cxd2820r_get_frontend_algo(struct dvb_frontend *fe)
 static void cxd2820r_release(struct dvb_frontend *fe)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
-       dbg("%s", __func__);
+       int uninitialized_var(ret); /* silence compiler warning */
 
+       dev_dbg(&priv->i2c->dev, "%s\n", __func__);
+
+#ifdef CONFIG_GPIOLIB
+       /* remove GPIOs */
+       if (priv->gpio_chip.label) {
+               ret = gpiochip_remove(&priv->gpio_chip);
+               if (ret)
+                       dev_err(&priv->i2c->dev, "%s: gpiochip_remove() " \
+                                       "failed=%d\n", KBUILD_MODNAME, ret);
+       }
+#endif
        kfree(priv);
        return;
 }
@@ -561,12 +587,56 @@ static void cxd2820r_release(struct dvb_frontend *fe)
 static int cxd2820r_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        struct cxd2820r_priv *priv = fe->demodulator_priv;
-       dbg("%s: %d", __func__, enable);
+
+       dev_dbg(&priv->i2c->dev, "%s: %d\n", __func__, enable);
 
        /* Bit 0 of reg 0xdb in bank 0x00 controls I2C repeater */
        return cxd2820r_wr_reg_mask(priv, 0xdb, enable ? 1 : 0, 0x1);
 }
 
+#ifdef CONFIG_GPIOLIB
+static int cxd2820r_gpio_direction_output(struct gpio_chip *chip, unsigned nr,
+               int val)
+{
+       struct cxd2820r_priv *priv =
+                       container_of(chip, struct cxd2820r_priv, gpio_chip);
+       u8 gpio[GPIO_COUNT];
+
+       dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val);
+
+       memcpy(gpio, priv->gpio, sizeof(gpio));
+       gpio[nr] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | (val << 2);
+
+       return cxd2820r_gpio(&priv->fe, gpio);
+}
+
+static void cxd2820r_gpio_set(struct gpio_chip *chip, unsigned nr, int val)
+{
+       struct cxd2820r_priv *priv =
+                       container_of(chip, struct cxd2820r_priv, gpio_chip);
+       u8 gpio[GPIO_COUNT];
+
+       dev_dbg(&priv->i2c->dev, "%s: nr=%d val=%d\n", __func__, nr, val);
+
+       memcpy(gpio, priv->gpio, sizeof(gpio));
+       gpio[nr] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | (val << 2);
+
+       (void) cxd2820r_gpio(&priv->fe, gpio);
+
+       return;
+}
+
+static int cxd2820r_gpio_get(struct gpio_chip *chip, unsigned nr)
+{
+       struct cxd2820r_priv *priv =
+                       container_of(chip, struct cxd2820r_priv, gpio_chip);
+
+       dev_dbg(&priv->i2c->dev, "%s: nr=%d\n", __func__, nr);
+
+       return (priv->gpio[nr] >> 2) & 0x01;
+}
+#endif
+
 static const struct dvb_frontend_ops cxd2820r_ops = {
        .delsys = { SYS_DVBT, SYS_DVBT2, SYS_DVBC_ANNEX_A },
        /* default: DVB-T/T2 */
@@ -613,29 +683,70 @@ static const struct dvb_frontend_ops cxd2820r_ops = {
 };
 
 struct dvb_frontend *cxd2820r_attach(const struct cxd2820r_config *cfg,
-               struct i2c_adapter *i2c)
+               struct i2c_adapter *i2c, int *gpio_chip_base
+)
 {
-       struct cxd2820r_priv *priv = NULL;
+       struct cxd2820r_priv *priv;
        int ret;
-       u8 tmp;
+       u8 tmp, gpio[GPIO_COUNT];
 
-       priv = kzalloc(sizeof (struct cxd2820r_priv), GFP_KERNEL);
-       if (!priv)
+       priv = kzalloc(sizeof(struct cxd2820r_priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               dev_err(&i2c->dev, "%s: kzalloc() failed\n",
+                               KBUILD_MODNAME);
                goto error;
+       }
 
        priv->i2c = i2c;
-       memcpy(&priv->cfg, cfg, sizeof (struct cxd2820r_config));
+       memcpy(&priv->cfg, cfg, sizeof(struct cxd2820r_config));
+       memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof(struct dvb_frontend_ops));
+       priv->fe.demodulator_priv = priv;
 
        priv->bank[0] = priv->bank[1] = 0xff;
        ret = cxd2820r_rd_reg(priv, 0x000fd, &tmp);
-       dbg("%s: chip id=%02x", __func__, tmp);
+       dev_dbg(&priv->i2c->dev, "%s: chip id=%02x\n", __func__, tmp);
        if (ret || tmp != 0xe1)
                goto error;
 
-       memcpy(&priv->fe.ops, &cxd2820r_ops, sizeof (struct dvb_frontend_ops));
-       priv->fe.demodulator_priv = priv;
+       if (gpio_chip_base) {
+#ifdef CONFIG_GPIOLIB
+               /* add GPIOs */
+               priv->gpio_chip.label = KBUILD_MODNAME;
+               priv->gpio_chip.dev = &priv->i2c->dev;
+               priv->gpio_chip.owner = THIS_MODULE;
+               priv->gpio_chip.direction_output =
+                               cxd2820r_gpio_direction_output;
+               priv->gpio_chip.set = cxd2820r_gpio_set;
+               priv->gpio_chip.get = cxd2820r_gpio_get;
+               priv->gpio_chip.base = -1; /* dynamic allocation */
+               priv->gpio_chip.ngpio = GPIO_COUNT;
+               priv->gpio_chip.can_sleep = 1;
+               ret = gpiochip_add(&priv->gpio_chip);
+               if (ret)
+                       goto error;
+
+               dev_dbg(&priv->i2c->dev, "%s: gpio_chip.base=%d\n", __func__,
+                               priv->gpio_chip.base);
+
+               *gpio_chip_base = priv->gpio_chip.base;
+#else
+               /*
+                * Use static GPIO configuration if GPIOLIB is undefined.
+                * This is fallback condition.
+                */
+               gpio[0] = (*gpio_chip_base >> 0) & 0x07;
+               gpio[1] = (*gpio_chip_base >> 3) & 0x07;
+               gpio[2] = 0;
+               ret = cxd2820r_gpio(&priv->fe, gpio);
+               if (ret)
+                       goto error;
+#endif
+       }
+
        return &priv->fe;
 error:
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
        kfree(priv);
        return NULL;
 }
similarity index 89%
rename from drivers/media/dvb/frontends/cxd2820r_priv.h
rename to drivers/media/dvb-frontends/cxd2820r_priv.h
index 9a9822cad9cd59de41dce73474c51f44fa0e802c..7ff5f60c83e1f29d7600c1bd3169c813a6045d8e 100644 (file)
 #include "dvb_frontend.h"
 #include "dvb_math.h"
 #include "cxd2820r.h"
-
-#define LOG_PREFIX "cxd2820r"
-
-#undef dbg
-#define dbg(f, arg...) \
-       if (cxd2820r_debug) \
-               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+#include <linux/gpio.h>
 
 struct reg_val_mask {
        u32 reg;
@@ -54,7 +42,11 @@ struct cxd2820r_priv {
        bool ber_running;
 
        u8 bank[2];
-       u8 gpio[3];
+#define GPIO_COUNT 3
+       u8 gpio[GPIO_COUNT];
+#ifdef CONFIG_GPIOLIB
+       struct gpio_chip gpio_chip;
+#endif
 
        fe_delivery_system_t delivery_system;
        bool last_tune_failed; /* for switch between T and T2 tune */
@@ -64,7 +56,7 @@ struct cxd2820r_priv {
 
 extern int cxd2820r_debug;
 
-int cxd2820r_gpio(struct dvb_frontend *fe);
+int cxd2820r_gpio(struct dvb_frontend *fe, u8 *gpio);
 
 int cxd2820r_wr_reg_mask(struct cxd2820r_priv *priv, u32 reg, u8 val,
        u8 mask);
similarity index 91%
rename from drivers/media/dvb/frontends/cxd2820r_t.c
rename to drivers/media/dvb-frontends/cxd2820r_t.c
index 1a026239cdcc081afeb2b3f6d3e172d73a4c224c..fa184ca2dd687de442b38db531ab108038b77b27 100644 (file)
@@ -54,7 +54,8 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
                { 0x00427, 0x41, 0xff },
        };
 
-       dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+       dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", __func__,
+                       c->frequency, c->bandwidth_hz);
 
        switch (c->bandwidth_hz) {
        case 6000000:
@@ -73,11 +74,6 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
                return -EINVAL;
        }
 
-       /* update GPIOs */
-       ret = cxd2820r_gpio(fe);
-       if (ret)
-               goto error;
-
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
                fe->ops.tuner_ops.set_params(fe);
@@ -102,7 +98,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
        } else
                if_freq = 0;
 
-       dbg("%s: if_freq=%d", __func__, if_freq);
+       dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
@@ -137,7 +133,7 @@ int cxd2820r_set_frontend_t(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -254,7 +250,7 @@ int cxd2820r_get_frontend_t(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -288,7 +284,7 @@ int cxd2820r_read_ber_t(struct dvb_frontend *fe, u32 *ber)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -312,7 +308,7 @@ int cxd2820r_read_signal_strength_t(struct dvb_frontend *fe,
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -336,11 +332,12 @@ int cxd2820r_read_snr_t(struct dvb_frontend *fe, u16 *snr)
        else
                *snr = 0;
 
-       dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+       dev_dbg(&priv->i2c->dev, "%s: dBx10=%d val=%04x\n", __func__, *snr,
+                       tmp);
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -389,12 +386,11 @@ int cxd2820r_read_status_t(struct dvb_frontend *fe, fe_status_t *status)
                }
        }
 
-       dbg("%s: lock=%02x %02x %02x %02x", __func__,
-               buf[0], buf[1], buf[2], buf[3]);
+       dev_dbg(&priv->i2c->dev, "%s: lock=%*ph\n", __func__, 4, buf);
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -409,7 +405,7 @@ int cxd2820r_init_t(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -425,7 +421,7 @@ int cxd2820r_sleep_t(struct dvb_frontend *fe)
                { 0x00080, 0x00, 0xff },
        };
 
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s\n", __func__);
 
        priv->delivery_system = SYS_UNDEFINED;
 
@@ -438,7 +434,7 @@ int cxd2820r_sleep_t(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
similarity index 91%
rename from drivers/media/dvb/frontends/cxd2820r_t2.c
rename to drivers/media/dvb-frontends/cxd2820r_t2.c
index 3a5759e0d2352c3d6753acd400bd9d32442e6cdf..e82d82a7a2ebb6e3c8c40e1d6fc4886f0e8fbde9 100644 (file)
@@ -68,7 +68,8 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
                { 0x027ef, 0x10, 0x18 },
        };
 
-       dbg("%s: RF=%d BW=%d", __func__, c->frequency, c->bandwidth_hz);
+       dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n", __func__,
+                       c->frequency, c->bandwidth_hz);
 
        switch (c->bandwidth_hz) {
        case 5000000:
@@ -91,11 +92,6 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
                return -EINVAL;
        }
 
-       /* update GPIOs */
-       ret = cxd2820r_gpio(fe);
-       if (ret)
-               goto error;
-
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
                fe->ops.tuner_ops.set_params(fe);
@@ -119,7 +115,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
        } else
                if_freq = 0;
 
-       dbg("%s: if_freq=%d", __func__, if_freq);
+       dev_dbg(&priv->i2c->dev, "%s: if_freq=%d\n", __func__, if_freq);
 
        num = if_freq / 1000; /* Hz => kHz */
        num *= 0x1000000;
@@ -150,7 +146,7 @@ int cxd2820r_set_frontend_t2(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 
 }
@@ -266,7 +262,7 @@ int cxd2820r_get_frontend_t2(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -291,11 +287,11 @@ int cxd2820r_read_status_t2(struct dvb_frontend *fe, fe_status_t *status)
                }
        }
 
-       dbg("%s: lock=%02x", __func__, buf[0]);
+       dev_dbg(&priv->i2c->dev, "%s: lock=%02x\n", __func__, buf[0]);
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -322,7 +318,7 @@ int cxd2820r_read_ber_t2(struct dvb_frontend *fe, u32 *ber)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -346,7 +342,7 @@ int cxd2820r_read_signal_strength_t2(struct dvb_frontend *fe,
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -370,11 +366,12 @@ int cxd2820r_read_snr_t2(struct dvb_frontend *fe, u16 *snr)
        else
                *snr = 0;
 
-       dbg("%s: dBx10=%d val=%04x", __func__, *snr, tmp);
+       dev_dbg(&priv->i2c->dev, "%s: dBx10=%d val=%04x\n", __func__, *snr,
+                       tmp);
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -398,7 +395,7 @@ int cxd2820r_sleep_t2(struct dvb_frontend *fe)
                { 0x00080, 0x00, 0xff },
        };
 
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s\n", __func__);
 
        for (i = 0; i < ARRAY_SIZE(tab); i++) {
                ret = cxd2820r_wr_reg_mask(priv, tab[i].reg, tab[i].val,
@@ -411,7 +408,7 @@ int cxd2820r_sleep_t2(struct dvb_frontend *fe)
 
        return ret;
 error:
-       dbg("%s: failed:%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
similarity index 95%
rename from drivers/media/dvb/frontends/drxk.h
rename to drivers/media/dvb-frontends/drxk.h
index d615d7d055a29dfba39b3fd6e9879830cd96a080..94fecfbf14c1278d70669e18d1b5c4a7d6ebdaf7 100644 (file)
@@ -28,6 +28,7 @@
  *                             A value of 0 (default) or lower indicates that
  *                             the correct number of parameters will be
  *                             automatically detected.
+ * @load_firmware_sync:                Force the firmware load to be synchronous.
  *
  * On the *_gpio vars, bit 0 is UIO-1, bit 1 is UIO-2 and bit 2 is
  * UIO-3.
@@ -39,6 +40,7 @@ struct drxk_config {
        bool    parallel_ts;
        bool    dynamic_clk;
        bool    enable_merr_cfg;
+       bool    load_firmware_sync;
 
        bool    antenna_dvbt;
        u16     antenna_gpio;
similarity index 99%
rename from drivers/media/dvb/frontends/drxk_hard.c
rename to drivers/media/dvb-frontends/drxk_hard.c
index 1ab8154542daebc056912efbdb7866bedae7304d..8b4c6d5f8f3694d330dfd50d36ae9ef870af4339 100644 (file)
@@ -6609,15 +6609,25 @@ struct dvb_frontend *drxk_attach(const struct drxk_config *config,
 
        /* Load firmware and initialize DRX-K */
        if (state->microcode_name) {
-               status = request_firmware_nowait(THIS_MODULE, 1,
+               if (config->load_firmware_sync) {
+                       const struct firmware *fw = NULL;
+
+                       status = request_firmware(&fw, state->microcode_name,
+                                                 state->i2c->dev.parent);
+                       if (status < 0)
+                               fw = NULL;
+                       load_firmware_cb(fw, state);
+               } else {
+                       status = request_firmware_nowait(THIS_MODULE, 1,
                                              state->microcode_name,
                                              state->i2c->dev.parent,
                                              GFP_KERNEL,
                                              state, load_firmware_cb);
-               if (status < 0) {
-                       printk(KERN_ERR
-                       "drxk: failed to request a firmware\n");
-                       return NULL;
+                       if (status < 0) {
+                               printk(KERN_ERR
+                                      "drxk: failed to request a firmware\n");
+                               return NULL;
+                       }
                }
        } else if (init_drxk(state) < 0)
                goto error;
similarity index 96%
rename from drivers/media/dvb/frontends/dvb-pll.c
rename to drivers/media/dvb-frontends/dvb-pll.c
index 1ab34838221c0b14d09bdfec5bb67bbce382bd1c..6d8fe884323714f89392ecf221e81f3c6b8b0214 100644 (file)
@@ -116,6 +116,31 @@ static struct dvb_pll_desc dvb_pll_thomson_dtt759x = {
        },
 };
 
+static void thomson_dtt7520x_bw(struct dvb_frontend *fe, u8 *buf)
+{
+       u32 bw = fe->dtv_property_cache.bandwidth_hz;
+       if (bw == 8000000)
+               buf[3] ^= 0x10;
+}
+
+static struct dvb_pll_desc dvb_pll_thomson_dtt7520x = {
+       .name  = "Thomson dtt7520x",
+       .min   = 185000000,
+       .max   = 900000000,
+       .set   = thomson_dtt7520x_bw,
+       .iffreq = 36166667,
+       .count = 7,
+       .entries = {
+               {  305000000, 166667, 0xb4, 0x12 },
+               {  405000000, 166667, 0xbc, 0x12 },
+               {  445000000, 166667, 0xbc, 0x12 },
+               {  465000000, 166667, 0xf4, 0x18 },
+               {  735000000, 166667, 0xfc, 0x18 },
+               {  835000000, 166667, 0xbc, 0x18 },
+               {  999999999, 166667, 0xfc, 0x18 },
+       },
+};
+
 static struct dvb_pll_desc dvb_pll_lg_z201 = {
        .name  = "LG z201",
        .min   = 174000000,
@@ -513,6 +538,7 @@ static struct dvb_pll_desc *pll_list[] = {
        [DVB_PLL_UNDEFINED]              = NULL,
        [DVB_PLL_THOMSON_DTT7579]        = &dvb_pll_thomson_dtt7579,
        [DVB_PLL_THOMSON_DTT759X]        = &dvb_pll_thomson_dtt759x,
+       [DVB_PLL_THOMSON_DTT7520X]       = &dvb_pll_thomson_dtt7520x,
        [DVB_PLL_LG_Z201]                = &dvb_pll_lg_z201,
        [DVB_PLL_UNKNOWN_1]              = &dvb_pll_unknown_1,
        [DVB_PLL_TUA6010XS]              = &dvb_pll_tua6010xs,
similarity index 97%
rename from drivers/media/dvb/frontends/dvb-pll.h
rename to drivers/media/dvb-frontends/dvb-pll.h
index 086964344c38bd180d0fe6f798d918f48d7edada..4de754f76ce95d8b7183f76117579c7e0d128b54 100644 (file)
@@ -27,6 +27,7 @@
 #define DVB_PLL_SAMSUNG_TBDU18132      16
 #define DVB_PLL_SAMSUNG_TBMU24112      17
 #define DVB_PLL_TDEE4                 18
+#define DVB_PLL_THOMSON_DTT7520X       19
 
 /**
  * Attach a dvb-pll to the supplied frontend structure.
similarity index 87%
rename from drivers/media/dvb/frontends/ec100.c
rename to drivers/media/dvb-frontends/ec100.c
index c56fddbf53b77b56b5cb9ea4c1ca34e59e6e96d0..9d424809d06b7dcb7f680491ce700078073ba30e 100644 (file)
  */
 
 #include "dvb_frontend.h"
-#include "ec100_priv.h"
 #include "ec100.h"
 
-int ec100_debug;
-module_param_named(debug, ec100_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
 struct ec100_state {
        struct i2c_adapter *i2c;
        struct dvb_frontend frontend;
@@ -38,23 +33,33 @@ struct ec100_state {
 /* write single register */
 static int ec100_write_reg(struct ec100_state *state, u8 reg, u8 val)
 {
+       int ret;
        u8 buf[2] = {reg, val};
-       struct i2c_msg msg = {
-               .addr = state->config.demod_address,
-               .flags = 0,
-               .len = 2,
-               .buf = buf};
-
-       if (i2c_transfer(state->i2c, &msg, 1) != 1) {
-               warn("I2C write failed reg:%02x", reg);
-               return -EREMOTEIO;
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = state->config.demod_address,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       ret = i2c_transfer(state->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               dev_warn(&state->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
+                               KBUILD_MODNAME, ret, reg);
+               ret = -EREMOTEIO;
        }
-       return 0;
+
+       return ret;
 }
 
 /* read single register */
 static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
 {
+       int ret;
        struct i2c_msg msg[2] = {
                {
                        .addr = state->config.demod_address,
@@ -69,11 +74,16 @@ static int ec100_read_reg(struct ec100_state *state, u8 reg, u8 *val)
                }
        };
 
-       if (i2c_transfer(state->i2c, msg, 2) != 2) {
-               warn("I2C read failed reg:%02x", reg);
-               return -EREMOTEIO;
+       ret = i2c_transfer(state->i2c, msg, 2);
+       if (ret == 2) {
+               ret = 0;
+       } else {
+               dev_warn(&state->i2c->dev, "%s: i2c rd failed=%d reg=%02x\n",
+                               KBUILD_MODNAME, ret, reg);
+               ret = -EREMOTEIO;
        }
-       return 0;
+
+       return ret;
 }
 
 static int ec100_set_frontend(struct dvb_frontend *fe)
@@ -83,8 +93,8 @@ static int ec100_set_frontend(struct dvb_frontend *fe)
        int ret;
        u8 tmp, tmp2;
 
-       deb_info("%s: freq:%d bw:%d\n", __func__, c->frequency,
-               c->bandwidth_hz);
+       dev_dbg(&state->i2c->dev, "%s: frequency=%d bandwidth_hz=%d\n",
+                       __func__, c->frequency, c->bandwidth_hz);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
@@ -150,7 +160,7 @@ static int ec100_set_frontend(struct dvb_frontend *fe)
 
        return ret;
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -196,7 +206,7 @@ static int ec100_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        return ret;
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -228,7 +238,7 @@ static int ec100_read_ber(struct dvb_frontend *fe, u32 *ber)
 
        return ret;
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -248,7 +258,7 @@ static int ec100_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 
        return ret;
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&state->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
similarity index 95%
rename from drivers/media/dvb/frontends/ec100.h
rename to drivers/media/dvb-frontends/ec100.h
index ee8e52417958e0df45069df12edfff66a882b3c1..b8479719d7f1e22d2d437ff1d790b83ec464224f 100644 (file)
@@ -38,7 +38,7 @@ extern struct dvb_frontend *ec100_attach(const struct ec100_config *config,
 static inline struct dvb_frontend *ec100_attach(
        const struct ec100_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
similarity index 89%
rename from drivers/media/dvb/frontends/hd29l2.c
rename to drivers/media/dvb-frontends/hd29l2.c
index a00318190837af051d834124f96f94832de21724..d7b9d549156d4d923e6ea9c7a988c0849725dd0c 100644 (file)
 
 #include "hd29l2_priv.h"
 
-int hd29l2_debug;
-module_param_named(debug, hd29l2_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
 /* write multiple registers */
 static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
 {
@@ -48,7 +44,9 @@ static int hd29l2_wr_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev,
+                               "%s: i2c wr failed=%d reg=%02x len=%d\n",
+                               KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -78,7 +76,9 @@ static int hd29l2_rd_regs(struct hd29l2_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 2) {
                ret = 0;
        } else {
-               warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev,
+                               "%s: i2c rd failed=%d reg=%02x len=%d\n",
+                               KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -160,7 +160,7 @@ static int hd29l2_soft_reset(struct hd29l2_priv *priv)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -170,7 +170,7 @@ static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
        struct hd29l2_priv *priv = fe->demodulator_priv;
        u8 tmp;
 
-       dbg("%s: enable=%d", __func__, enable);
+       dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
 
        /* set tuner address for demod */
        if (!priv->tuner_i2c_addr_programmed && enable) {
@@ -199,11 +199,11 @@ static int hd29l2_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
                usleep_range(5000, 10000);
        }
 
-       dbg("%s: loop=%d", __func__, i);
+       dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -238,7 +238,7 @@ static int hd29l2_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -270,7 +270,7 @@ static int hd29l2_read_snr(struct dvb_frontend *fe, u16 *snr)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -295,7 +295,7 @@ static int hd29l2_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -322,7 +322,7 @@ static int hd29l2_read_ber(struct dvb_frontend *fe, u32 *ber)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -344,11 +344,12 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
        u32 if_freq, if_ctl;
        bool auto_mode;
 
-       dbg("%s: delivery_system=%d frequency=%d bandwidth_hz=%d " \
-               "modulation=%d inversion=%d fec_inner=%d guard_interval=%d",
-                __func__,
-               c->delivery_system, c->frequency, c->bandwidth_hz,
-               c->modulation, c->inversion, c->fec_inner, c->guard_interval);
+       dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
+                       "bandwidth_hz=%d modulation=%d inversion=%d " \
+                       "fec_inner=%d guard_interval=%d\n", __func__,
+                       c->delivery_system, c->frequency, c->bandwidth_hz,
+                       c->modulation, c->inversion, c->fec_inner,
+                       c->guard_interval);
 
        /* as for now we detect always params automatically */
        auto_mode = true;
@@ -394,7 +395,8 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       dbg("%s: if_freq=%d if_ctl=%x", __func__, if_freq, if_ctl);
+       dev_dbg(&priv->i2c->dev, "%s: if_freq=%d if_ctl=%x\n",
+                       __func__, if_freq, if_ctl);
 
        if (auto_mode) {
                /*
@@ -437,7 +439,7 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
                                break;
                }
 
-               dbg("%s: loop=%d", __func__, i);
+               dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
 
                if (i == 0)
                        /* detection failed */
@@ -477,7 +479,8 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
        /* ensure modulation validy */
        /* 0=QAM4_NR, 1=QAM4, 2=QAM16, 3=QAM32, 4=QAM64 */
        if (modulation > (ARRAY_SIZE(reg_mod_vals_tab[0].val) - 1)) {
-               dbg("%s: modulation=%d not valid", __func__, modulation);
+               dev_dbg(&priv->i2c->dev, "%s: modulation=%d not valid\n",
+                               __func__, modulation);
                goto err;
        }
 
@@ -499,12 +502,14 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       dbg("%s: modulation=%d guard_interval=%d carrier=%d",
-               __func__, modulation, guard_interval, carrier);
+       dev_dbg(&priv->i2c->dev,
+                       "%s: modulation=%d guard_interval=%d carrier=%d\n",
+                       __func__, modulation, guard_interval, carrier);
 
        if ((carrier == HD29L2_CARRIER_MULTI) && (modulation == HD29L2_QAM64) &&
                (guard_interval == HD29L2_PN945)) {
-               dbg("%s: C=3780 && QAM64 && PN945", __func__);
+               dev_dbg(&priv->i2c->dev, "%s: C=3780 && QAM64 && PN945\n",
+                               __func__);
 
                ret = hd29l2_wr_reg(priv, 0x42, 0x33);
                if (ret)
@@ -535,14 +540,14 @@ static enum dvbfe_search hd29l2_search(struct dvb_frontend *fe)
                        break;
        }
 
-       dbg("%s: loop=%d", __func__, i);
+       dev_dbg(&priv->i2c->dev, "%s: loop=%d\n", __func__, i);
 
        if (i == 0)
                return DVBFE_ALGO_SEARCH_AGAIN;
 
        return DVBFE_ALGO_SEARCH_SUCCESS;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return DVBFE_ALGO_SEARCH_ERROR;
 }
 
@@ -704,14 +709,14 @@ static int hd29l2_get_frontend(struct dvb_frontend *fe)
 
        if_ctl = (buf[0] << 16) | ((buf[1] - 7) << 8) | buf[2];
 
-       dbg("%s: %s %s %s | %s %s %s | %s %s | NCO=%06x", __func__,
-               str_constellation, str_code_rate, str_constellation_code_rate,
-               str_guard_interval, str_carrier, str_guard_interval_carrier,
-               str_interleave, str_interleave_, if_ctl);
-
+       dev_dbg(&priv->i2c->dev, "%s: %s %s %s | %s %s %s | %s %s | NCO=%06x\n",
+                       __func__, str_constellation, str_code_rate,
+                       str_constellation_code_rate, str_guard_interval,
+                       str_carrier, str_guard_interval_carrier, str_interleave,
+                       str_interleave_, if_ctl);
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -730,7 +735,7 @@ static int hd29l2_init(struct dvb_frontend *fe)
                { 0x10, 0x38 },
        };
 
-       dbg("%s:", __func__);
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
 
        /* reset demod */
        /* it is recommended to HW reset chip using RST_N pin */
@@ -774,7 +779,7 @@ static int hd29l2_init(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
similarity index 96%
rename from drivers/media/dvb/frontends/hd29l2.h
rename to drivers/media/dvb-frontends/hd29l2.h
index a7a64431364d35d734a1c5c88387fa27636a00df..4ad00d79aa77350cb10d9d9e2258c2415cc0bbfe 100644 (file)
@@ -58,7 +58,7 @@ extern struct dvb_frontend *hd29l2_attach(const struct hd29l2_config *config,
 static inline struct dvb_frontend *hd29l2_attach(
 const struct hd29l2_config *config, struct i2c_adapter *i2c)
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
similarity index 96%
rename from drivers/media/dvb/frontends/hd29l2_priv.h
rename to drivers/media/dvb-frontends/hd29l2_priv.h
index ba16dc3ec2bdf04143cb1bb24608bb1a4ee9b380..4d571a2282d4177a074d45f5269e8f4bcd194581 100644 (file)
 #include "dvb_math.h"
 #include "hd29l2.h"
 
-#define LOG_PREFIX "hd29l2"
-
-#undef dbg
-#define dbg(f, arg...) \
-       if (hd29l2_debug) \
-               printk(KERN_INFO   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
 #define HD29L2_XTAL 30400000 /* Hz */
 
 
similarity index 99%
rename from drivers/media/dvb/frontends/it913x-fe.c
rename to drivers/media/dvb-frontends/it913x-fe.c
index 708cbf197913669d84eafe50e0f18fcee2f6ef4e..6e1c6eb340b7ead632f4629cee4a60999c2ccf3c 100644 (file)
@@ -199,7 +199,7 @@ static int it913x_init_tuner(struct it913x_fe_state *state)
 
        if (reg < 0)
                return -ENODEV;
-       else if (reg < sizeof(nv))
+       else if (reg < ARRAY_SIZE(nv))
                nv_val = nv[reg];
        else
                nv_val = 2;
similarity index 99%
rename from drivers/media/dvb/frontends/lgs8gl5.c
rename to drivers/media/dvb-frontends/lgs8gl5.c
index 2cec8041a1068e7f0d7f6cef5a365d68434cfbed..416cce3fefc7166777246d3ebd278eca720e9f7a 100644 (file)
@@ -412,7 +412,7 @@ EXPORT_SYMBOL(lgs8gl5_attach);
 
 
 static struct dvb_frontend_ops lgs8gl5_ops = {
-       .delsys = { SYS_DMBTH },
+       .delsys = { SYS_DTMB },
        .info = {
                .name                   = "Legend Silicon LGS-8GL5 DMB-TH",
                .frequency_min          = 474000000,
similarity index 99%
rename from drivers/media/dvb/frontends/lgs8gxx.c
rename to drivers/media/dvb-frontends/lgs8gxx.c
index c2ea2749ebedd40c0466a96ec33f90bfebcbee13..3c92f36ea5c7a287261eba1d34f5bff7c7eb0b47 100644 (file)
@@ -995,7 +995,7 @@ static int lgs8gxx_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 }
 
 static struct dvb_frontend_ops lgs8gxx_ops = {
-       .delsys = { SYS_DMBTH },
+       .delsys = { SYS_DTMB },
        .info = {
                .name = "Legend Silicon LGS8913/LGS8GXX DMB-TH",
                .frequency_min = 474000000,
similarity index 99%
rename from drivers/media/dvb/frontends/m88rs2000.c
rename to drivers/media/dvb-frontends/m88rs2000.c
index 312588e84daeedf855ccc266b8484dbc13706ee0..633815ed90ca7262641185cdd17b2224079a3316 100644 (file)
@@ -481,7 +481,7 @@ static int m88rs2000_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        if ((reg & 0x7) == 0x7) {
                *status = FE_HAS_CARRIER | FE_HAS_SIGNAL | FE_HAS_VITERBI
-                       | FE_HAS_LOCK;
+                       | FE_HAS_SYNC | FE_HAS_LOCK;
                if (state->config->set_ts_params)
                        state->config->set_ts_params(fe, CALL_IS_READ);
        }
similarity index 93%
rename from drivers/media/dvb/frontends/nxt200x.c
rename to drivers/media/dvb-frontends/nxt200x.c
index 49ca78d883b18031ec110a6329be86bf49c9acbe..8e288940a61fcb0654034dde41457de506e25a8f 100644 (file)
@@ -37,6 +37,8 @@
  * /usr/lib/hotplug/firmware/ or /lib/firmware/
  * (depending on configuration of firmware hotplug).
  */
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #define NXT2002_DEFAULT_FIRMWARE "dvb-fe-nxt2002.fw"
 #define NXT2004_DEFAULT_FIRMWARE "dvb-fe-nxt2004.fw"
 #define CRC_CCIT_MASK 0x1021
@@ -62,10 +64,7 @@ struct nxt200x_state {
 };
 
 static int debug;
-#define dprintk(args...) \
-       do { \
-               if (debug) printk(KERN_DEBUG "nxt200x: " args); \
-       } while (0)
+#define dprintk(args...)       do { if (debug) pr_debug(args); } while (0)
 
 static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len)
 {
@@ -73,7 +72,7 @@ static int i2c_writebytes (struct nxt200x_state* state, u8 addr, u8 *buf, u8 len
        struct i2c_msg msg = { .addr = addr, .flags = 0, .buf = buf, .len = len };
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+               pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
                        __func__, addr, err);
                return -EREMOTEIO;
        }
@@ -86,7 +85,7 @@ static int i2c_readbytes(struct nxt200x_state *state, u8 addr, u8 *buf, u8 len)
        struct i2c_msg msg = { .addr = addr, .flags = I2C_M_RD, .buf = buf, .len = len };
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+               pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
                        __func__, addr, err);
                return -EREMOTEIO;
        }
@@ -104,7 +103,7 @@ static int nxt200x_writebytes (struct nxt200x_state* state, u8 reg,
        memcpy(&buf2[1], buf, len);
 
        if ((err = i2c_transfer (state->i2c, &msg, 1)) != 1) {
-               printk (KERN_WARNING "nxt200x: %s: i2c write error (addr 0x%02x, err == %i)\n",
+               pr_warn("%s: i2c write error (addr 0x%02x, err == %i)\n",
                        __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
@@ -121,7 +120,7 @@ static int nxt200x_readbytes(struct nxt200x_state *state, u8 reg, u8 *buf, u8 le
        int err;
 
        if ((err = i2c_transfer (state->i2c, msg, 2)) != 2) {
-               printk (KERN_WARNING "nxt200x: %s: i2c read error (addr 0x%02x, err == %i)\n",
+               pr_warn("%s: i2c read error (addr 0x%02x, err == %i)\n",
                        __func__, state->config->demod_address, err);
                return -EREMOTEIO;
        }
@@ -199,7 +198,7 @@ static int nxt200x_writereg_multibyte (struct nxt200x_state* state, u8 reg, u8*
                        break;
        }
 
-       printk(KERN_WARNING "nxt200x: Error writing multireg register 0x%02X\n",reg);
+       pr_warn("Error writing multireg register 0x%02X\n", reg);
 
        return 0;
 }
@@ -281,7 +280,8 @@ static void nxt200x_microcontroller_stop (struct nxt200x_state* state)
                counter++;
        }
 
-       printk(KERN_WARNING "nxt200x: Timeout waiting for nxt200x to stop. This is ok after firmware upload.\n");
+       pr_warn("Timeout waiting for nxt200x to stop. This is ok after "
+               "firmware upload.\n");
        return;
 }
 
@@ -320,7 +320,7 @@ static void nxt2004_microcontroller_init (struct nxt200x_state* state)
                counter++;
        }
 
-       printk(KERN_WARNING "nxt200x: Timeout waiting for nxt2004 to init.\n");
+       pr_warn("Timeout waiting for nxt2004 to init.\n");
 
        return;
 }
@@ -331,14 +331,14 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
 
        dprintk("%s\n", __func__);
 
-       dprintk("Tuner Bytes: %02X %02X %02X %02X\n", data[1], data[2], data[3], data[4]);
+       dprintk("Tuner Bytes: %*ph\n", 4, data + 1);
 
        /* if NXT2004, write directly to tuner. if NXT2002, write through NXT chip.
         * direct write is required for Philips TUV1236D and ALPS TDHU2 */
        switch (state->demod_chip) {
                case NXT2004:
                        if (i2c_writebytes(state, data[0], data+1, 4))
-                               printk(KERN_WARNING "nxt200x: error writing to tuner\n");
+                               pr_warn("error writing to tuner\n");
                        /* wait until we have a lock */
                        while (count < 20) {
                                i2c_readbytes(state, data[0], &buf, 1);
@@ -347,7 +347,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
                                msleep(100);
                                count++;
                        }
-                       printk("nxt2004: timeout waiting for tuner lock\n");
+                       pr_warn("timeout waiting for tuner lock\n");
                        break;
                case NXT2002:
                        /* set the i2c transfer speed to the tuner */
@@ -376,7 +376,7 @@ static int nxt200x_writetuner (struct nxt200x_state* state, u8* data)
                                msleep(100);
                                count++;
                        }
-                       printk("nxt2002: timeout error writing tuner\n");
+                       pr_warn("timeout error writing to tuner\n");
                        break;
                default:
                        return -EINVAL;
@@ -878,22 +878,24 @@ static int nxt2002_init(struct dvb_frontend* fe)
        u8 buf[2];
 
        /* request the firmware, this will block until someone uploads it */
-       printk("nxt2002: Waiting for firmware upload (%s)...\n", NXT2002_DEFAULT_FIRMWARE);
+       pr_debug("%s: Waiting for firmware upload (%s)...\n",
+                __func__, NXT2002_DEFAULT_FIRMWARE);
        ret = request_firmware(&fw, NXT2002_DEFAULT_FIRMWARE,
                               state->i2c->dev.parent);
-       printk("nxt2002: Waiting for firmware upload(2)...\n");
+       pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
        if (ret) {
-               printk("nxt2002: No firmware uploaded (timeout or file not found?)\n");
+               pr_err("%s: No firmware uploaded (timeout or file not found?)"
+                      "\n", __func__);
                return ret;
        }
 
        ret = nxt2002_load_firmware(fe, fw);
        release_firmware(fw);
        if (ret) {
-               printk("nxt2002: Writing firmware to device failed\n");
+               pr_err("%s: Writing firmware to device failed\n", __func__);
                return ret;
        }
-       printk("nxt2002: Firmware upload complete\n");
+       pr_info("%s: Firmware upload complete\n", __func__);
 
        /* Put the micro into reset */
        nxt200x_microcontroller_stop(state);
@@ -943,22 +945,24 @@ static int nxt2004_init(struct dvb_frontend* fe)
        nxt200x_writebytes(state, 0x1E, buf, 1);
 
        /* request the firmware, this will block until someone uploads it */
-       printk("nxt2004: Waiting for firmware upload (%s)...\n", NXT2004_DEFAULT_FIRMWARE);
+       pr_debug("%s: Waiting for firmware upload (%s)...\n",
+                __func__, NXT2004_DEFAULT_FIRMWARE);
        ret = request_firmware(&fw, NXT2004_DEFAULT_FIRMWARE,
                               state->i2c->dev.parent);
-       printk("nxt2004: Waiting for firmware upload(2)...\n");
+       pr_debug("%s: Waiting for firmware upload(2)...\n", __func__);
        if (ret) {
-               printk("nxt2004: No firmware uploaded (timeout or file not found?)\n");
+               pr_err("%s: No firmware uploaded (timeout or file not found?)"
+                      "\n", __func__);
                return ret;
        }
 
        ret = nxt2004_load_firmware(fe, fw);
        release_firmware(fw);
        if (ret) {
-               printk("nxt2004: Writing firmware to device failed\n");
+               pr_err("%s: Writing firmware to device failed\n", __func__);
                return ret;
        }
-       printk("nxt2004: Firmware upload complete\n");
+       pr_info("%s: Firmware upload complete\n", __func__);
 
        /* ensure transfer is complete */
        buf[0] = 0x01;
@@ -1157,18 +1161,17 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
 
        /* read card id */
        nxt200x_readbytes(state, 0x00, buf, 5);
-       dprintk("NXT info: %02X %02X %02X %02X %02X\n",
-               buf[0], buf[1], buf[2], buf[3], buf[4]);
+       dprintk("NXT info: %*ph\n", 5, buf);
 
        /* set demod chip */
        switch (buf[0]) {
                case 0x04:
                        state->demod_chip = NXT2002;
-                       printk("nxt200x: NXT2002 Detected\n");
+                       pr_info("NXT2002 Detected\n");
                        break;
                case 0x05:
                        state->demod_chip = NXT2004;
-                       printk("nxt200x: NXT2004 Detected\n");
+                       pr_info("NXT2004 Detected\n");
                        break;
                default:
                        goto error;
@@ -1197,8 +1200,7 @@ struct dvb_frontend* nxt200x_attach(const struct nxt200x_config* config,
 
 error:
        kfree(state);
-       printk("Unknown/Unsupported NXT chip: %02X %02X %02X %02X %02X\n",
-               buf[0], buf[1], buf[2], buf[3], buf[4]);
+       pr_err("Unknown/Unsupported NXT chip: %*ph\n", 5, buf);
        return NULL;
 }
 
similarity index 88%
rename from drivers/media/dvb/frontends/rtl2830.c
rename to drivers/media/dvb-frontends/rtl2830.c
index 93612ebac519d86cdf8efdf257021ba986dceefd..b0f6ec03d1eb0e4b1e10444e63b482ca945d5a6c 100644 (file)
 
 #include "rtl2830_priv.h"
 
-int rtl2830_debug;
-module_param_named(debug, rtl2830_debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off frontend debugging (default:off).");
-
 /* write multiple hardware registers */
-static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
+static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, const u8 *val, int len)
 {
        int ret;
        u8 buf[1+len];
@@ -52,7 +48,8 @@ static int rtl2830_wr(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -80,14 +77,16 @@ static int rtl2830_rd(struct rtl2830_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 2) {
                ret = 0;
        } else {
-               warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
 }
 
 /* write multiple registers */
-static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
+static int rtl2830_wr_regs(struct rtl2830_priv *priv, u16 reg, const u8 *val,
+               int len)
 {
        int ret;
        u8 reg2 = (reg >> 0) & 0xff;
@@ -124,14 +123,6 @@ static int rtl2830_rd_regs(struct rtl2830_priv *priv, u16 reg, u8 *val, int len)
        return rtl2830_rd(priv, reg2, val, len);
 }
 
-#if 0 /* currently not used */
-/* write single register */
-static int rtl2830_wr_reg(struct rtl2830_priv *priv, u16 reg, u8 val)
-{
-       return rtl2830_wr_regs(priv, reg, &val, 1);
-}
-#endif
-
 /* read single register */
 static int rtl2830_rd_reg(struct rtl2830_priv *priv, u16 reg, u8 *val)
 {
@@ -184,9 +175,6 @@ static int rtl2830_init(struct dvb_frontend *fe)
 {
        struct rtl2830_priv *priv = fe->demodulator_priv;
        int ret, i;
-       u64 num;
-       u8 buf[3], tmp;
-       u32 if_ctl;
        struct rtl2830_reg_val_mask tab[] = {
                { 0x00d, 0x01, 0x03 },
                { 0x00d, 0x10, 0x10 },
@@ -242,26 +230,6 @@ static int rtl2830_init(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       num = priv->cfg.if_dvbt % priv->cfg.xtal;
-       num *= 0x400000;
-       num = div_u64(num, priv->cfg.xtal);
-       num = -num;
-       if_ctl = num & 0x3fffff;
-       dbg("%s: if_ctl=%08x", __func__, if_ctl);
-
-       ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
-       if (ret)
-               goto err;
-
-       buf[0] = tmp << 6;
-       buf[0] = (if_ctl >> 16) & 0x3f;
-       buf[1] = (if_ctl >>  8) & 0xff;
-       buf[2] = (if_ctl >>  0) & 0xff;
-
-       ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
-       if (ret)
-               goto err;
-
        /* TODO: spec init */
 
        /* soft reset */
@@ -277,7 +245,7 @@ static int rtl2830_init(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -303,7 +271,10 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
        struct rtl2830_priv *priv = fe->demodulator_priv;
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
        int ret, i;
-       static u8 bw_params1[3][34] = {
+       u64 num;
+       u8 buf[3], tmp;
+       u32 if_ctl, if_frequency;
+       static const u8 bw_params1[3][34] = {
                {
                0x1f, 0xf0, 0x1f, 0xf0, 0x1f, 0xfa, 0x00, 0x17, 0x00, 0x41,
                0x00, 0x64, 0x00, 0x67, 0x00, 0x38, 0x1f, 0xde, 0x1f, 0x7a,
@@ -321,15 +292,15 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
                0x04, 0x24, 0x04, 0xdb, /* 8 MHz */
                },
        };
-       static u8 bw_params2[3][6] = {
-               {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30,}, /* 6 MHz */
-               {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98,}, /* 7 MHz */
-               {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64,}, /* 8 MHz */
+       static const u8 bw_params2[3][6] = {
+               {0xc3, 0x0c, 0x44, 0x33, 0x33, 0x30}, /* 6 MHz */
+               {0xb8, 0xe3, 0x93, 0x99, 0x99, 0x98}, /* 7 MHz */
+               {0xae, 0xba, 0xf3, 0x26, 0x66, 0x64}, /* 8 MHz */
        };
 
-
-       dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
-               c->frequency, c->bandwidth_hz, c->inversion);
+       dev_dbg(&priv->i2c->dev,
+                       "%s: frequency=%d bandwidth_hz=%d inversion=%d\n",
+                       __func__, c->frequency, c->bandwidth_hz, c->inversion);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
@@ -346,7 +317,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
                i = 2;
                break;
        default:
-               dbg("invalid bandwidth");
+               dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
                return -EINVAL;
        }
 
@@ -354,6 +325,36 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
+       /* program if frequency */
+       if (fe->ops.tuner_ops.get_if_frequency)
+               ret = fe->ops.tuner_ops.get_if_frequency(fe, &if_frequency);
+       else
+               ret = -EINVAL;
+
+       if (ret < 0)
+               goto err;
+
+       num = if_frequency % priv->cfg.xtal;
+       num *= 0x400000;
+       num = div_u64(num, priv->cfg.xtal);
+       num = -num;
+       if_ctl = num & 0x3fffff;
+       dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d if_ctl=%08x\n",
+                       __func__, if_frequency, if_ctl);
+
+       ret = rtl2830_rd_reg_mask(priv, 0x119, &tmp, 0xc0); /* b[7:6] */
+       if (ret)
+               goto err;
+
+       buf[0] = tmp << 6;
+       buf[0] |= (if_ctl >> 16) & 0x3f;
+       buf[1] = (if_ctl >>  8) & 0xff;
+       buf[2] = (if_ctl >>  0) & 0xff;
+
+       ret = rtl2830_wr_regs(priv, 0x119, buf, 3);
+       if (ret)
+               goto err;
+
        /* 1/2 split I2C write */
        ret = rtl2830_wr_regs(priv, 0x11c, &bw_params1[i][0], 17);
        if (ret)
@@ -370,7 +371,7 @@ static int rtl2830_set_frontend(struct dvb_frontend *fe)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -392,7 +393,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe)
        if (ret)
                goto err;
 
-       dbg("%s: TPS=%02x %02x %02x", __func__, buf[0], buf[1], buf[2]);
+       dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
 
        switch ((buf[0] >> 2) & 3) {
        case 0:
@@ -482,7 +483,7 @@ static int rtl2830_get_frontend(struct dvb_frontend *fe)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -510,7 +511,7 @@ static int rtl2830_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -559,7 +560,7 @@ static int rtl2830_read_snr(struct dvb_frontend *fe, u16 *snr)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -580,7 +581,7 @@ static int rtl2830_read_ber(struct dvb_frontend *fe, u32 *ber)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -616,7 +617,7 @@ static int rtl2830_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
 
        return 0;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -640,11 +641,12 @@ static int rtl2830_tuner_i2c_xfer(struct i2c_adapter *i2c_adap,
 
        ret = i2c_transfer(priv->i2c, msg, num);
        if (ret < 0)
-               warn("tuner i2c failed=%d", ret);
+               dev_warn(&priv->i2c->dev, "%s: tuner i2c failed=%d\n",
+                       KBUILD_MODNAME, ret);
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -700,7 +702,9 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
        priv->tuner_i2c_adapter.algo_data = NULL;
        i2c_set_adapdata(&priv->tuner_i2c_adapter, priv);
        if (i2c_add_adapter(&priv->tuner_i2c_adapter) < 0) {
-               err("tuner I2C bus could not be initialized");
+               dev_err(&i2c->dev,
+                               "%s: tuner i2c bus could not be initialized\n",
+                               KBUILD_MODNAME);
                goto err;
        }
 
@@ -708,7 +712,7 @@ struct dvb_frontend *rtl2830_attach(const struct rtl2830_config *cfg,
 
        return &priv->fe;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
        kfree(priv);
        return NULL;
 }
similarity index 90%
rename from drivers/media/dvb/frontends/rtl2830.h
rename to drivers/media/dvb-frontends/rtl2830.h
index 1c6ee91749c252403ea39bb8f2fe7b21a03a7f32..f4349a1fc03e3879f8085159f4f31178164148bd 100644 (file)
@@ -46,13 +46,6 @@ struct rtl2830_config {
         */
        bool spec_inv;
 
-       /*
-        * IFs for all used modes.
-        * Hz
-        * 4570000, 4571429, 36000000, 36125000, 36166667, 44000000
-        */
-       u32 if_dvbt;
-
        /*
         */
        u8 vtop;
@@ -82,7 +75,7 @@ static inline struct dvb_frontend *rtl2830_attach(
        struct i2c_adapter *i2c
 )
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 
similarity index 75%
rename from drivers/media/dvb/frontends/rtl2830_priv.h
rename to drivers/media/dvb-frontends/rtl2830_priv.h
index 9b20557ccf6cde4410bd876ff4e8ad70667a5061..fab10ecb3c3b18f6e3bb1f5a249f2a686fbf021c 100644 (file)
 #include "dvb_math.h"
 #include "rtl2830.h"
 
-#define LOG_PREFIX "rtl2830"
-
-#undef dbg
-#define dbg(f, arg...) \
-       if (rtl2830_debug) \
-               printk(KERN_INFO            LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
 struct rtl2830_priv {
        struct i2c_adapter *i2c;
        struct dvb_frontend fe;
similarity index 77%
rename from drivers/media/dvb/frontends/rtl2832.c
rename to drivers/media/dvb-frontends/rtl2832.c
index 28269ccaeab709a95ce5a02ab345f1a86f6ec305..80c8e5f1182fdc377a7e6ac83ff3e2efc8e523c8 100644 (file)
@@ -19,6 +19,7 @@
  */
 
 #include "rtl2832_priv.h"
+#include "dvb_math.h"
 #include <linux/bitops.h>
 
 int rtl2832_debug;
@@ -178,7 +179,8 @@ static int rtl2832_wr(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -206,10 +208,11 @@ static int rtl2832_rd(struct rtl2832_priv *priv, u8 reg, u8 *val, int len)
        if (ret == 2) {
                ret = 0;
        } else {
-               warn("i2c rd failed=%d reg=%02x len=%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
-}
-return ret;
+       }
+       return ret;
 }
 
 /* write multiple registers */
@@ -218,7 +221,6 @@ static int rtl2832_wr_regs(struct rtl2832_priv *priv, u8 reg, u8 page, u8 *val,
 {
        int ret;
 
-
        /* switch bank if needed */
        if (page != priv->page) {
                ret = rtl2832_wr(priv, 0x00, &page, 1);
@@ -298,7 +300,7 @@ int rtl2832_rd_demod_reg(struct rtl2832_priv *priv, int reg, u32 *val)
        return ret;
 
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 
 }
@@ -350,18 +352,17 @@ int rtl2832_wr_demod_reg(struct rtl2832_priv *priv, int reg, u32 val)
        return ret;
 
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 
 }
 
-
 static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
        int ret;
        struct rtl2832_priv *priv = fe->demodulator_priv;
 
-       dbg("%s: enable=%d", __func__, enable);
+       dev_dbg(&priv->i2c->dev, "%s: enable=%d\n", __func__, enable);
 
        /* gate already open or close */
        if (priv->i2c_gate_state == enable)
@@ -375,19 +376,17 @@ static int rtl2832_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 
        return ret;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-
-
 static int rtl2832_init(struct dvb_frontend *fe)
 {
        struct rtl2832_priv *priv = fe->demodulator_priv;
-       int i, ret;
-
+       int i, ret, len;
        u8 en_bbin;
        u64 pset_iffreq;
+       const struct rtl2832_reg_value *init;
 
        /* initialization values for the demodulator registers */
        struct rtl2832_reg_value rtl2832_initial_regs[] = {
@@ -434,40 +433,9 @@ static int rtl2832_init(struct dvb_frontend *fe)
                {DVBT_TRK_KC_I2,                0x5},
                {DVBT_CR_THD_SET2,              0x1},
                {DVBT_SPEC_INV,                 0x0},
-               {DVBT_DAGC_TRG_VAL,             0x5a},
-               {DVBT_AGC_TARG_VAL_0,           0x0},
-               {DVBT_AGC_TARG_VAL_8_1,         0x5a},
-               {DVBT_AAGC_LOOP_GAIN,           0x16},
-               {DVBT_LOOP_GAIN2_3_0,           0x6},
-               {DVBT_LOOP_GAIN2_4,             0x1},
-               {DVBT_LOOP_GAIN3,               0x16},
-               {DVBT_VTOP1,                    0x35},
-               {DVBT_VTOP2,                    0x21},
-               {DVBT_VTOP3,                    0x21},
-               {DVBT_KRF1,                     0x0},
-               {DVBT_KRF2,                     0x40},
-               {DVBT_KRF3,                     0x10},
-               {DVBT_KRF4,                     0x10},
-               {DVBT_IF_AGC_MIN,               0x80},
-               {DVBT_IF_AGC_MAX,               0x7f},
-               {DVBT_RF_AGC_MIN,               0x80},
-               {DVBT_RF_AGC_MAX,               0x7f},
-               {DVBT_POLAR_RF_AGC,             0x0},
-               {DVBT_POLAR_IF_AGC,             0x0},
-               {DVBT_AD7_SETTING,              0xe9bf},
-               {DVBT_EN_GI_PGA,                0x0},
-               {DVBT_THD_LOCK_UP,              0x0},
-               {DVBT_THD_LOCK_DW,              0x0},
-               {DVBT_THD_UP1,                  0x11},
-               {DVBT_THD_DW1,                  0xef},
-               {DVBT_INTER_CNT_LEN,            0xc},
-               {DVBT_GI_PGA_STATE,             0x0},
-               {DVBT_EN_AGC_PGA,               0x1},
-               {DVBT_IF_AGC_MAN,               0x0},
        };
 
-
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
 
        en_bbin = (priv->cfg.if_dvbt == 0 ? 0x1 : 0x0);
 
@@ -480,8 +448,6 @@ static int rtl2832_init(struct dvb_frontend *fe)
        pset_iffreq = div_u64(pset_iffreq, priv->cfg.xtal);
        pset_iffreq = pset_iffreq & 0x3fffff;
 
-
-
        for (i = 0; i < ARRAY_SIZE(rtl2832_initial_regs); i++) {
                ret = rtl2832_wr_demod_reg(priv, rtl2832_initial_regs[i].reg,
                        rtl2832_initial_regs[i].value);
@@ -489,6 +455,34 @@ static int rtl2832_init(struct dvb_frontend *fe)
                        goto err;
        }
 
+       /* load tuner specific settings */
+       dev_dbg(&priv->i2c->dev, "%s: load settings for tuner=%02x\n",
+                       __func__, priv->cfg.tuner);
+       switch (priv->cfg.tuner) {
+       case RTL2832_TUNER_FC0012:
+       case RTL2832_TUNER_FC0013:
+               len = ARRAY_SIZE(rtl2832_tuner_init_fc0012);
+               init = rtl2832_tuner_init_fc0012;
+               break;
+       case RTL2832_TUNER_TUA9001:
+               len = ARRAY_SIZE(rtl2832_tuner_init_tua9001);
+               init = rtl2832_tuner_init_tua9001;
+               break;
+       case RTL2832_TUNER_E4000:
+               len = ARRAY_SIZE(rtl2832_tuner_init_e4000);
+               init = rtl2832_tuner_init_e4000;
+               break;
+       default:
+               ret = -EINVAL;
+               goto err;
+       }
+
+       for (i = 0; i < len; i++) {
+               ret = rtl2832_wr_demod_reg(priv, init[i].reg, init[i].value);
+               if (ret)
+                       goto err;
+       }
+
        /* if frequency settings */
        ret = rtl2832_wr_demod_reg(priv, DVBT_EN_BBIN, en_bbin);
                if (ret)
@@ -503,7 +497,7 @@ static int rtl2832_init(struct dvb_frontend *fe)
        return ret;
 
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -511,7 +505,7 @@ static int rtl2832_sleep(struct dvb_frontend *fe)
 {
        struct rtl2832_priv *priv = fe->demodulator_priv;
 
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
        priv->sleeping = true;
        return 0;
 }
@@ -519,7 +513,9 @@ static int rtl2832_sleep(struct dvb_frontend *fe)
 int rtl2832_get_tune_settings(struct dvb_frontend *fe,
        struct dvb_frontend_tune_settings *s)
 {
-       dbg("%s", __func__);
+       struct rtl2832_priv *priv = fe->demodulator_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
        s->min_delay_ms = 1000;
        s->step_size = fe->ops.info.frequency_stepsize * 2;
        s->max_drift = (fe->ops.info.frequency_stepsize * 2) + 1;
@@ -533,8 +529,6 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
        int ret, i, j;
        u64 bw_mode, num, num2;
        u32 resamp_ratio, cfreq_off_ratio;
-
-
        static u8 bw_params[3][32] = {
        /* 6 MHz bandwidth */
                {
@@ -562,15 +556,14 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
        };
 
 
-       dbg("%s: frequency=%d bandwidth_hz=%d inversion=%d", __func__,
-               c->frequency, c->bandwidth_hz, c->inversion);
-
+       dev_dbg(&priv->i2c->dev, "%s: frequency=%d bandwidth_hz=%d " \
+                       "inversion=%d\n", __func__, c->frequency,
+                       c->bandwidth_hz, c->inversion);
 
        /* program tuner */
        if (fe->ops.tuner_ops.set_params)
                fe->ops.tuner_ops.set_params(fe);
 
-
        switch (c->bandwidth_hz) {
        case 6000000:
                i = 0;
@@ -585,7 +578,7 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
                bw_mode = 64000000;
                break;
        default:
-               dbg("invalid bandwidth");
+               dev_dbg(&priv->i2c->dev, "%s: invalid bandwidth\n", __func__);
                return -EINVAL;
        }
 
@@ -632,7 +625,119 @@ static int rtl2832_set_frontend(struct dvb_frontend *fe)
 
        return ret;
 err:
-       info("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int rtl2832_get_frontend(struct dvb_frontend *fe)
+{
+       struct rtl2832_priv *priv = fe->demodulator_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret;
+       u8 buf[3];
+
+       if (priv->sleeping)
+               return 0;
+
+       ret = rtl2832_rd_regs(priv, 0x3c, 3, buf, 2);
+       if (ret)
+               goto err;
+
+       ret = rtl2832_rd_reg(priv, 0x51, 3, &buf[2]);
+       if (ret)
+               goto err;
+
+       dev_dbg(&priv->i2c->dev, "%s: TPS=%*ph\n", __func__, 3, buf);
+
+       switch ((buf[0] >> 2) & 3) {
+       case 0:
+               c->modulation = QPSK;
+               break;
+       case 1:
+               c->modulation = QAM_16;
+               break;
+       case 2:
+               c->modulation = QAM_64;
+               break;
+       }
+
+       switch ((buf[2] >> 2) & 1) {
+       case 0:
+               c->transmission_mode = TRANSMISSION_MODE_2K;
+               break;
+       case 1:
+               c->transmission_mode = TRANSMISSION_MODE_8K;
+       }
+
+       switch ((buf[2] >> 0) & 3) {
+       case 0:
+               c->guard_interval = GUARD_INTERVAL_1_32;
+               break;
+       case 1:
+               c->guard_interval = GUARD_INTERVAL_1_16;
+               break;
+       case 2:
+               c->guard_interval = GUARD_INTERVAL_1_8;
+               break;
+       case 3:
+               c->guard_interval = GUARD_INTERVAL_1_4;
+               break;
+       }
+
+       switch ((buf[0] >> 4) & 7) {
+       case 0:
+               c->hierarchy = HIERARCHY_NONE;
+               break;
+       case 1:
+               c->hierarchy = HIERARCHY_1;
+               break;
+       case 2:
+               c->hierarchy = HIERARCHY_2;
+               break;
+       case 3:
+               c->hierarchy = HIERARCHY_4;
+               break;
+       }
+
+       switch ((buf[1] >> 3) & 7) {
+       case 0:
+               c->code_rate_HP = FEC_1_2;
+               break;
+       case 1:
+               c->code_rate_HP = FEC_2_3;
+               break;
+       case 2:
+               c->code_rate_HP = FEC_3_4;
+               break;
+       case 3:
+               c->code_rate_HP = FEC_5_6;
+               break;
+       case 4:
+               c->code_rate_HP = FEC_7_8;
+               break;
+       }
+
+       switch ((buf[1] >> 0) & 7) {
+       case 0:
+               c->code_rate_LP = FEC_1_2;
+               break;
+       case 1:
+               c->code_rate_LP = FEC_2_3;
+               break;
+       case 2:
+               c->code_rate_LP = FEC_3_4;
+               break;
+       case 3:
+               c->code_rate_LP = FEC_5_6;
+               break;
+       case 4:
+               c->code_rate_LP = FEC_7_8;
+               break;
+       }
+
+       return 0;
+err:
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -643,8 +748,7 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
        u32 tmp;
        *status = 0;
 
-
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
        if (priv->sleeping)
                return 0;
 
@@ -664,33 +768,72 @@ static int rtl2832_read_status(struct dvb_frontend *fe, fe_status_t *status)
 
        return ret;
 err:
-       info("%s: failed=%d", __func__, ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
 static int rtl2832_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-       *snr = 0;
+       struct rtl2832_priv *priv = fe->demodulator_priv;
+       int ret, hierarchy, constellation;
+       u8 buf[2], tmp;
+       u16 tmp16;
+#define CONSTELLATION_NUM 3
+#define HIERARCHY_NUM 4
+       static const u32 snr_constant[CONSTELLATION_NUM][HIERARCHY_NUM] = {
+               { 85387325, 85387325, 85387325, 85387325 },
+               { 86676178, 86676178, 87167949, 87795660 },
+               { 87659938, 87659938, 87885178, 88241743 },
+       };
+
+       /* reports SNR in resolution of 0.1 dB */
+
+       ret = rtl2832_rd_reg(priv, 0x3c, 3, &tmp);
+       if (ret)
+               goto err;
+
+       constellation = (tmp >> 2) & 0x03; /* [3:2] */
+       if (constellation > CONSTELLATION_NUM - 1)
+               goto err;
+
+       hierarchy = (tmp >> 4) & 0x07; /* [6:4] */
+       if (hierarchy > HIERARCHY_NUM - 1)
+               goto err;
+
+       ret = rtl2832_rd_regs(priv, 0x0c, 4, buf, 2);
+       if (ret)
+               goto err;
+
+       tmp16 = buf[0] << 8 | buf[1];
+
+       if (tmp16)
+               *snr = (snr_constant[constellation][hierarchy] -
+                               intlog10(tmp16)) / ((1 << 24) / 100);
+       else
+               *snr = 0;
+
        return 0;
+err:
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
 }
 
 static int rtl2832_read_ber(struct dvb_frontend *fe, u32 *ber)
 {
-       *ber = 0;
-       return 0;
-}
+       struct rtl2832_priv *priv = fe->demodulator_priv;
+       int ret;
+       u8 buf[2];
 
-static int rtl2832_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
-{
-       *ucblocks = 0;
-       return 0;
-}
+       ret = rtl2832_rd_regs(priv, 0x4e, 3, buf, 2);
+       if (ret)
+               goto err;
 
+       *ber = buf[0] << 8 | buf[1];
 
-static int rtl2832_read_signal_strength(struct dvb_frontend *fe, u16 *strength)
-{
-       *strength = 0;
        return 0;
+err:
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
 }
 
 static struct dvb_frontend_ops rtl2832_ops;
@@ -699,7 +842,7 @@ static void rtl2832_release(struct dvb_frontend *fe)
 {
        struct rtl2832_priv *priv = fe->demodulator_priv;
 
-       dbg("%s", __func__);
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
        kfree(priv);
 }
 
@@ -710,7 +853,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
        int ret = 0;
        u8 tmp;
 
-       dbg("%s", __func__);
+       dev_dbg(&i2c->dev, "%s:\n", __func__);
 
        /* allocate memory for the internal state */
        priv = kzalloc(sizeof(struct rtl2832_priv), GFP_KERNEL);
@@ -736,7 +879,7 @@ struct dvb_frontend *rtl2832_attach(const struct rtl2832_config *cfg,
 
        return &priv->fe;
 err:
-       dbg("%s: failed=%d", __func__, ret);
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
        kfree(priv);
        return NULL;
 }
@@ -774,12 +917,12 @@ static struct dvb_frontend_ops rtl2832_ops = {
        .get_tune_settings = rtl2832_get_tune_settings,
 
        .set_frontend = rtl2832_set_frontend,
+       .get_frontend = rtl2832_get_frontend,
 
        .read_status = rtl2832_read_status,
        .read_snr = rtl2832_read_snr,
        .read_ber = rtl2832_read_ber,
-       .read_ucblocks = rtl2832_read_ucblocks,
-       .read_signal_strength = rtl2832_read_signal_strength,
+
        .i2c_gate_ctrl = rtl2832_i2c_gate_ctrl,
 };
 
similarity index 84%
rename from drivers/media/dvb/frontends/rtl2832.h
rename to drivers/media/dvb-frontends/rtl2832.h
index d94dc9a3fa628f9d1ce35743838782064ce47eee..785a466eb06555472d37ca092e34fbbdea287f4f 100644 (file)
@@ -44,28 +44,29 @@ struct rtl2832_config {
        u32 if_dvbt;
 
        /*
+        * tuner
+        * XXX: This must be keep sync with dvb_usb_rtl28xxu demod driver.
         */
+#define RTL2832_TUNER_TUA9001   0x24
+#define RTL2832_TUNER_FC0012    0x26
+#define RTL2832_TUNER_E4000     0x27
+#define RTL2832_TUNER_FC0013    0x29
        u8 tuner;
 };
 
-
 #if defined(CONFIG_DVB_RTL2832) || \
        (defined(CONFIG_DVB_RTL2832_MODULE) && defined(MODULE))
 extern struct dvb_frontend *rtl2832_attach(
        const struct rtl2832_config *cfg,
        struct i2c_adapter *i2c
 );
-
-extern struct i2c_adapter *rtl2832_get_tuner_i2c_adapter(
-       struct dvb_frontend *fe
-);
 #else
 static inline struct dvb_frontend *rtl2832_attach(
        const struct rtl2832_config *config,
        struct i2c_adapter *i2c
 )
 {
-       printk(KERN_WARNING "%s: driver disabled by Kconfig\n", __func__);
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
        return NULL;
 }
 #endif
similarity index 55%
rename from drivers/media/dvb/frontends/rtl2832_priv.h
rename to drivers/media/dvb-frontends/rtl2832_priv.h
index 0ce9502da8ba6817f4a96db3895462f33469e26a..7d97ce9d2193ea206ebae9fa3d7dcccf2db4a9f6 100644 (file)
 #include "dvb_frontend.h"
 #include "rtl2832.h"
 
-#define LOG_PREFIX "rtl2832"
-
-#undef dbg
-#define dbg(f, arg...) \
-do { \
-       if (rtl2832_debug)  \
-               printk(KERN_INFO     LOG_PREFIX": " f "\n" , ## arg); \
-} while (0)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
 struct rtl2832_priv {
        struct i2c_adapter *i2c;
        struct dvb_frontend fe;
@@ -257,4 +242,101 @@ enum DVBT_REG_BIT_NAME {
        DVBT_REG_BIT_NAME_ITEM_TERMINATOR,
 };
 
+static const struct rtl2832_reg_value rtl2832_tuner_init_tua9001[] = {
+       {DVBT_DAGC_TRG_VAL,             0x39},
+       {DVBT_AGC_TARG_VAL_0,            0x0},
+       {DVBT_AGC_TARG_VAL_8_1,         0x5a},
+       {DVBT_AAGC_LOOP_GAIN,           0x16},
+       {DVBT_LOOP_GAIN2_3_0,            0x6},
+       {DVBT_LOOP_GAIN2_4,              0x1},
+       {DVBT_LOOP_GAIN3,               0x16},
+       {DVBT_VTOP1,                    0x35},
+       {DVBT_VTOP2,                    0x21},
+       {DVBT_VTOP3,                    0x21},
+       {DVBT_KRF1,                      0x0},
+       {DVBT_KRF2,                     0x40},
+       {DVBT_KRF3,                     0x10},
+       {DVBT_KRF4,                     0x10},
+       {DVBT_IF_AGC_MIN,               0x80},
+       {DVBT_IF_AGC_MAX,               0x7f},
+       {DVBT_RF_AGC_MIN,               0x9c},
+       {DVBT_RF_AGC_MAX,               0x7f},
+       {DVBT_POLAR_RF_AGC,              0x0},
+       {DVBT_POLAR_IF_AGC,              0x0},
+       {DVBT_AD7_SETTING,            0xe9f4},
+       {DVBT_OPT_ADC_IQ,                0x1},
+       {DVBT_AD_AVI,                    0x0},
+       {DVBT_AD_AVQ,                    0x0},
+};
+
+static const struct rtl2832_reg_value rtl2832_tuner_init_fc0012[] = {
+       {DVBT_DAGC_TRG_VAL,             0x5a},
+       {DVBT_AGC_TARG_VAL_0,            0x0},
+       {DVBT_AGC_TARG_VAL_8_1,         0x5a},
+       {DVBT_AAGC_LOOP_GAIN,           0x16},
+       {DVBT_LOOP_GAIN2_3_0,            0x6},
+       {DVBT_LOOP_GAIN2_4,              0x1},
+       {DVBT_LOOP_GAIN3,               0x16},
+       {DVBT_VTOP1,                    0x35},
+       {DVBT_VTOP2,                    0x21},
+       {DVBT_VTOP3,                    0x21},
+       {DVBT_KRF1,                      0x0},
+       {DVBT_KRF2,                     0x40},
+       {DVBT_KRF3,                     0x10},
+       {DVBT_KRF4,                     0x10},
+       {DVBT_IF_AGC_MIN,               0x80},
+       {DVBT_IF_AGC_MAX,               0x7f},
+       {DVBT_RF_AGC_MIN,               0x80},
+       {DVBT_RF_AGC_MAX,               0x7f},
+       {DVBT_POLAR_RF_AGC,              0x0},
+       {DVBT_POLAR_IF_AGC,              0x0},
+       {DVBT_AD7_SETTING,            0xe9bf},
+       {DVBT_EN_GI_PGA,                 0x0},
+       {DVBT_THD_LOCK_UP,               0x0},
+       {DVBT_THD_LOCK_DW,               0x0},
+       {DVBT_THD_UP1,                  0x11},
+       {DVBT_THD_DW1,                  0xef},
+       {DVBT_INTER_CNT_LEN,             0xc},
+       {DVBT_GI_PGA_STATE,              0x0},
+       {DVBT_EN_AGC_PGA,                0x1},
+       {DVBT_IF_AGC_MAN,                0x0},
+};
+
+static const struct rtl2832_reg_value rtl2832_tuner_init_e4000[] = {
+       {DVBT_DAGC_TRG_VAL,             0x5a},
+       {DVBT_AGC_TARG_VAL_0,            0x0},
+       {DVBT_AGC_TARG_VAL_8_1,         0x5a},
+       {DVBT_AAGC_LOOP_GAIN,           0x18},
+       {DVBT_LOOP_GAIN2_3_0,            0x8},
+       {DVBT_LOOP_GAIN2_4,              0x1},
+       {DVBT_LOOP_GAIN3,               0x18},
+       {DVBT_VTOP1,                    0x35},
+       {DVBT_VTOP2,                    0x21},
+       {DVBT_VTOP3,                    0x21},
+       {DVBT_KRF1,                      0x0},
+       {DVBT_KRF2,                     0x40},
+       {DVBT_KRF3,                     0x10},
+       {DVBT_KRF4,                     0x10},
+       {DVBT_IF_AGC_MIN,               0x80},
+       {DVBT_IF_AGC_MAX,               0x7f},
+       {DVBT_RF_AGC_MIN,               0x80},
+       {DVBT_RF_AGC_MAX,               0x7f},
+       {DVBT_POLAR_RF_AGC,              0x0},
+       {DVBT_POLAR_IF_AGC,              0x0},
+       {DVBT_AD7_SETTING,            0xe9d4},
+       {DVBT_EN_GI_PGA,                 0x0},
+       {DVBT_THD_LOCK_UP,               0x0},
+       {DVBT_THD_LOCK_DW,               0x0},
+       {DVBT_THD_UP1,                  0x14},
+       {DVBT_THD_DW1,                  0xec},
+       {DVBT_INTER_CNT_LEN,             0xc},
+       {DVBT_GI_PGA_STATE,              0x0},
+       {DVBT_EN_AGC_PGA,                0x1},
+       {DVBT_REG_GPE,                   0x1},
+       {DVBT_REG_GPO,                   0x1},
+       {DVBT_REG_MONSEL,                0x1},
+       {DVBT_REG_MON,                   0x1},
+       {DVBT_REG_4MSEL,                 0x0},
+};
+
 #endif /* RTL2832_PRIV_H */
similarity index 99%
rename from drivers/media/dvb/frontends/stb0899_drv.c
rename to drivers/media/dvb-frontends/stb0899_drv.c
index 5d7f8a9b451b8ec93fc596a6d813004b8866cd87..79e29de87fb7b50feb4f2fd65bed5e00c6b6ac8d 100644 (file)
@@ -1563,6 +1563,7 @@ static int stb0899_get_frontend(struct dvb_frontend *fe)
 
        dprintk(state->verbose, FE_DEBUG, 1, "Get params");
        p->symbol_rate = internal->srate;
+       p->frequency = internal->freq;
 
        return 0;
 }
similarity index 99%
rename from drivers/media/dvb/frontends/stv090x.c
rename to drivers/media/dvb-frontends/stv090x.c
index ea86a5603e5756106a342a18668d3b8889ebdd1e..13caec013902b72839c473be7d1ba3f02e7aa96d 100644 (file)
@@ -3425,6 +3425,33 @@ err:
        return -1;
 }
 
+static int stv090x_set_mis(struct stv090x_state *state, int mis)
+{
+       u32 reg;
+
+       if (mis < 0 || mis > 255) {
+               dprintk(FE_DEBUG, 1, "Disable MIS filtering");
+               reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+               STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x00);
+               if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+                       goto err;
+       } else {
+               dprintk(FE_DEBUG, 1, "Enable MIS filtering - %d", mis);
+               reg = STV090x_READ_DEMOD(state, PDELCTRL1);
+               STV090x_SETFIELD_Px(reg, FILTER_EN_FIELD, 0x01);
+               if (STV090x_WRITE_DEMOD(state, PDELCTRL1, reg) < 0)
+                       goto err;
+               if (STV090x_WRITE_DEMOD(state, ISIENTRY, mis) < 0)
+                       goto err;
+               if (STV090x_WRITE_DEMOD(state, ISIBITENA, 0xff) < 0)
+                       goto err;
+       }
+       return 0;
+err:
+       dprintk(FE_ERROR, 1, "I/O error");
+       return -1;
+}
+
 static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
 {
        struct stv090x_state *state = fe->demodulator_priv;
@@ -3447,6 +3474,8 @@ static enum dvbfe_search stv090x_search(struct dvb_frontend *fe)
                state->search_range = 5000000;
        }
 
+       stv090x_set_mis(state, props->stream_id);
+
        if (stv090x_algo(state) == STV090x_RANGEOK) {
                dprintk(FE_DEBUG, 1, "Search success!");
                return DVBFE_ALGO_SEARCH_SUCCESS;
@@ -4798,6 +4827,9 @@ struct dvb_frontend *stv090x_attach(const struct stv090x_config *config,
                }
        }
 
+       if (state->internal->dev_ver >= 0x30)
+               state->frontend.ops.info.caps |= FE_CAN_MULTISTREAM;
+
        /* workaround for stuck DiSEqC output */
        if (config->diseqc_envelope_mode)
                stv090x_send_diseqc_burst(&state->frontend, SEC_MINI_A);
similarity index 99%
rename from drivers/media/dvb/frontends/tda1004x.c
rename to drivers/media/dvb-frontends/tda1004x.c
index 35d72b46aa1e81acc51706433738f21abac76767..a2631be7ffac9943384bdabc608b811f5686859e 100644 (file)
@@ -329,6 +329,7 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
        tda1004x_write_byteI(state, dspCodeCounterReg, 0);
        fw_msg.addr = state->config->demod_address;
 
+       i2c_lock_adapter(state->i2c);
        buf[0] = dspCodeInReg;
        while (pos != len) {
                // work out how much to send this time
@@ -339,15 +340,18 @@ static int tda1004x_do_upload(struct tda1004x_state *state,
                // send the chunk
                memcpy(buf + 1, mem + pos, tx_size);
                fw_msg.len = tx_size + 1;
-               if (i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
+               if (__i2c_transfer(state->i2c, &fw_msg, 1) != 1) {
                        printk(KERN_ERR "tda1004x: Error during firmware upload\n");
+                       i2c_unlock_adapter(state->i2c);
                        return -EIO;
                }
                pos += tx_size;
 
                dprintk("%s: fw_pos=0x%x\n", __func__, pos);
        }
-       // give the DSP a chance to settle 03/10/05 Hac
+       i2c_unlock_adapter(state->i2c);
+
+       /* give the DSP a chance to settle 03/10/05 Hac */
        msleep(100);
 
        return 0;
similarity index 99%
rename from drivers/media/dvb/frontends/tda10071.c
rename to drivers/media/dvb-frontends/tda10071.c
index 703c3d05f9f453f67f054234f4e86818743ff5f9..a83bf680234529a8504b6e3439e6b5f21fa3824b 100644 (file)
@@ -257,7 +257,7 @@ static int tda10071_set_voltage(struct dvb_frontend *fe,
                                __func__);
                ret = -EINVAL;
                goto error;
-       };
+       }
 
        cmd.args[0] = CMD_LNB_SET_DC_LEVEL;
        cmd.args[1] = 0;
@@ -369,7 +369,7 @@ static int tda10071_diseqc_recv_slave_reply(struct dvb_frontend *fe,
        if (ret)
                goto error;
 
-       reply->msg_len = tmp & 0x1f; /* [4:0] */;
+       reply->msg_len = tmp & 0x1f; /* [4:0] */
        if (reply->msg_len > sizeof(reply->msg))
                reply->msg_len = sizeof(reply->msg); /* truncate API max */
 
@@ -850,7 +850,7 @@ static int tda10071_init(struct dvb_frontend *fe)
        struct tda10071_cmd cmd;
        int ret, i, len, remaining, fw_size;
        const struct firmware *fw;
-       u8 *fw_file = TDA10071_DEFAULT_FIRMWARE;
+       u8 *fw_file = TDA10071_FIRMWARE;
        u8 tmp, buf[4];
        struct tda10071_reg_val_mask tab[] = {
                { 0xcd, 0x00, 0x07 },
@@ -1282,3 +1282,4 @@ static struct dvb_frontend_ops tda10071_ops = {
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("NXP TDA10071 DVB-S/S2 demodulator driver");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(TDA10071_FIRMWARE);
similarity index 98%
rename from drivers/media/dvb/frontends/tda10071_priv.h
rename to drivers/media/dvb-frontends/tda10071_priv.h
index 0fa85cfa70c21d85b0f06952b0e8b035c6cd4c92..4baf14bfb65a6d6ca4a485861492efcdc955f006 100644 (file)
@@ -77,7 +77,7 @@ struct tda10071_reg_val_mask {
 };
 
 /* firmware filename */
-#define TDA10071_DEFAULT_FIRMWARE      "dvb-fe-tda10071.fw"
+#define TDA10071_FIRMWARE "dvb-fe-tda10071.fw"
 
 /* firmware commands */
 #define CMD_DEMOD_INIT          0x10
similarity index 86%
rename from drivers/media/dvb/frontends/tda8261.c
rename to drivers/media/dvb-frontends/tda8261.c
index 53c7d8f1df289a373a3b96a143f87841f6fd0d43..19c488814e5c78e5b7e87e78419190d8e40faa11 100644 (file)
@@ -43,7 +43,7 @@ static int tda8261_read(struct tda8261_state *state, u8 *buf)
        struct i2c_msg msg = { .addr    = config->addr, .flags = I2C_M_RD,.buf = buf,  .len = 1 };
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
-               printk("%s: read error, err=%d\n", __func__, err);
+               pr_err("%s: read error, err=%d\n", __func__, err);
 
        return err;
 }
@@ -55,7 +55,7 @@ static int tda8261_write(struct tda8261_state *state, u8 *buf)
        struct i2c_msg msg = { .addr = config->addr, .flags = 0, .buf = buf, .len = 4 };
 
        if ((err = i2c_transfer(state->i2c, &msg, 1)) != 1)
-               printk("%s: write error, err=%d\n", __func__, err);
+               pr_err("%s: write error, err=%d\n", __func__, err);
 
        return err;
 }
@@ -69,11 +69,11 @@ static int tda8261_get_status(struct dvb_frontend *fe, u32 *status)
        *status = 0;
 
        if ((err = tda8261_read(state, &result)) < 0) {
-               printk("%s: I/O Error\n", __func__);
+               pr_err("%s: I/O Error\n", __func__);
                return err;
        }
        if ((result >> 6) & 0x01) {
-               printk("%s: Tuner Phase Locked\n", __func__);
+               pr_debug("%s: Tuner Phase Locked\n", __func__);
                *status = 1;
        }
 
@@ -98,7 +98,7 @@ static int tda8261_get_state(struct dvb_frontend *fe,
                tstate->bandwidth = 40000000; /* FIXME! need to calculate Bandwidth */
                break;
        default:
-               printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+               pr_err("%s: Unknown parameter (param=%d)\n", __func__, param);
                err = -EINVAL;
                break;
        }
@@ -124,11 +124,11 @@ static int tda8261_set_state(struct dvb_frontend *fe,
                 */
                frequency = tstate->frequency;
                if ((frequency < 950000) || (frequency > 2150000)) {
-                       printk("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
+                       pr_warn("%s: Frequency beyond limits, frequency=%d\n", __func__, frequency);
                        return -EINVAL;
                }
                N = (frequency + (div_tab[config->step_size] - 1)) / div_tab[config->step_size];
-               printk("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
+               pr_debug("%s: Step size=%d, Divider=%d, PG=0x%02x (%d)\n",
                        __func__, config->step_size, div_tab[config->step_size], N, N);
 
                buf[0] = (N >> 8) & 0xff;
@@ -144,25 +144,25 @@ static int tda8261_set_state(struct dvb_frontend *fe,
 
                /* Set params */
                if ((err = tda8261_write(state, buf)) < 0) {
-                       printk("%s: I/O Error\n", __func__);
+                       pr_err("%s: I/O Error\n", __func__);
                        return err;
                }
                /* sleep for some time */
-               printk("%s: Waiting to Phase LOCK\n", __func__);
+               pr_debug("%s: Waiting to Phase LOCK\n", __func__);
                msleep(20);
                /* check status */
                if ((err = tda8261_get_status(fe, &status)) < 0) {
-                       printk("%s: I/O Error\n", __func__);
+                       pr_err("%s: I/O Error\n", __func__);
                        return err;
                }
                if (status == 1) {
-                       printk("%s: Tuner Phase locked: status=%d\n", __func__, status);
+                       pr_debug("%s: Tuner Phase locked: status=%d\n", __func__, status);
                        state->frequency = frequency; /* cache successful state */
                } else {
-                       printk("%s: No Phase lock: status=%d\n", __func__, status);
+                       pr_debug("%s: No Phase lock: status=%d\n", __func__, status);
                }
        } else {
-               printk("%s: Unknown parameter (param=%d)\n", __func__, param);
+               pr_err("%s: Unknown parameter (param=%d)\n", __func__, param);
                return -EINVAL;
        }
 
@@ -214,7 +214,7 @@ struct dvb_frontend *tda8261_attach(struct dvb_frontend *fe,
 
 //     printk("%s: Attaching %s TDA8261 8PSK/QPSK tuner\n",
 //             __func__, fe->ops.tuner_ops.tuner_name);
-       printk("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
+       pr_info("%s: Attaching TDA8261 8PSK/QPSK tuner\n", __func__);
 
        return fe;
 
diff --git a/drivers/media/dvb/Kconfig b/drivers/media/dvb/Kconfig
deleted file mode 100644 (file)
index f6e40b3..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-#
-# DVB device configuration
-#
-
-config DVB_MAX_ADAPTERS
-       int "maximum number of DVB/ATSC adapters"
-       depends on DVB_CORE
-       default 8
-       range 1 255
-       help
-         Maximum number of DVB/ATSC adapters. Increasing this number
-         increases the memory consumption of the DVB subsystem even
-         if a much lower number of DVB/ATSC adapters is present.
-         Only values in the range 4-32 are tested.
-
-         If you are unsure about this, use the default value 8
-
-config DVB_DYNAMIC_MINORS
-       bool "Dynamic DVB minor allocation"
-       depends on DVB_CORE
-       default n
-       help
-         If you say Y here, the DVB subsystem will use dynamic minor
-         allocation for any device that uses the DVB major number.
-         This means that you can have more than 4 of a single type
-         of device (like demuxes and frontends) per adapter, but udev
-         will be required to manage the device nodes.
-
-         If you are unsure about this, say N here.
-
-menuconfig DVB_CAPTURE_DRIVERS
-       bool "DVB/ATSC adapters"
-       depends on DVB_CORE
-       default y
-       ---help---
-         Say Y to select Digital TV adapters
-
-if DVB_CAPTURE_DRIVERS && DVB_CORE
-
-comment "Supported SAA7146 based PCI Adapters"
-       depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/ttpci/Kconfig"
-
-comment "Supported USB Adapters"
-       depends on DVB_CORE && USB && I2C
-source "drivers/media/dvb/dvb-usb/Kconfig"
-source "drivers/media/dvb/ttusb-budget/Kconfig"
-source "drivers/media/dvb/ttusb-dec/Kconfig"
-source "drivers/media/dvb/siano/Kconfig"
-
-comment "Supported FlexCopII (B2C2) Adapters"
-       depends on DVB_CORE && (PCI || USB) && I2C
-source "drivers/media/dvb/b2c2/Kconfig"
-
-comment "Supported BT878 Adapters"
-       depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/bt8xx/Kconfig"
-
-comment "Supported Pluto2 Adapters"
-       depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/pluto2/Kconfig"
-
-comment "Supported SDMC DM1105 Adapters"
-       depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/dm1105/Kconfig"
-
-comment "Supported FireWire (IEEE 1394) Adapters"
-       depends on DVB_CORE && FIREWIRE
-source "drivers/media/dvb/firewire/Kconfig"
-
-comment "Supported Earthsoft PT1 Adapters"
-       depends on DVB_CORE && PCI && I2C
-source "drivers/media/dvb/pt1/Kconfig"
-
-comment "Supported Mantis Adapters"
-       depends on DVB_CORE && PCI && I2C
-       source "drivers/media/dvb/mantis/Kconfig"
-
-comment "Supported nGene Adapters"
-       depends on DVB_CORE && PCI && I2C
-       source "drivers/media/dvb/ngene/Kconfig"
-
-comment "Supported ddbridge ('Octopus') Adapters"
-       depends on DVB_CORE && PCI && I2C
-       source "drivers/media/dvb/ddbridge/Kconfig"
-
-comment "Supported DVB Frontends"
-       depends on DVB_CORE
-source "drivers/media/dvb/frontends/Kconfig"
-
-endif # DVB_CAPTURE_DRIVERS
diff --git a/drivers/media/dvb/Makefile b/drivers/media/dvb/Makefile
deleted file mode 100644 (file)
index b2cefe6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-#
-# Makefile for the kernel multimedia device drivers.
-#
-
-obj-y        := dvb-core/      \
-               frontends/      \
-               ttpci/          \
-               ttusb-dec/      \
-               ttusb-budget/   \
-               b2c2/           \
-               bt8xx/          \
-               dvb-usb/        \
-               pluto2/         \
-               siano/          \
-               dm1105/         \
-               pt1/            \
-               mantis/         \
-               ngene/          \
-               ddbridge/
-
-obj-$(CONFIG_DVB_FIREDTV)      += firewire/
diff --git a/drivers/media/dvb/b2c2/Kconfig b/drivers/media/dvb/b2c2/Kconfig
deleted file mode 100644 (file)
index 9e57814..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-config DVB_B2C2_FLEXCOP
-       tristate "Technisat/B2C2 FlexCopII(b) and FlexCopIII adapters"
-       depends on DVB_CORE && I2C
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_MT312 if !DVB_FE_CUSTOMISE
-       select DVB_NXT200X if !DVB_FE_CUSTOMISE
-       select DVB_STV0297 if !DVB_FE_CUSTOMISE
-       select DVB_BCM3510 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_S5H1420 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_ITD1000 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select DVB_CX24123 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select DVB_TUNER_CX24113 if !DVB_FE_CUSTOMISE
-       help
-         Support for the digital TV receiver chip made by B2C2 Inc. included in
-         Technisats PCI cards and USB boxes.
-
-         Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_PCI
-       tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
-       depends on DVB_B2C2_FLEXCOP && PCI && I2C
-       help
-         Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
-
-         Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_USB
-       tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
-       depends on DVB_B2C2_FLEXCOP && USB && I2C
-       help
-         Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2,
-
-         Say Y if you own such a device and want to use it.
-
-config DVB_B2C2_FLEXCOP_DEBUG
-       bool "Enable debug for the B2C2 FlexCop drivers"
-       depends on DVB_B2C2_FLEXCOP
-       help
-         Say Y if you want to enable the module option to control debug messages
-         of all B2C2 FlexCop drivers.
diff --git a/drivers/media/dvb/b2c2/Makefile b/drivers/media/dvb/b2c2/Makefile
deleted file mode 100644 (file)
index 3d04a8d..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-b2c2-flexcop-objs = flexcop.o flexcop-fe-tuner.o flexcop-i2c.o \
-       flexcop-sram.o flexcop-eeprom.o flexcop-misc.o flexcop-hw-filter.o
-obj-$(CONFIG_DVB_B2C2_FLEXCOP) += b2c2-flexcop.o
-
-ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
-b2c2-flexcop-objs += flexcop-dma.o
-endif
-
-b2c2-flexcop-pci-objs = flexcop-pci.o
-obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
-
-b2c2-flexcop-usb-objs = flexcop-usb.o
-obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
diff --git a/drivers/media/dvb/bt8xx/Kconfig b/drivers/media/dvb/bt8xx/Kconfig
deleted file mode 100644 (file)
index 8668e63..0000000
+++ /dev/null
@@ -1,22 +0,0 @@
-config DVB_BT8XX
-       tristate "BT8xx based PCI cards"
-       depends on DVB_CORE && PCI && I2C && VIDEO_BT848
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_SP887X if !DVB_FE_CUSTOMISE
-       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
-       select DVB_CX24110 if !DVB_FE_CUSTOMISE
-       select DVB_OR51211 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       help
-         Support for PCI cards based on the Bt8xx PCI bridge. Examples are
-         the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
-         the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and
-         some AVerMedia cards.
-
-         Since these cards have no MPEG decoder onboard, they transmit
-         only compressed MPEG data over the PCI bus, so you need
-         an external software decoder to watch TV on your computer.
-
-         Say Y if you own such a device and want to use it.
diff --git a/drivers/media/dvb/bt8xx/Makefile b/drivers/media/dvb/bt8xx/Makefile
deleted file mode 100644 (file)
index 0713b3a..0000000
+++ /dev/null
@@ -1,6 +0,0 @@
-obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
-ccflags-y += -Idrivers/media/video/bt8xx
-ccflags-y += -Idrivers/media/common/tuners
diff --git a/drivers/media/dvb/dm1105/Makefile b/drivers/media/dvb/dm1105/Makefile
deleted file mode 100644 (file)
index 95a008b..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_DM1105) += dm1105.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
diff --git a/drivers/media/dvb/dvb-usb/Kconfig b/drivers/media/dvb/dvb-usb/Kconfig
deleted file mode 100644 (file)
index c216156..0000000
+++ /dev/null
@@ -1,440 +0,0 @@
-config DVB_USB
-       tristate "Support for various USB DVB devices"
-       depends on DVB_CORE && USB && I2C && RC_CORE
-       help
-         By enabling this you will be able to choose the various supported
-         USB1.1 and USB2.0 DVB devices.
-
-         Almost every USB device needs a firmware, please look into
-         <file:Documentation/dvb/README.dvb-usb>.
-
-         For a complete list of supported USB devices see the LinuxTV DVB Wiki:
-         <http://www.linuxtv.org/wiki/index.php/DVB_USB>
-
-         Say Y if you own a USB DVB device.
-
-config DVB_USB_DEBUG
-       bool "Enable extended debug support for all DVB-USB devices"
-       depends on DVB_USB
-       help
-         Say Y if you want to enable debugging. See modinfo dvb-usb (and the
-         appropriate drivers) for debug levels.
-
-config DVB_USB_A800
-       tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
-       depends on DVB_USB
-       select DVB_DIB3000MC
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
-
-config DVB_USB_DIBUSB_MB
-       tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_DIB3000MB
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
-         DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
-
-         For an up-to-date list of devices supported by this driver, have a look
-         on the Linux-DVB Wiki at www.linuxtv.org.
-
-         Say Y if you own such a device and want to use it. You should build it as
-         a module.
-
-config DVB_USB_DIBUSB_MB_FAULTY
-       bool "Support faulty USB IDs"
-       depends on DVB_USB_DIBUSB_MB
-       help
-         Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
-
-config DVB_USB_DIBUSB_MC
-       tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
-       depends on DVB_USB
-       select DVB_DIB3000MC
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Support for USB2.0 DVB-T receivers based on reference designs made by
-         DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
-
-         For an up-to-date list of devices supported by this driver, have a look
-         on the Linux-DVB Wiki at www.linuxtv.org.
-
-         Say Y if you own such a device and want to use it. You should build it as
-         a module.
-
-config DVB_USB_DIB0700
-       tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
-       depends on DVB_USB
-       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-       select DVB_DIB7000M if !DVB_FE_CUSTOMISE
-       select DVB_DIB8000 if !DVB_FE_CUSTOMISE
-       select DVB_DIB3000MC if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_DIB0090 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MT2266 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-       help
-         Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
-         USB bridge is also present in devices having the DiB7700 DVB-T-USB
-         silicon. This chip can be found in devices offered by Hauppauge,
-         Avermedia and other big and small companies.
-
-         For an up-to-date list of devices supported by this driver, have a look
-         on the LinuxTV Wiki at www.linuxtv.org.
-
-         Say Y if you own such a device and want to use it. You should build it as
-         a module.
-
-config DVB_USB_UMT_010
-       tristate "HanfTek UMT-010 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_DIB3000MC
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
-
-config DVB_USB_CXUSB
-       tristate "Conexant USB2.0 hybrid reference design support"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_CX22702 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-       select DVB_TUNER_DIB0070 if !DVB_FE_CUSTOMISE
-       select DVB_ATBM8830 if !DVB_FE_CUSTOMISE
-       select DVB_LGS8GXX if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MAX2165 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Conexant USB2.0 hybrid reference design.
-         Currently, only DVB and ATSC modes are supported, analog mode
-         shall be added in the future. Devices that require this module:
-
-         Medion MD95700 hybrid USB2.0 device.
-         DViCO FusionHDTV (Bluebird) USB2.0 devices
-
-config DVB_USB_M920X
-       tristate "Uli m920x DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
-         Currently, only devices with a product id of
-         "DTV USB MINI" (in cold state) are supported.
-         Firmware required.
-
-config DVB_USB_GL861
-       tristate "Genesys Logic GL861 USB2.0 support"
-       depends on DVB_USB
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
-         receiver with USB ID 0db0:5581.
-
-config DVB_USB_AU6610
-       tristate "Alcor Micro AU6610 USB2.0 support"
-       depends on DVB_USB
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
-
-config DVB_USB_DIGITV
-       tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_NXT6000 if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
-
-config DVB_USB_VP7045
-       tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
-       depends on DVB_USB
-       help
-         Say Y here to support the
-
-           TwinhanDTV Alpha (stick) (VP-7045),
-               TwinhanDTV MagicBox II (VP-7046),
-               DigitalNow TinyUSB 2 DVB-t,
-               DigitalRise USB 2.0 Ter (Beetle) and
-               TYPHOON DVB-T USB DRIVE
-
-         DVB-T USB2.0 receivers.
-
-config DVB_USB_VP702X
-       tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
-       depends on DVB_USB
-       help
-         Say Y here to support the
-
-           TwinhanDTV StarBox,
-               DigitalRise USB Starbox and
-               TYPHOON DVB-S USB 2.0 BOX
-
-         DVB-S USB2.0 receivers.
-
-config DVB_USB_GP8PSK
-       tristate "GENPIX 8PSK->USB module support"
-       depends on DVB_USB
-       help
-         Say Y here to support the
-           GENPIX 8psk module
-
-         DVB-S USB2.0 receivers.
-
-config DVB_USB_NOVA_T_USB2
-       tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_DIB3000MC
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
-
-config DVB_USB_TTUSB2
-       tristate "Pinnacle 400e DVB-S USB2.0 support"
-       depends on DVB_USB
-       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
-         firmware protocol used by this module is similar to the one used by the
-         old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
-
-config DVB_USB_DTT200U
-       tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
-       depends on DVB_USB
-       help
-         Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
-
-         The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
-
-         The WT-220U and its clones are pen-sized.
-
-config DVB_USB_OPERA1
-       tristate "Opera1 DVB-S USB2.0 receiver"
-       depends on DVB_USB
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the Opera DVB-S USB2.0 receiver.
-
-config DVB_USB_AF9005
-       tristate "Afatech AF9005 DVB-T USB1.1 support"
-       depends on DVB_USB && EXPERIMENTAL
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
-         and the TerraTec Cinergy T USB XE (Rev.1)
-
-config DVB_USB_AF9005_REMOTE
-       tristate "Afatech AF9005 default remote control support"
-       depends on DVB_USB_AF9005
-       help
-         Say Y here to support the default remote control decoding for the
-         Afatech AF9005 based receiver.
-
-config DVB_USB_PCTV452E
-       tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
-       depends on DVB_USB
-       select TTPCI_EEPROM
-       select DVB_LNBP22 if !DVB_FE_CUSTOMISE
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       help
-         Support for external USB adapter designed by Pinnacle,
-         shipped under the brand name 'PCTV HDTV Pro USB'.
-         Also supports TT Connect S2-3600/3650 cards.
-         Say Y if you own such a device and want to use it.
-
-config DVB_USB_DW2102
-       tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_STB6000 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_SI21XX if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select DVB_MT312 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10039 if !DVB_FE_CUSTOMISE
-       select DVB_DS3000 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
-         receivers.
-
-config DVB_USB_CINERGY_T2
-       tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
-       depends on DVB_USB
-       help
-         Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
-
-         Say Y if you own such a device and want to use it.
-
-config DVB_USB_ANYSEE
-       tristate "Anysee DVB-T/C USB2.0 support"
-       depends on DVB_USB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18212 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6423 if !DVB_FE_CUSTOMISE
-       select DVB_CXD2820R if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the Anysee E30, Anysee E30 Plus or
-         Anysee E30 C Plus DVB USB2.0 receiver.
-
-config DVB_USB_DTV5100
-       tristate "AME DTV-5100 USB2.0 DVB-T support"
-       depends on DVB_USB
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
-
-config DVB_USB_AF9015
-       tristate "Afatech AF9015 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_AF9013
-       select DVB_PLL              if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2060   if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_QT1010   if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
-
-config DVB_USB_CE6230
-       tristate "Intel CE6230 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_ZL10353
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver
-
-config DVB_USB_FRIIO
-       tristate "Friio ISDB-T USB2.0 Receiver support"
-       depends on DVB_USB
-       help
-         Say Y here to support the Japanese DTV receiver Friio.
-
-config DVB_USB_EC168
-       tristate "E3C EC168 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_EC100
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
-
-config DVB_USB_AZ6007
-       tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support"
-       depends on DVB_USB
-       select DVB_DRXK if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2063 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support theAfatech AF9005 based DVB-T/DVB-C receivers.
-
-config DVB_USB_AZ6027
-       tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
-       depends on DVB_USB
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the AZ6027 device
-
-config DVB_USB_LME2510
-       tristate "LME DM04/QQBOX DVB-S USB2.0 support"
-       depends on DVB_USB
-       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-       select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_IX2505V if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_M88RS2000 if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the LME DM04/QQBOX DVB-S USB2.0 .
-
-config DVB_USB_TECHNISAT_USB2
-       tristate "Technisat DVB-S/S2 USB2.0 support"
-       depends on DVB_USB
-       select DVB_STV090x if !DVB_FE_CUSTOMISE
-       select DVB_STV6110x if !DVB_FE_CUSTOMISE
-       help
-         Say Y here to support the Technisat USB2 DVB-S/S2 device
-
-config DVB_USB_IT913X
-       tristate "it913x driver"
-       depends on DVB_USB
-       select DVB_IT913X_FE
-       help
-         Say Y here to support the it913x device
-
-config DVB_USB_MXL111SF
-       tristate "MxL111SF DTV USB2.0 support"
-       depends on DVB_USB
-       select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-       select DVB_LG2160 if !DVB_FE_CUSTOMISE
-       select VIDEO_TVEEPROM
-       help
-         Say Y here to support the MxL111SF USB2.0 DTV receiver.
-
-config DVB_USB_RTL28XXU
-       tristate "Realtek RTL28xxU DVB USB support"
-       depends on DVB_USB && EXPERIMENTAL
-       select DVB_RTL2830
-       select DVB_RTL2832
-       select MEDIA_TUNER_QT1010 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MT2060 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_FC0012 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_FC0013 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Realtek RTL28xxU DVB USB receiver.
-
-config DVB_USB_AF9035
-       tristate "Afatech AF9035 DVB-T USB2.0 support"
-       depends on DVB_USB
-       select DVB_AF9033
-       select MEDIA_TUNER_TUA9001 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_FC0011 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18218 if !MEDIA_TUNER_CUSTOMISE
-       help
-         Say Y here to support the Afatech AF9035 based DVB USB receiver.
-
diff --git a/drivers/media/dvb/dvb-usb/Makefile b/drivers/media/dvb/dvb-usb/Makefile
deleted file mode 100644 (file)
index b667ac3..0000000
+++ /dev/null
@@ -1,121 +0,0 @@
-dvb-usb-objs = dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o
-obj-$(CONFIG_DVB_USB) += dvb-usb.o
-
-dvb-usb-vp7045-objs = vp7045.o vp7045-fe.o
-obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
-
-dvb-usb-vp702x-objs = vp702x.o vp702x-fe.o
-obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
-
-dvb-usb-gp8psk-objs = gp8psk.o gp8psk-fe.o
-obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
-
-dvb-usb-dtt200u-objs = dtt200u.o dtt200u-fe.o
-obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
-
-dvb-usb-dibusb-common-objs = dibusb-common.o
-
-dvb-usb-a800-objs = a800.o
-obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
-
-dvb-usb-dibusb-mb-objs = dibusb-mb.o
-obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
-
-dvb-usb-dibusb-mc-objs = dibusb-mc.o
-obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
-
-dvb-usb-nova-t-usb2-objs = nova-t-usb2.o
-obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
-
-dvb-usb-umt-010-objs = umt-010.o
-obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
-
-dvb-usb-m920x-objs = m920x.o
-obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o
-
-dvb-usb-gl861-objs = gl861.o
-obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o
-
-dvb-usb-au6610-objs = au6610.o
-obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o
-
-dvb-usb-digitv-objs = digitv.o
-obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
-
-dvb-usb-cxusb-objs = cxusb.o
-obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
-
-dvb-usb-ttusb2-objs = ttusb2.o
-obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
-
-dvb-usb-dib0700-objs = dib0700_core.o dib0700_devices.o
-obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
-
-dvb-usb-opera-objs = opera1.o
-obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
-
-dvb-usb-af9005-objs = af9005.o af9005-fe.o
-obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
-
-dvb-usb-af9005-remote-objs = af9005-remote.o
-obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
-
-dvb-usb-anysee-objs = anysee.o
-obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
-
-dvb-usb-pctv452e-objs = pctv452e.o
-obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
-
-dvb-usb-dw2102-objs = dw2102.o
-obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
-
-dvb-usb-dtv5100-objs = dtv5100.o
-obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
-
-dvb-usb-af9015-objs = af9015.o
-obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
-
-dvb-usb-cinergyT2-objs = cinergyT2-core.o cinergyT2-fe.o
-obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
-
-dvb-usb-ce6230-objs = ce6230.o
-obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o
-
-dvb-usb-friio-objs = friio.o friio-fe.o
-obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
-
-dvb-usb-ec168-objs = ec168.o
-obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
-
-dvb-usb-az6007-objs = az6007.o
-obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o
-
-dvb-usb-az6027-objs = az6027.o
-obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
-
-dvb-usb-lmedm04-objs = lmedm04.o
-obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
-
-dvb-usb-technisat-usb2-objs = technisat-usb2.o
-obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
-
-dvb-usb-it913x-objs := it913x.o
-obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
-
-dvb-usb-mxl111sf-objs = mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o mxl111sf-gpio.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
-obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
-
-dvb-usb-rtl28xxu-objs = rtl28xxu.o
-obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
-
-dvb-usb-af9035-objs = af9035.o
-obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends/
-# due to tuner-xc3028
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/ttpci
-
diff --git a/drivers/media/dvb/dvb-usb/af9015.c b/drivers/media/dvb/dvb-usb/af9015.c
deleted file mode 100644 (file)
index 677fed7..0000000
+++ /dev/null
@@ -1,1952 +0,0 @@
-/*
- * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
- *
- * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
- *
- * Thanks to Afatech who kindly provided information.
- *
- *    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/hash.h>
-#include <linux/slab.h>
-
-#include "af9015.h"
-#include "af9013.h"
-#include "mt2060.h"
-#include "qt1010.h"
-#include "tda18271.h"
-#include "mxl5005s.h"
-#include "mc44s803.h"
-#include "tda18218.h"
-#include "mxl5007t.h"
-
-static int dvb_usb_af9015_debug;
-module_param_named(debug, dvb_usb_af9015_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-static int dvb_usb_af9015_remote;
-module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
-MODULE_PARM_DESC(remote, "select remote");
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-static DEFINE_MUTEX(af9015_usb_mutex);
-
-static struct af9015_config af9015_config;
-static struct dvb_usb_device_properties af9015_properties[3];
-static int af9015_properties_count = ARRAY_SIZE(af9015_properties);
-
-static struct af9013_config af9015_af9013_config[] = {
-       {
-               .i2c_addr = AF9015_I2C_DEMOD,
-               .ts_mode = AF9013_TS_USB,
-               .api_version = { 0, 1, 9, 0 },
-               .gpio[0] = AF9013_GPIO_HI,
-               .gpio[3] = AF9013_GPIO_TUNER_ON,
-
-       }, {
-               .ts_mode = AF9013_TS_SERIAL,
-               .api_version = { 0, 1, 9, 0 },
-               .gpio[0] = AF9013_GPIO_TUNER_ON,
-               .gpio[1] = AF9013_GPIO_LO,
-       }
-};
-
-static int af9015_rw_udev(struct usb_device *udev, struct req_t *req)
-{
-#define BUF_LEN 63
-#define REQ_HDR_LEN 8 /* send header size */
-#define ACK_HDR_LEN 2 /* rece header size */
-       int act_len, ret;
-       u8 buf[BUF_LEN];
-       u8 write = 1;
-       u8 msg_len = REQ_HDR_LEN;
-       static u8 seq; /* packet sequence number */
-
-       if (mutex_lock_interruptible(&af9015_usb_mutex) < 0)
-               return -EAGAIN;
-
-       buf[0] = req->cmd;
-       buf[1] = seq++;
-       buf[2] = req->i2c_addr;
-       buf[3] = req->addr >> 8;
-       buf[4] = req->addr & 0xff;
-       buf[5] = req->mbox;
-       buf[6] = req->addr_len;
-       buf[7] = req->data_len;
-
-       switch (req->cmd) {
-       case GET_CONFIG:
-       case READ_MEMORY:
-       case RECONNECT_USB:
-               write = 0;
-               break;
-       case READ_I2C:
-               write = 0;
-               buf[2] |= 0x01; /* set I2C direction */
-       case WRITE_I2C:
-               buf[0] = READ_WRITE_I2C;
-               break;
-       case WRITE_MEMORY:
-               if (((req->addr & 0xff00) == 0xff00) ||
-                   ((req->addr & 0xff00) == 0xae00))
-                       buf[0] = WRITE_VIRTUAL_MEMORY;
-       case WRITE_VIRTUAL_MEMORY:
-       case COPY_FIRMWARE:
-       case DOWNLOAD_FIRMWARE:
-       case BOOT:
-               break;
-       default:
-               err("unknown command:%d", req->cmd);
-               ret = -1;
-               goto error_unlock;
-       }
-
-       /* buffer overflow check */
-       if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) ||
-               (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
-               err("too much data; cmd:%d len:%d", req->cmd, req->data_len);
-               ret = -EINVAL;
-               goto error_unlock;
-       }
-
-       /* write requested */
-       if (write) {
-               memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len);
-               msg_len += req->data_len;
-       }
-
-       deb_xfer(">>> ");
-       debug_dump(buf, msg_len, deb_xfer);
-
-       /* send req */
-       ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
-               &act_len, AF9015_USB_TIMEOUT);
-       if (ret)
-               err("bulk message failed:%d (%d/%d)", ret, msg_len, act_len);
-       else
-               if (act_len != msg_len)
-                       ret = -1; /* all data is not send */
-       if (ret)
-               goto error_unlock;
-
-       /* no ack for those packets */
-       if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
-               goto exit_unlock;
-
-       /* write receives seq + status = 2 bytes
-          read receives seq + status + data = 2 + N bytes */
-       msg_len = ACK_HDR_LEN;
-       if (!write)
-               msg_len += req->data_len;
-
-       ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
-               &act_len, AF9015_USB_TIMEOUT);
-       if (ret) {
-               err("recv bulk message failed:%d", ret);
-               ret = -1;
-               goto error_unlock;
-       }
-
-       deb_xfer("<<< ");
-       debug_dump(buf, act_len, deb_xfer);
-
-       /* check status */
-       if (buf[1]) {
-               err("command failed:%d", buf[1]);
-               ret = -1;
-               goto error_unlock;
-       }
-
-       /* read request, copy returned data to return buf */
-       if (!write)
-               memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len);
-
-error_unlock:
-exit_unlock:
-       mutex_unlock(&af9015_usb_mutex);
-
-       return ret;
-}
-
-static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
-{
-       return af9015_rw_udev(d->udev, req);
-}
-
-static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
-       u8 len)
-{
-       struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-               val};
-       return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
-{
-       return af9015_write_regs(d, addr, &val, 1);
-}
-
-static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len)
-{
-       struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
-               val};
-       return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
-{
-       return af9015_read_regs(d, addr, val, 1);
-}
-
-static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-       u8 val)
-{
-       struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
-
-       if (addr == af9015_af9013_config[0].i2c_addr ||
-           addr == af9015_af9013_config[1].i2c_addr)
-               req.addr_len = 3;
-
-       return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
-       u8 *val)
-{
-       struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
-
-       if (addr == af9015_af9013_config[0].i2c_addr ||
-           addr == af9015_af9013_config[1].i2c_addr)
-               req.addr_len = 3;
-
-       return af9015_ctrl_msg(d, &req);
-}
-
-static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-       int num)
-{
-       struct dvb_usb_device *d = i2c_get_adapdata(adap);
-       int ret = 0, i = 0;
-       u16 addr;
-       u8 uninitialized_var(mbox), addr_len;
-       struct req_t req;
-
-/*
-The bus lock is needed because there is two tuners both using same I2C-address.
-Due to that the only way to select correct tuner is use demodulator I2C-gate.
-
-................................................
-. AF9015 includes integrated AF9013 demodulator.
-. ____________                   ____________  .                ____________
-.|     uC     |                 |   demod    | .               |    tuner   |
-.|------------|                 |------------| .               |------------|
-.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |
-.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |
-.|            |  |              | addr 0x38  | .               |  addr 0xc6 |
-.|____________|  |              |____________| .               |____________|
-.................|..............................
-                |               ____________                   ____________
-                |              |   demod    |                 |    tuner   |
-                |              |------------|                 |------------|
-                |              |   AF9013   |                 |   MXL5003  |
-                +----I2C-------|-----/ -----|-------I2C-------|            |
-                               | addr 0x3a  |                 |  addr 0xc6 |
-                               |____________|                 |____________|
-*/
-       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
-               return -EAGAIN;
-
-       while (i < num) {
-               if (msg[i].addr == af9015_af9013_config[0].i2c_addr ||
-                   msg[i].addr == af9015_af9013_config[1].i2c_addr) {
-                       addr = msg[i].buf[0] << 8;
-                       addr += msg[i].buf[1];
-                       mbox = msg[i].buf[2];
-                       addr_len = 3;
-               } else {
-                       addr = msg[i].buf[0];
-                       addr_len = 1;
-                       /* mbox is don't care in that case */
-               }
-
-               if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
-                       if (msg[i].len > 3 || msg[i+1].len > 61) {
-                               ret = -EOPNOTSUPP;
-                               goto error;
-                       }
-                       if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
-                               req.cmd = READ_MEMORY;
-                       else
-                               req.cmd = READ_I2C;
-                       req.i2c_addr = msg[i].addr;
-                       req.addr = addr;
-                       req.mbox = mbox;
-                       req.addr_len = addr_len;
-                       req.data_len = msg[i+1].len;
-                       req.data = &msg[i+1].buf[0];
-                       ret = af9015_ctrl_msg(d, &req);
-                       i += 2;
-               } else if (msg[i].flags & I2C_M_RD) {
-                       if (msg[i].len > 61) {
-                               ret = -EOPNOTSUPP;
-                               goto error;
-                       }
-                       if (msg[i].addr ==
-                               af9015_af9013_config[0].i2c_addr) {
-                               ret = -EINVAL;
-                               goto error;
-                       }
-                       req.cmd = READ_I2C;
-                       req.i2c_addr = msg[i].addr;
-                       req.addr = addr;
-                       req.mbox = mbox;
-                       req.addr_len = addr_len;
-                       req.data_len = msg[i].len;
-                       req.data = &msg[i].buf[0];
-                       ret = af9015_ctrl_msg(d, &req);
-                       i += 1;
-               } else {
-                       if (msg[i].len > 21) {
-                               ret = -EOPNOTSUPP;
-                               goto error;
-                       }
-                       if (msg[i].addr == af9015_af9013_config[0].i2c_addr)
-                               req.cmd = WRITE_MEMORY;
-                       else
-                               req.cmd = WRITE_I2C;
-                       req.i2c_addr = msg[i].addr;
-                       req.addr = addr;
-                       req.mbox = mbox;
-                       req.addr_len = addr_len;
-                       req.data_len = msg[i].len-addr_len;
-                       req.data = &msg[i].buf[addr_len];
-                       ret = af9015_ctrl_msg(d, &req);
-                       i += 1;
-               }
-               if (ret)
-                       goto error;
-
-       }
-       ret = i;
-
-error:
-       mutex_unlock(&d->i2c_mutex);
-
-       return ret;
-}
-
-static u32 af9015_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm af9015_i2c_algo = {
-       .master_xfer = af9015_i2c_xfer,
-       .functionality = af9015_i2c_func,
-};
-
-static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
-{
-       int ret;
-       u8 val, mask = 0x01;
-
-       ret = af9015_read_reg(d, addr, &val);
-       if (ret)
-               return ret;
-
-       mask <<= bit;
-       if (op) {
-               /* set bit */
-               val |= mask;
-       } else {
-               /* clear bit */
-               mask ^= 0xff;
-               val &= mask;
-       }
-
-       return af9015_write_reg(d, addr, val);
-}
-
-static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-       return af9015_do_reg_bit(d, addr, bit, 1);
-}
-
-static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
-{
-       return af9015_do_reg_bit(d, addr, bit, 0);
-}
-
-static int af9015_init_endpoint(struct dvb_usb_device *d)
-{
-       int ret;
-       u16 frame_size;
-       u8  packet_size;
-       deb_info("%s: USB speed:%d\n", __func__, d->udev->speed);
-
-       /* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0.
-          We use smaller - about 1/4 from the original, 5 and 87. */
-#define TS_PACKET_SIZE            188
-
-#define TS_USB20_PACKET_COUNT      87
-#define TS_USB20_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)
-
-#define TS_USB11_PACKET_COUNT       5
-#define TS_USB11_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)
-
-#define TS_USB20_MAX_PACKET_SIZE  512
-#define TS_USB11_MAX_PACKET_SIZE   64
-
-       if (d->udev->speed == USB_SPEED_FULL) {
-               frame_size = TS_USB11_FRAME_SIZE/4;
-               packet_size = TS_USB11_MAX_PACKET_SIZE/4;
-       } else {
-               frame_size = TS_USB20_FRAME_SIZE/4;
-               packet_size = TS_USB20_MAX_PACKET_SIZE/4;
-       }
-
-       ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */
-       if (ret)
-               goto error;
-       ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */
-       if (ret)
-               goto error;
-       ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */
-       if (ret)
-               goto error;
-       ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */
-       if (ret)
-               goto error;
-       ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */
-       if (ret)
-               goto error;
-       if (af9015_config.dual_mode) {
-               ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */
-               if (ret)
-                       goto error;
-       }
-       ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */
-       if (ret)
-               goto error;
-       if (af9015_config.dual_mode) {
-               ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */
-               if (ret)
-                       goto error;
-       }
-       /* EP4 xfer length */
-       ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);
-       if (ret)
-               goto error;
-       ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);
-       if (ret)
-               goto error;
-       /* EP5 xfer length */
-       ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);
-       if (ret)
-               goto error;
-       ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);
-       if (ret)
-               goto error;
-       ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */
-       if (ret)
-               goto error;
-       ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */
-       if (ret)
-               goto error;
-       ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */
-       if (ret)
-               goto error;
-       if (af9015_config.dual_mode) {
-               ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */
-               if (ret)
-                       goto error;
-       }
-
-       /* enable / disable mp2if2 */
-       if (af9015_config.dual_mode)
-               ret = af9015_set_reg_bit(d, 0xd50b, 0);
-       else
-               ret = af9015_clear_reg_bit(d, 0xd50b, 0);
-
-error:
-       if (ret)
-               err("endpoint init failed:%d", ret);
-       return ret;
-}
-
-static int af9015_copy_firmware(struct dvb_usb_device *d)
-{
-       int ret;
-       u8 fw_params[4];
-       u8 val, i;
-       struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
-               fw_params };
-       deb_info("%s:\n", __func__);
-
-       fw_params[0] = af9015_config.firmware_size >> 8;
-       fw_params[1] = af9015_config.firmware_size & 0xff;
-       fw_params[2] = af9015_config.firmware_checksum >> 8;
-       fw_params[3] = af9015_config.firmware_checksum & 0xff;
-
-       /* wait 2nd demodulator ready */
-       msleep(100);
-
-       ret = af9015_read_reg_i2c(d,
-               af9015_af9013_config[1].i2c_addr, 0x98be, &val);
-       if (ret)
-               goto error;
-       else
-               deb_info("%s: firmware status:%02x\n", __func__, val);
-
-       if (val == 0x0c) /* fw is running, no need for download */
-               goto exit;
-
-       /* set I2C master clock to fast (to speed up firmware copy) */
-       ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
-       if (ret)
-               goto error;
-
-       msleep(50);
-
-       /* copy firmware */
-       ret = af9015_ctrl_msg(d, &req);
-       if (ret)
-               err("firmware copy cmd failed:%d", ret);
-       deb_info("%s: firmware copy done\n", __func__);
-
-       /* set I2C master clock back to normal */
-       ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
-       if (ret)
-               goto error;
-
-       /* request boot firmware */
-       ret = af9015_write_reg_i2c(d, af9015_af9013_config[1].i2c_addr,
-               0xe205, 1);
-       deb_info("%s: firmware boot cmd status:%d\n", __func__, ret);
-       if (ret)
-               goto error;
-
-       for (i = 0; i < 15; i++) {
-               msleep(100);
-
-               /* check firmware status */
-               ret = af9015_read_reg_i2c(d,
-                       af9015_af9013_config[1].i2c_addr, 0x98be, &val);
-               deb_info("%s: firmware status cmd status:%d fw status:%02x\n",
-                       __func__, ret, val);
-               if (ret)
-                       goto error;
-
-               if (val == 0x0c || val == 0x04) /* success or fail */
-                       break;
-       }
-
-       if (val == 0x04) {
-               err("firmware did not run");
-               ret = -1;
-       } else if (val != 0x0c) {
-               err("firmware boot timeout");
-               ret = -1;
-       }
-
-error:
-exit:
-       return ret;
-}
-
-/* hash (and dump) eeprom */
-static int af9015_eeprom_hash(struct usb_device *udev)
-{
-       static const unsigned int eeprom_size = 256;
-       unsigned int reg;
-       int ret;
-       u8 val, *eeprom;
-       struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
-
-       eeprom = kmalloc(eeprom_size, GFP_KERNEL);
-       if (eeprom == NULL)
-               return -ENOMEM;
-
-       for (reg = 0; reg < eeprom_size; reg++) {
-               req.addr = reg;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto free;
-               eeprom[reg] = val;
-       }
-
-       if (dvb_usb_af9015_debug & 0x01)
-               print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, eeprom,
-                               eeprom_size);
-
-       BUG_ON(eeprom_size % 4);
-
-       af9015_config.eeprom_sum = 0;
-       for (reg = 0; reg < eeprom_size / sizeof(u32); reg++) {
-               af9015_config.eeprom_sum *= GOLDEN_RATIO_PRIME_32;
-               af9015_config.eeprom_sum += le32_to_cpu(((u32 *)eeprom)[reg]);
-       }
-
-       deb_info("%s: eeprom sum=%.8x\n", __func__, af9015_config.eeprom_sum);
-
-       ret = 0;
-free:
-       kfree(eeprom);
-       return ret;
-}
-
-static int af9015_init(struct dvb_usb_device *d)
-{
-       int ret;
-       deb_info("%s:\n", __func__);
-
-       /* init RC canary */
-       ret = af9015_write_reg(d, 0x98e9, 0xff);
-       if (ret)
-               goto error;
-
-       ret = af9015_init_endpoint(d);
-       if (ret)
-               goto error;
-
-error:
-       return ret;
-}
-
-static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       int ret;
-       deb_info("%s: onoff:%d\n", __func__, onoff);
-
-       if (onoff)
-               ret = af9015_set_reg_bit(adap->dev, 0xd503, 0);
-       else
-               ret = af9015_clear_reg_bit(adap->dev, 0xd503, 0);
-
-       return ret;
-}
-
-static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
-       int onoff)
-{
-       int ret;
-       u8 idx;
-
-       deb_info("%s: set pid filter, index %d, pid %x, onoff %d\n",
-               __func__, index, pid, onoff);
-
-       ret = af9015_write_reg(adap->dev, 0xd505, (pid & 0xff));
-       if (ret)
-               goto error;
-
-       ret = af9015_write_reg(adap->dev, 0xd506, (pid >> 8));
-       if (ret)
-               goto error;
-
-       idx = ((index & 0x1f) | (1 << 5));
-       ret = af9015_write_reg(adap->dev, 0xd504, idx);
-
-error:
-       return ret;
-}
-
-static int af9015_download_firmware(struct usb_device *udev,
-       const struct firmware *fw)
-{
-       int i, len, remaining, ret;
-       struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
-       u16 checksum = 0;
-
-       deb_info("%s:\n", __func__);
-
-       /* calc checksum */
-       for (i = 0; i < fw->size; i++)
-               checksum += fw->data[i];
-
-       af9015_config.firmware_size = fw->size;
-       af9015_config.firmware_checksum = checksum;
-
-       #define FW_ADDR 0x5100 /* firmware start address */
-       #define LEN_MAX 55 /* max packet size */
-       for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
-               len = remaining;
-               if (len > LEN_MAX)
-                       len = LEN_MAX;
-
-               req.data_len = len;
-               req.data = (u8 *) &fw->data[fw->size - remaining];
-               req.addr = FW_ADDR + fw->size - remaining;
-
-               ret = af9015_rw_udev(udev, &req);
-               if (ret) {
-                       err("firmware download failed:%d", ret);
-                       goto error;
-               }
-       }
-
-       /* firmware loaded, request boot */
-       req.cmd = BOOT;
-       ret = af9015_rw_udev(udev, &req);
-       if (ret) {
-               err("firmware boot failed:%d", ret);
-               goto error;
-       }
-
-error:
-       return ret;
-}
-
-struct af9015_rc_setup {
-       unsigned int id;
-       char *rc_codes;
-};
-
-static char *af9015_rc_setup_match(unsigned int id,
-       const struct af9015_rc_setup *table)
-{
-       for (; table->rc_codes; table++)
-               if (table->id == id)
-                       return table->rc_codes;
-       return NULL;
-}
-
-static const struct af9015_rc_setup af9015_rc_setup_modparam[] = {
-       { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M },
-       { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II },
-       { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND },
-       { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE },
-       { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS },
-       { }
-};
-
-static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
-       { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
-       { 0xa3703d00, RC_MAP_ALINK_DTU_M },
-       { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
-       { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
-       { }
-};
-
-static const struct af9015_rc_setup af9015_rc_setup_usbids[] = {
-       { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_RC,
-               RC_MAP_TERRATEC_SLIM_2 },
-       { (USB_VID_TERRATEC << 16) | USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
-               RC_MAP_TERRATEC_SLIM },
-       { (USB_VID_VISIONPLUS << 16) | USB_PID_AZUREWAVE_AD_TU700,
-               RC_MAP_AZUREWAVE_AD_TU700 },
-       { (USB_VID_VISIONPLUS << 16) | USB_PID_TINYTWIN,
-               RC_MAP_AZUREWAVE_AD_TU700 },
-       { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGI_VOX_MINI_III,
-               RC_MAP_MSI_DIGIVOX_III },
-       { (USB_VID_MSI_2 << 16) | USB_PID_MSI_DIGIVOX_DUO,
-               RC_MAP_MSI_DIGIVOX_III },
-       { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV_DONGLE_GOLD,
-               RC_MAP_LEADTEK_Y04G0051 },
-       { (USB_VID_LEADTEK << 16) | USB_PID_WINFAST_DTV2000DS,
-               RC_MAP_LEADTEK_Y04G0051 },
-       { (USB_VID_AVERMEDIA << 16) | USB_PID_AVERMEDIA_VOLAR_X,
-               RC_MAP_AVERMEDIA_M135A },
-       { (USB_VID_AFATECH << 16) | USB_PID_TREKSTOR_DVBT,
-               RC_MAP_TREKSTOR },
-       { (USB_VID_KWORLD_2 << 16) | USB_PID_TINYTWIN_2,
-               RC_MAP_DIGITALNOW_TINYTWIN },
-       { (USB_VID_GTEK << 16) | USB_PID_TINYTWIN_3,
-               RC_MAP_DIGITALNOW_TINYTWIN },
-       { (USB_VID_KWORLD_2 << 16) | USB_PID_SVEON_STV22,
-               RC_MAP_MSI_DIGIVOX_III },
-       { }
-};
-
-static void af9015_set_remote_config(struct usb_device *udev,
-               struct dvb_usb_device_properties *props)
-{
-       u16 vid = le16_to_cpu(udev->descriptor.idVendor);
-       u16 pid = le16_to_cpu(udev->descriptor.idProduct);
-
-       /* try to load remote based module param */
-       props->rc.core.rc_codes = af9015_rc_setup_match(
-               dvb_usb_af9015_remote, af9015_rc_setup_modparam);
-
-       /* try to load remote based eeprom hash */
-       if (!props->rc.core.rc_codes)
-               props->rc.core.rc_codes = af9015_rc_setup_match(
-                       af9015_config.eeprom_sum, af9015_rc_setup_hashes);
-
-       /* try to load remote based USB ID */
-       if (!props->rc.core.rc_codes)
-               props->rc.core.rc_codes = af9015_rc_setup_match(
-                       (vid << 16) | pid, af9015_rc_setup_usbids);
-
-       /* try to load remote based USB iManufacturer string */
-       if (!props->rc.core.rc_codes && vid == USB_VID_AFATECH) {
-               /* Check USB manufacturer and product strings and try
-                  to determine correct remote in case of chip vendor
-                  reference IDs are used.
-                  DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */
-               char manufacturer[10];
-               memset(manufacturer, 0, sizeof(manufacturer));
-               usb_string(udev, udev->descriptor.iManufacturer,
-                       manufacturer, sizeof(manufacturer));
-               if (!strcmp("MSI", manufacturer)) {
-                       /* iManufacturer 1 MSI
-                          iProduct      2 MSI K-VOX */
-                       props->rc.core.rc_codes = af9015_rc_setup_match(
-                               AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
-                               af9015_rc_setup_modparam);
-               }
-       }
-
-       /* finally load "empty" just for leaving IR receiver enabled */
-       if (!props->rc.core.rc_codes)
-               props->rc.core.rc_codes = RC_MAP_EMPTY;
-
-       return;
-}
-
-static int af9015_read_config(struct usb_device *udev)
-{
-       int ret;
-       u8 val, i, offset = 0;
-       struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
-
-       /* IR remote controller */
-       req.addr = AF9015_EEPROM_IR_MODE;
-       /* first message will timeout often due to possible hw bug */
-       for (i = 0; i < 4; i++) {
-               ret = af9015_rw_udev(udev, &req);
-               if (!ret)
-                       break;
-       }
-       if (ret)
-               goto error;
-
-       ret = af9015_eeprom_hash(udev);
-       if (ret)
-               goto error;
-
-       deb_info("%s: IR mode=%d\n", __func__, val);
-       for (i = 0; i < af9015_properties_count; i++) {
-               if (val == AF9015_IR_MODE_DISABLED)
-                       af9015_properties[i].rc.core.rc_codes = NULL;
-               else
-                       af9015_set_remote_config(udev, &af9015_properties[i]);
-       }
-
-       /* TS mode - one or two receivers */
-       req.addr = AF9015_EEPROM_TS_MODE;
-       ret = af9015_rw_udev(udev, &req);
-       if (ret)
-               goto error;
-       af9015_config.dual_mode = val;
-       deb_info("%s: TS mode=%d\n", __func__, af9015_config.dual_mode);
-
-       /* Set adapter0 buffer size according to USB port speed, adapter1 buffer
-          size can be static because it is enabled only USB2.0 */
-       for (i = 0; i < af9015_properties_count; i++) {
-               /* USB1.1 set smaller buffersize and disable 2nd adapter */
-               if (udev->speed == USB_SPEED_FULL) {
-                       af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
-                               = TS_USB11_FRAME_SIZE;
-                       /* disable 2nd adapter because we don't have
-                          PID-filters */
-                       af9015_config.dual_mode = 0;
-               } else {
-                       af9015_properties[i].adapter[0].fe[0].stream.u.bulk.buffersize
-                               = TS_USB20_FRAME_SIZE;
-               }
-       }
-
-       if (af9015_config.dual_mode) {
-               /* read 2nd demodulator I2C address */
-               req.addr = AF9015_EEPROM_DEMOD2_I2C;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-               af9015_af9013_config[1].i2c_addr = val;
-
-               /* enable 2nd adapter */
-               for (i = 0; i < af9015_properties_count; i++)
-                       af9015_properties[i].num_adapters = 2;
-
-       } else {
-                /* disable 2nd adapter */
-               for (i = 0; i < af9015_properties_count; i++)
-                       af9015_properties[i].num_adapters = 1;
-       }
-
-       for (i = 0; i < af9015_properties[0].num_adapters; i++) {
-               if (i == 1)
-                       offset = AF9015_EEPROM_OFFSET;
-               /* xtal */
-               req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-               switch (val) {
-               case 0:
-                       af9015_af9013_config[i].clock = 28800000;
-                       break;
-               case 1:
-                       af9015_af9013_config[i].clock = 20480000;
-                       break;
-               case 2:
-                       af9015_af9013_config[i].clock = 28000000;
-                       break;
-               case 3:
-                       af9015_af9013_config[i].clock = 25000000;
-                       break;
-               };
-               deb_info("%s: [%d] xtal=%d set clock=%d\n", __func__, i,
-                       val, af9015_af9013_config[i].clock);
-
-               /* IF frequency */
-               req.addr = AF9015_EEPROM_IF1H + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-
-               af9015_af9013_config[i].if_frequency = val << 8;
-
-               req.addr = AF9015_EEPROM_IF1L + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-
-               af9015_af9013_config[i].if_frequency += val;
-               af9015_af9013_config[i].if_frequency *= 1000;
-               deb_info("%s: [%d] IF frequency=%d\n", __func__, i,
-                       af9015_af9013_config[0].if_frequency);
-
-               /* MT2060 IF1 */
-               req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-               af9015_config.mt2060_if1[i] = val << 8;
-               req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-               af9015_config.mt2060_if1[i] += val;
-               deb_info("%s: [%d] MT2060 IF1=%d\n", __func__, i,
-                       af9015_config.mt2060_if1[i]);
-
-               /* tuner */
-               req.addr =  AF9015_EEPROM_TUNER_ID1 + offset;
-               ret = af9015_rw_udev(udev, &req);
-               if (ret)
-                       goto error;
-               switch (val) {
-               case AF9013_TUNER_ENV77H11D5:
-               case AF9013_TUNER_MT2060:
-               case AF9013_TUNER_QT1010:
-               case AF9013_TUNER_UNKNOWN:
-               case AF9013_TUNER_MT2060_2:
-               case AF9013_TUNER_TDA18271:
-               case AF9013_TUNER_QT1010A:
-               case AF9013_TUNER_TDA18218:
-                       af9015_af9013_config[i].spec_inv = 1;
-                       break;
-               case AF9013_TUNER_MXL5003D:
-               case AF9013_TUNER_MXL5005D:
-               case AF9013_TUNER_MXL5005R:
-               case AF9013_TUNER_MXL5007T:
-                       af9015_af9013_config[i].spec_inv = 0;
-                       break;
-               case AF9013_TUNER_MC44S803:
-                       af9015_af9013_config[i].gpio[1] = AF9013_GPIO_LO;
-                       af9015_af9013_config[i].spec_inv = 1;
-                       break;
-               default:
-                       warn("tuner id=%d not supported, please report!", val);
-                       return -ENODEV;
-               };
-
-               af9015_af9013_config[i].tuner = val;
-               deb_info("%s: [%d] tuner id=%d\n", __func__, i, val);
-       }
-
-error:
-       if (ret)
-               err("eeprom read failed=%d", ret);
-
-       /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
-          content :-( Override some wrong values here. Ditto for the
-          AVerTV Red HD+ (A850T) device. */
-       if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
-               ((le16_to_cpu(udev->descriptor.idProduct) ==
-                       USB_PID_AVERMEDIA_A850) ||
-               (le16_to_cpu(udev->descriptor.idProduct) ==
-                       USB_PID_AVERMEDIA_A850T))) {
-               deb_info("%s: AverMedia A850: overriding config\n", __func__);
-               /* disable dual mode */
-               af9015_config.dual_mode = 0;
-                /* disable 2nd adapter */
-               for (i = 0; i < af9015_properties_count; i++)
-                       af9015_properties[i].num_adapters = 1;
-
-               /* set correct IF */
-               af9015_af9013_config[0].if_frequency = 4570000;
-       }
-
-       return ret;
-}
-
-static int af9015_identify_state(struct usb_device *udev,
-                                struct dvb_usb_device_properties *props,
-                                struct dvb_usb_device_description **desc,
-                                int *cold)
-{
-       int ret;
-       u8 reply;
-       struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};
-
-       ret = af9015_rw_udev(udev, &req);
-       if (ret)
-               return ret;
-
-       deb_info("%s: reply:%02x\n", __func__, reply);
-       if (reply == 0x02)
-               *cold = 0;
-       else
-               *cold = 1;
-
-       return ret;
-}
-
-static int af9015_rc_query(struct dvb_usb_device *d)
-{
-       struct af9015_state *priv = d->priv;
-       int ret;
-       u8 buf[17];
-
-       /* read registers needed to detect remote controller code */
-       ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
-       if (ret)
-               goto error;
-
-       /* If any of these are non-zero, assume invalid data */
-       if (buf[1] || buf[2] || buf[3])
-               return ret;
-
-       /* Check for repeat of previous code */
-       if ((priv->rc_repeat != buf[6] || buf[0]) &&
-                                       !memcmp(&buf[12], priv->rc_last, 4)) {
-               deb_rc("%s: key repeated\n", __func__);
-               rc_keydown(d->rc_dev, priv->rc_keycode, 0);
-               priv->rc_repeat = buf[6];
-               return ret;
-       }
-
-       /* Only process key if canary killed */
-       if (buf[16] != 0xff && buf[0] != 0x01) {
-               deb_rc("%s: key pressed %02x %02x %02x %02x\n", __func__,
-                       buf[12], buf[13], buf[14], buf[15]);
-
-               /* Reset the canary */
-               ret = af9015_write_reg(d, 0x98e9, 0xff);
-               if (ret)
-                       goto error;
-
-               /* Remember this key */
-               memcpy(priv->rc_last, &buf[12], 4);
-               if (buf[14] == (u8) ~buf[15]) {
-                       if (buf[12] == (u8) ~buf[13]) {
-                               /* NEC */
-                               priv->rc_keycode = buf[12] << 8 | buf[14];
-                       } else {
-                               /* NEC extended*/
-                               priv->rc_keycode = buf[12] << 16 |
-                                       buf[13] << 8 | buf[14];
-                       }
-               } else {
-                       /* 32 bit NEC */
-                       priv->rc_keycode = buf[12] << 24 | buf[13] << 16 |
-                                       buf[14] << 8 | buf[15];
-               }
-               rc_keydown(d->rc_dev, priv->rc_keycode, 0);
-       } else {
-               deb_rc("%s: no key press\n", __func__);
-               /* Invalidate last keypress */
-               /* Not really needed, but helps with debug */
-               priv->rc_last[2] = priv->rc_last[3];
-       }
-
-       priv->rc_repeat = buf[6];
-
-error:
-       if (ret)
-               err("%s: failed:%d", __func__, ret);
-
-       return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_set_frontend(struct dvb_frontend *fe)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->set_frontend[adap->id](fe);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_read_status(struct dvb_frontend *fe,
-       fe_status_t *status)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->read_status[adap->id](fe, status);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_init(struct dvb_frontend *fe)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->init[adap->id](fe);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-/* override demod callbacks for resource locking */
-static int af9015_af9013_sleep(struct dvb_frontend *fe)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->sleep[adap->id](fe);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_init(struct dvb_frontend *fe)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->tuner_init[adap->id](fe);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-/* override tuner callbacks for resource locking */
-static int af9015_tuner_sleep(struct dvb_frontend *fe)
-{
-       int ret;
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct af9015_state *priv = adap->dev->priv;
-
-       if (mutex_lock_interruptible(&adap->dev->usb_mutex))
-               return -EAGAIN;
-
-       ret = priv->tuner_sleep[adap->id](fe);
-
-       mutex_unlock(&adap->dev->usb_mutex);
-
-       return ret;
-}
-
-
-static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       int ret;
-       struct af9015_state *state = adap->dev->priv;
-
-       if (adap->id == 1) {
-               /* copy firmware to 2nd demodulator */
-               if (af9015_config.dual_mode) {
-                       ret = af9015_copy_firmware(adap->dev);
-                       if (ret) {
-                               err("firmware copy to 2nd frontend " \
-                                       "failed, will disable it");
-                               af9015_config.dual_mode = 0;
-                               return -ENODEV;
-                       }
-               } else {
-                       return -ENODEV;
-               }
-       }
-
-       /* attach demodulator */
-       adap->fe_adap[0].fe = dvb_attach(af9013_attach,
-               &af9015_af9013_config[adap->id], &adap->dev->i2c_adap);
-
-       /*
-        * AF9015 firmware does not like if it gets interrupted by I2C adapter
-        * request on some critical phases. During normal operation I2C adapter
-        * is used only 2nd demodulator and tuner on dual tuner devices.
-        * Override demodulator callbacks and use mutex for limit access to
-        * those "critical" paths to keep AF9015 happy.
-        * Note: we abuse unused usb_mutex here.
-        */
-       if (adap->fe_adap[0].fe) {
-               state->set_frontend[adap->id] =
-                       adap->fe_adap[0].fe->ops.set_frontend;
-               adap->fe_adap[0].fe->ops.set_frontend =
-                       af9015_af9013_set_frontend;
-
-               state->read_status[adap->id] =
-                       adap->fe_adap[0].fe->ops.read_status;
-               adap->fe_adap[0].fe->ops.read_status =
-                       af9015_af9013_read_status;
-
-               state->init[adap->id] = adap->fe_adap[0].fe->ops.init;
-               adap->fe_adap[0].fe->ops.init = af9015_af9013_init;
-
-               state->sleep[adap->id] = adap->fe_adap[0].fe->ops.sleep;
-               adap->fe_adap[0].fe->ops.sleep = af9015_af9013_sleep;
-       }
-
-       return adap->fe_adap[0].fe == NULL ? -ENODEV : 0;
-}
-
-static struct mt2060_config af9015_mt2060_config = {
-       .i2c_address = 0xc0,
-       .clock_out = 0,
-};
-
-static struct qt1010_config af9015_qt1010_config = {
-       .i2c_address = 0xc4,
-};
-
-static struct tda18271_config af9015_tda18271_config = {
-       .gate = TDA18271_GATE_DIGITAL,
-       .small_i2c = TDA18271_16_BYTE_CHUNK_INIT,
-};
-
-static struct mxl5005s_config af9015_mxl5003_config = {
-       .i2c_address     = 0xc6,
-       .if_freq         = IF_FREQ_4570000HZ,
-       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-       .agc_mode        = MXL_SINGLE_AGC,
-       .tracking_filter = MXL_TF_DEFAULT,
-       .rssi_enable     = MXL_RSSI_ENABLE,
-       .cap_select      = MXL_CAP_SEL_ENABLE,
-       .div_out         = MXL_DIV_OUT_4,
-       .clock_out       = MXL_CLOCK_OUT_DISABLE,
-       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
-       .top             = MXL5005S_TOP_25P2,
-       .mod_mode        = MXL_DIGITAL_MODE,
-       .if_mode         = MXL_ZERO_IF,
-       .AgcMasterByte   = 0x00,
-};
-
-static struct mxl5005s_config af9015_mxl5005_config = {
-       .i2c_address     = 0xc6,
-       .if_freq         = IF_FREQ_4570000HZ,
-       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-       .agc_mode        = MXL_SINGLE_AGC,
-       .tracking_filter = MXL_TF_OFF,
-       .rssi_enable     = MXL_RSSI_ENABLE,
-       .cap_select      = MXL_CAP_SEL_ENABLE,
-       .div_out         = MXL_DIV_OUT_4,
-       .clock_out       = MXL_CLOCK_OUT_DISABLE,
-       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
-       .top             = MXL5005S_TOP_25P2,
-       .mod_mode        = MXL_DIGITAL_MODE,
-       .if_mode         = MXL_ZERO_IF,
-       .AgcMasterByte   = 0x00,
-};
-
-static struct mc44s803_config af9015_mc44s803_config = {
-       .i2c_address = 0xc0,
-       .dig_out = 1,
-};
-
-static struct tda18218_config af9015_tda18218_config = {
-       .i2c_address = 0xc0,
-       .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */
-};
-
-static struct mxl5007t_config af9015_mxl5007t_config = {
-       .xtal_freq_hz = MxL_XTAL_24_MHZ,
-       .if_freq_hz = MxL_IF_4_57_MHZ,
-};
-
-static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
-{
-       int ret;
-       struct af9015_state *state = adap->dev->priv;
-       deb_info("%s:\n", __func__);
-
-       switch (af9015_af9013_config[adap->id].tuner) {
-       case AF9013_TUNER_MT2060:
-       case AF9013_TUNER_MT2060_2:
-               ret = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap, &af9015_mt2060_config,
-                       af9015_config.mt2060_if1[adap->id])
-                       == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_QT1010:
-       case AF9013_TUNER_QT1010A:
-               ret = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       &af9015_qt1010_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_TDA18271:
-               ret = dvb_attach(tda18271_attach, adap->fe_adap[0].fe, 0xc0,
-                       &adap->dev->i2c_adap,
-                       &af9015_tda18271_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_TDA18218:
-               ret = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       &af9015_tda18218_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_MXL5003D:
-               ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_MXL5005D:
-       case AF9013_TUNER_MXL5005R:
-               ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_ENV77H11D5:
-               ret = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe, 0xc0,
-                       &adap->dev->i2c_adap,
-                       DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_MC44S803:
-               ret = dvb_attach(mc44s803_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       &af9015_mc44s803_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_MXL5007T:
-               ret = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap,
-                       0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
-               break;
-       case AF9013_TUNER_UNKNOWN:
-       default:
-               ret = -ENODEV;
-               err("Unknown tuner id:%d",
-                       af9015_af9013_config[adap->id].tuner);
-       }
-
-       if (adap->fe_adap[0].fe->ops.tuner_ops.init) {
-               state->tuner_init[adap->id] =
-                       adap->fe_adap[0].fe->ops.tuner_ops.init;
-               adap->fe_adap[0].fe->ops.tuner_ops.init = af9015_tuner_init;
-       }
-
-       if (adap->fe_adap[0].fe->ops.tuner_ops.sleep) {
-               state->tuner_sleep[adap->id] =
-                       adap->fe_adap[0].fe->ops.tuner_ops.sleep;
-               adap->fe_adap[0].fe->ops.tuner_ops.sleep = af9015_tuner_sleep;
-       }
-
-       return ret;
-}
-
-enum af9015_usb_table_entry {
-       AFATECH_9015,
-       AFATECH_9016,
-       WINFAST_DTV_GOLD,
-       PINNACLE_PCTV_71E,
-       KWORLD_PLUSTV_399U,
-       TINYTWIN,
-       AZUREWAVE_TU700,
-       TERRATEC_AF9015,
-       KWORLD_PLUSTV_PC160,
-       AVERTV_VOLAR_X,
-       XTENSIONS_380U,
-       MSI_DIGIVOX_DUO,
-       AVERTV_VOLAR_X_REV2,
-       TELESTAR_STARSTICK_2,
-       AVERMEDIA_A309_USB,
-       MSI_DIGIVOX_MINI_III,
-       KWORLD_E396,
-       KWORLD_E39B,
-       KWORLD_E395,
-       TREKSTOR_DVBT,
-       AVERTV_A850,
-       AVERTV_A805,
-       CONCEPTRONIC_CTVDIGRCU,
-       KWORLD_MC810,
-       GENIUS_TVGO_DVB_T03,
-       KWORLD_399U_2,
-       KWORLD_PC160_T,
-       SVEON_STV20,
-       TINYTWIN_2,
-       WINFAST_DTV2000DS,
-       KWORLD_UB383_T,
-       KWORLD_E39A,
-       AVERMEDIA_A815M,
-       CINERGY_T_STICK_RC,
-       CINERGY_T_DUAL_RC,
-       AVERTV_A850T,
-       TINYTWIN_3,
-       SVEON_STV22,
-};
-
-static struct usb_device_id af9015_usb_table[] = {
-       [AFATECH_9015] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015)},
-       [AFATECH_9016] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016)},
-       [WINFAST_DTV_GOLD] = {
-               USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD)},
-       [PINNACLE_PCTV_71E] = {
-               USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E)},
-       [KWORLD_PLUSTV_399U] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U)},
-       [TINYTWIN] = {
-               USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN)},
-       [AZUREWAVE_TU700] = {
-               USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700)},
-       [TERRATEC_AF9015] = {
-               USB_DEVICE(USB_VID_TERRATEC,
-                               USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2)},
-       [KWORLD_PLUSTV_PC160] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T)},
-       [AVERTV_VOLAR_X] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X)},
-       [XTENSIONS_380U] = {
-               USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380)},
-       [MSI_DIGIVOX_DUO] = {
-               USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO)},
-       [AVERTV_VOLAR_X_REV2] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2)},
-       [TELESTAR_STARSTICK_2] = {
-               USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2)},
-       [AVERMEDIA_A309_USB] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309)},
-       [MSI_DIGIVOX_MINI_III] = {
-               USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III)},
-       [KWORLD_E396] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U)},
-       [KWORLD_E39B] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2)},
-       [KWORLD_E395] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3)},
-       [TREKSTOR_DVBT] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT)},
-       [AVERTV_A850] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850)},
-       [AVERTV_A805] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805)},
-       [CONCEPTRONIC_CTVDIGRCU] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU)},
-       [KWORLD_MC810] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810)},
-       [GENIUS_TVGO_DVB_T03] = {
-               USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03)},
-       [KWORLD_399U_2] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2)},
-       [KWORLD_PC160_T] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T)},
-       [SVEON_STV20] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20)},
-       [TINYTWIN_2] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2)},
-       [WINFAST_DTV2000DS] = {
-               USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS)},
-       [KWORLD_UB383_T] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T)},
-       [KWORLD_E39A] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4)},
-       [AVERMEDIA_A815M] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M)},
-       [CINERGY_T_STICK_RC] = {
-               USB_DEVICE(USB_VID_TERRATEC,
-                               USB_PID_TERRATEC_CINERGY_T_STICK_RC)},
-       [CINERGY_T_DUAL_RC] = {
-               USB_DEVICE(USB_VID_TERRATEC,
-                               USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC)},
-       [AVERTV_A850T] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T)},
-       [TINYTWIN_3] = {
-               USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3)},
-       [SVEON_STV22] = {
-               USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22)},
-       { }
-};
-MODULE_DEVICE_TABLE(usb, af9015_usb_table);
-
-#define AF9015_RC_INTERVAL 500
-static struct dvb_usb_device_properties af9015_properties[] = {
-       {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .download_firmware = af9015_download_firmware,
-               .firmware = "dvb-usb-af9015.fw",
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct af9015_state),
-
-               .num_adapters = 2,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
-                                                       DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-                                               .pid_filter_count = 32,
-                                               .pid_filter       = af9015_pid_filter,
-                                               .pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x84,
-                                               },
-                                       }
-                               },
-                       },
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x85,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = TS_USB20_FRAME_SIZE,
-                                                               }
-                                                       }
-                                               },
-                                       }
-                               },
-                       }
-               },
-
-               .identify_state = af9015_identify_state,
-
-               .rc.core = {
-                       .protocol         = RC_TYPE_NEC,
-                       .module_name      = "af9015",
-                       .rc_query         = af9015_rc_query,
-                       .rc_interval      = AF9015_RC_INTERVAL,
-                       .allowed_protos   = RC_TYPE_NEC,
-               },
-
-               .i2c_algo = &af9015_i2c_algo,
-
-               .num_device_descs = 12, /* check max from dvb-usb.h */
-               .devices = {
-                       {
-                               .name = "Afatech AF9015 DVB-T USB2.0 stick",
-                               .cold_ids = {
-                                       &af9015_usb_table[AFATECH_9015],
-                                       &af9015_usb_table[AFATECH_9016],
-                               },
-                       }, {
-                               .name = "Leadtek WinFast DTV Dongle Gold",
-                               .cold_ids = {
-                                       &af9015_usb_table[WINFAST_DTV_GOLD],
-                               },
-                       }, {
-                               .name = "Pinnacle PCTV 71e",
-                               .cold_ids = {
-                                       &af9015_usb_table[PINNACLE_PCTV_71E],
-                               },
-                       }, {
-                               .name = "KWorld PlusTV Dual DVB-T Stick " \
-                                       "(DVB-T 399U)",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_PLUSTV_399U],
-                                       &af9015_usb_table[KWORLD_399U_2],
-                               },
-                       }, {
-                               .name = "DigitalNow TinyTwin DVB-T Receiver",
-                               .cold_ids = {
-                                       &af9015_usb_table[TINYTWIN],
-                                       &af9015_usb_table[TINYTWIN_2],
-                                       &af9015_usb_table[TINYTWIN_3],
-                               },
-                       }, {
-                               .name = "TwinHan AzureWave AD-TU700(704J)",
-                               .cold_ids = {
-                                       &af9015_usb_table[AZUREWAVE_TU700],
-                               },
-                       }, {
-                               .name = "TerraTec Cinergy T USB XE",
-                               .cold_ids = {
-                                       &af9015_usb_table[TERRATEC_AF9015],
-                               },
-                       }, {
-                               .name = "KWorld PlusTV Dual DVB-T PCI " \
-                                       "(DVB-T PC160-2T)",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_PLUSTV_PC160],
-                               },
-                       }, {
-                               .name = "AVerMedia AVerTV DVB-T Volar X",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERTV_VOLAR_X],
-                               },
-                       }, {
-                               .name = "TerraTec Cinergy T Stick RC",
-                               .cold_ids = {
-                                       &af9015_usb_table[CINERGY_T_STICK_RC],
-                               },
-                       }, {
-                               .name = "TerraTec Cinergy T Stick Dual RC",
-                               .cold_ids = {
-                                       &af9015_usb_table[CINERGY_T_DUAL_RC],
-                               },
-                       }, {
-                               .name = "AverMedia AVerTV Red HD+ (A850T)",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERTV_A850T],
-                               },
-                       },
-               }
-       }, {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .download_firmware = af9015_download_firmware,
-               .firmware = "dvb-usb-af9015.fw",
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct af9015_state),
-
-               .num_adapters = 2,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
-                                                       DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-                                               .pid_filter_count = 32,
-                                               .pid_filter       = af9015_pid_filter,
-                                               .pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x84,
-                                               },
-                                       }
-                               },
-                       },
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x85,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = TS_USB20_FRAME_SIZE,
-                                                               }
-                                                       }
-                                               },
-                                       }
-                               },
-                       }
-               },
-
-               .identify_state = af9015_identify_state,
-
-               .rc.core = {
-                       .protocol         = RC_TYPE_NEC,
-                       .module_name      = "af9015",
-                       .rc_query         = af9015_rc_query,
-                       .rc_interval      = AF9015_RC_INTERVAL,
-                       .allowed_protos   = RC_TYPE_NEC,
-               },
-
-               .i2c_algo = &af9015_i2c_algo,
-
-               .num_device_descs = 10, /* check max from dvb-usb.h */
-               .devices = {
-                       {
-                               .name = "Xtensions XD-380",
-                               .cold_ids = {
-                                       &af9015_usb_table[XTENSIONS_380U],
-                               },
-                       }, {
-                               .name = "MSI DIGIVOX Duo",
-                               .cold_ids = {
-                                       &af9015_usb_table[MSI_DIGIVOX_DUO],
-                               },
-                       }, {
-                               .name = "Fujitsu-Siemens Slim Mobile USB DVB-T",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERTV_VOLAR_X_REV2],
-                               },
-                       }, {
-                               .name = "Telestar Starstick 2",
-                               .cold_ids = {
-                                       &af9015_usb_table[TELESTAR_STARSTICK_2],
-                               },
-                       }, {
-                               .name = "AVerMedia A309",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERMEDIA_A309_USB],
-                               },
-                       }, {
-                               .name = "MSI Digi VOX mini III",
-                               .cold_ids = {
-                                       &af9015_usb_table[MSI_DIGIVOX_MINI_III],
-                               },
-                       }, {
-                               .name = "KWorld USB DVB-T TV Stick II " \
-                                       "(VS-DVB-T 395U)",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_E396],
-                                       &af9015_usb_table[KWORLD_E39B],
-                                       &af9015_usb_table[KWORLD_E395],
-                                       &af9015_usb_table[KWORLD_E39A],
-                               },
-                       }, {
-                               .name = "TrekStor DVB-T USB Stick",
-                               .cold_ids = {
-                                       &af9015_usb_table[TREKSTOR_DVBT],
-                               },
-                       }, {
-                               .name = "AverMedia AVerTV Volar Black HD " \
-                                       "(A850)",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERTV_A850],
-                               },
-                       }, {
-                               .name = "Sveon STV22 Dual USB DVB-T Tuner HDTV",
-                               .cold_ids = {
-                                       &af9015_usb_table[SVEON_STV22],
-                               },
-                       },
-               }
-       }, {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .download_firmware = af9015_download_firmware,
-               .firmware = "dvb-usb-af9015.fw",
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct af9015_state),
-
-               .num_adapters = 2,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .caps = DVB_USB_ADAP_HAS_PID_FILTER |
-                                                       DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-
-                                               .pid_filter_count = 32,
-                                               .pid_filter       = af9015_pid_filter,
-                                               .pid_filter_ctrl  = af9015_pid_filter_ctrl,
-
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x84,
-                                               },
-                                       }
-                               },
-                       },
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = af9015_af9013_frontend_attach,
-                                               .tuner_attach    = af9015_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x85,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = TS_USB20_FRAME_SIZE,
-                                                               }
-                                                       }
-                                               },
-                                       }
-                               },
-                       }
-               },
-
-               .identify_state = af9015_identify_state,
-
-               .rc.core = {
-                       .protocol         = RC_TYPE_NEC,
-                       .module_name      = "af9015",
-                       .rc_query         = af9015_rc_query,
-                       .rc_interval      = AF9015_RC_INTERVAL,
-                       .allowed_protos   = RC_TYPE_NEC,
-               },
-
-               .i2c_algo = &af9015_i2c_algo,
-
-               .num_device_descs = 9, /* check max from dvb-usb.h */
-               .devices = {
-                       {
-                               .name = "AverMedia AVerTV Volar GPS 805 (A805)",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERTV_A805],
-                               },
-                       }, {
-                               .name = "Conceptronic USB2.0 DVB-T CTVDIGRCU " \
-                                       "V3.0",
-                               .cold_ids = {
-                                       &af9015_usb_table[CONCEPTRONIC_CTVDIGRCU],
-                               },
-                       }, {
-                               .name = "KWorld Digial MC-810",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_MC810],
-                               },
-                       }, {
-                               .name = "Genius TVGo DVB-T03",
-                               .cold_ids = {
-                                       &af9015_usb_table[GENIUS_TVGO_DVB_T03],
-                               },
-                       }, {
-                               .name = "KWorld PlusTV DVB-T PCI Pro Card " \
-                                       "(DVB-T PC160-T)",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_PC160_T],
-                               },
-                       }, {
-                               .name = "Sveon STV20 Tuner USB DVB-T HDTV",
-                               .cold_ids = {
-                                       &af9015_usb_table[SVEON_STV20],
-                               },
-                       }, {
-                               .name = "Leadtek WinFast DTV2000DS",
-                               .cold_ids = {
-                                       &af9015_usb_table[WINFAST_DTV2000DS],
-                               },
-                       }, {
-                               .name = "KWorld USB DVB-T Stick Mobile " \
-                                       "(UB383-T)",
-                               .cold_ids = {
-                                       &af9015_usb_table[KWORLD_UB383_T],
-                               },
-                       }, {
-                               .name = "AverMedia AVerTV Volar M (A815Mac)",
-                               .cold_ids = {
-                                       &af9015_usb_table[AVERMEDIA_A815M],
-                               },
-                       },
-               }
-       },
-};
-
-static int af9015_usb_probe(struct usb_interface *intf,
-                           const struct usb_device_id *id)
-{
-       int ret = 0;
-       struct dvb_usb_device *d = NULL;
-       struct usb_device *udev = interface_to_usbdev(intf);
-       u8 i;
-
-       deb_info("%s: interface:%d\n", __func__,
-               intf->cur_altsetting->desc.bInterfaceNumber);
-
-       /* interface 0 is used by DVB-T receiver and
-          interface 1 is for remote controller (HID) */
-       if (intf->cur_altsetting->desc.bInterfaceNumber == 0) {
-               ret = af9015_read_config(udev);
-               if (ret)
-                       return ret;
-
-               for (i = 0; i < af9015_properties_count; i++) {
-                       ret = dvb_usb_device_init(intf, &af9015_properties[i],
-                               THIS_MODULE, &d, adapter_nr);
-                       if (!ret)
-                               break;
-                       if (ret != -ENODEV)
-                               return ret;
-               }
-               if (ret)
-                       return ret;
-
-               if (d)
-                       ret = af9015_init(d);
-       }
-
-       return ret;
-}
-
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver af9015_usb_driver = {
-       .name = "dvb_usb_af9015",
-       .probe = af9015_usb_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table = af9015_usb_table,
-};
-
-module_usb_driver(af9015_usb_driver);
-
-MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Afatech AF9015 driver");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/it913x.c b/drivers/media/dvb/dvb-usb/it913x.c
deleted file mode 100644 (file)
index 6244fe9..0000000
+++ /dev/null
@@ -1,931 +0,0 @@
-/* DVB USB compliant linux driver for IT9137
- *
- * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
- * IT9137 (C) ITE Tech Inc.
- *
- * 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.
- *
- * 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.
- *
- *
- * see Documentation/dvb/README.dvb-usb for more information
- * see Documentation/dvb/it9137.txt for firmware information
- *
- */
-#define DVB_USB_LOG_PREFIX "it913x"
-
-#include <linux/usb.h>
-#include <linux/usb/input.h>
-#include <media/rc-core.h>
-
-#include "dvb-usb.h"
-#include "it913x-fe.h"
-
-/* debug */
-static int dvb_usb_it913x_debug;
-#define l_dprintk(var, level, args...) do { \
-       if ((var >= level)) \
-               printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
-} while (0)
-
-#define deb_info(level, args...) l_dprintk(dvb_usb_it913x_debug, level, args)
-#define debug_data_snipet(level, name, p) \
-        deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
-               *p, *(p+1), *(p+2), *(p+3), *(p+4), \
-                       *(p+5), *(p+6), *(p+7));
-
-
-module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
-                       DVB_USB_DEBUG_STATUS);
-
-static int pid_filter;
-module_param_named(pid, pid_filter, int, 0644);
-MODULE_PARM_DESC(pid, "set default 0=on 1=off");
-
-static int dvb_usb_it913x_firmware;
-module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644);
-MODULE_PARM_DESC(firmware, "set firmware 0=auto 1=IT9137 2=IT9135V1");
-
-
-int cmd_counter;
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-struct it913x_state {
-       u8 id;
-       struct ite_config it913x_config;
-       u8 pid_filter_onoff;
-};
-
-struct ite_config it913x_config;
-
-#define IT913X_RETRY   10
-#define IT913X_SND_TIMEOUT     100
-#define IT913X_RCV_TIMEOUT     200
-
-static int it913x_bulk_write(struct usb_device *dev,
-                               u8 *snd, int len, u8 pipe)
-{
-       int ret, actual_l, i;
-
-       for (i = 0; i < IT913X_RETRY; i++) {
-               ret = usb_bulk_msg(dev, usb_sndbulkpipe(dev, pipe),
-                               snd, len , &actual_l, IT913X_SND_TIMEOUT);
-               if (ret != -EBUSY && ret != -ETIMEDOUT)
-                       break;
-       }
-
-       if (len != actual_l && ret == 0)
-               ret = -EAGAIN;
-
-       return ret;
-}
-
-static int it913x_bulk_read(struct usb_device *dev,
-                               u8 *rev, int len, u8 pipe)
-{
-       int ret, actual_l, i;
-
-       for (i = 0; i < IT913X_RETRY; i++) {
-               ret = usb_bulk_msg(dev, usb_rcvbulkpipe(dev, pipe),
-                                rev, len , &actual_l, IT913X_RCV_TIMEOUT);
-               if (ret != -EBUSY && ret != -ETIMEDOUT)
-                       break;
-       }
-
-       if (len != actual_l && ret == 0)
-               ret = -EAGAIN;
-
-       return ret;
-}
-
-static u16 check_sum(u8 *p, u8 len)
-{
-       u16 sum = 0;
-       u8 i = 1;
-       while (i < len)
-               sum += (i++ & 1) ? (*p++) << 8 : *p++;
-       return ~sum;
-}
-
-static int it913x_usb_talk(struct usb_device *udev, u8 mode, u8 pro,
-                       u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
-{
-       int ret = 0, i, buf_size = 1;
-       u8 *buff;
-       u8 rlen;
-       u16 chk_sum;
-
-       buff = kzalloc(256, GFP_KERNEL);
-       if (!buff) {
-               info("USB Buffer Failed");
-               return -ENOMEM;
-       }
-
-       buff[buf_size++] = pro;
-       buff[buf_size++] = cmd;
-       buff[buf_size++] = cmd_counter;
-
-       switch (mode) {
-       case READ_LONG:
-       case WRITE_LONG:
-               buff[buf_size++] = len;
-               buff[buf_size++] = 2;
-               buff[buf_size++] = (reg >> 24);
-               buff[buf_size++] = (reg >> 16) & 0xff;
-               buff[buf_size++] = (reg >> 8) & 0xff;
-               buff[buf_size++] = reg & 0xff;
-       break;
-       case READ_SHORT:
-               buff[buf_size++] = addr;
-               break;
-       case WRITE_SHORT:
-               buff[buf_size++] = len;
-               buff[buf_size++] = addr;
-               buff[buf_size++] = (reg >> 8) & 0xff;
-               buff[buf_size++] = reg & 0xff;
-       break;
-       case READ_DATA:
-       case WRITE_DATA:
-               break;
-       case WRITE_CMD:
-               mode = 7;
-               break;
-       default:
-               kfree(buff);
-               return -EINVAL;
-       }
-
-       if (mode & 1) {
-               for (i = 0; i < len ; i++)
-                       buff[buf_size++] = data[i];
-       }
-       chk_sum = check_sum(&buff[1], buf_size);
-
-       buff[buf_size++] = chk_sum >> 8;
-       buff[0] = buf_size;
-       buff[buf_size++] = (chk_sum & 0xff);
-
-       ret = it913x_bulk_write(udev, buff, buf_size , 0x02);
-       if (ret < 0)
-               goto error;
-
-       ret = it913x_bulk_read(udev, buff, (mode & 1) ?
-                       5 : len + 5 , 0x01);
-       if (ret < 0)
-               goto error;
-
-       rlen = (mode & 0x1) ? 0x1 : len;
-
-       if (mode & 1)
-               ret = buff[2];
-       else
-               memcpy(data, &buff[3], rlen);
-
-       cmd_counter++;
-
-error: kfree(buff);
-
-       return ret;
-}
-
-static int it913x_io(struct usb_device *udev, u8 mode, u8 pro,
-                       u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
-{
-       int ret, i;
-
-       for (i = 0; i < IT913X_RETRY; i++) {
-               ret = it913x_usb_talk(udev, mode, pro,
-                       cmd, reg, addr, data, len);
-               if (ret != -EAGAIN)
-                       break;
-       }
-
-       return ret;
-}
-
-static int it913x_wr_reg(struct usb_device *udev, u8 pro, u32 reg , u8 data)
-{
-       int ret;
-       u8 b[1];
-       b[0] = data;
-       ret = it913x_io(udev, WRITE_LONG, pro,
-                       CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
-
-       return ret;
-}
-
-static int it913x_read_reg(struct usb_device *udev, u32 reg)
-{
-       int ret;
-       u8 data[1];
-
-       ret = it913x_io(udev, READ_LONG, DEV_0,
-                       CMD_DEMOD_READ, reg, 0, &data[0], 1);
-
-       return (ret < 0) ? ret : data[0];
-}
-
-static u32 it913x_query(struct usb_device *udev, u8 pro)
-{
-       int ret, i;
-       u8 data[4];
-       u8 ver;
-
-       for (i = 0; i < 5; i++) {
-               ret = it913x_io(udev, READ_LONG, pro, CMD_DEMOD_READ,
-                       0x1222, 0, &data[0], 3);
-               ver = data[0];
-               if (ver > 0 && ver < 3)
-                       break;
-               msleep(100);
-       }
-
-       if (ver < 1 || ver > 2) {
-               info("Failed to identify chip version applying 1");
-               it913x_config.chip_ver = 0x1;
-               it913x_config.chip_type = 0x9135;
-               return 0;
-       }
-
-       it913x_config.chip_ver = ver;
-       it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
-
-       info("Chip Version=%02x Chip Type=%04x", it913x_config.chip_ver,
-               it913x_config.chip_type);
-
-       ret |= it913x_io(udev, READ_SHORT, pro,
-                       CMD_QUERYINFO, 0, 0x1, &data[0], 4);
-
-       it913x_config.firmware = (data[0] << 24) + (data[1] << 16) +
-                       (data[2] << 8) + data[3];
-
-       return (ret < 0) ? 0 : it913x_config.firmware;
-}
-
-static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct it913x_state *st = adap->dev->priv;
-       struct usb_device *udev = adap->dev->udev;
-       int ret;
-       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-       mutex_lock(&adap->dev->i2c_mutex);
-
-       deb_info(1, "PID_C  (%02x)", onoff);
-
-       ret = it913x_wr_reg(udev, pro, PID_EN, st->pid_filter_onoff);
-
-       mutex_unlock(&adap->dev->i2c_mutex);
-       return ret;
-}
-
-static int it913x_pid_filter(struct dvb_usb_adapter *adap,
-               int index, u16 pid, int onoff)
-{
-       struct it913x_state *st = adap->dev->priv;
-       struct usb_device *udev = adap->dev->udev;
-       int ret;
-       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-       mutex_lock(&adap->dev->i2c_mutex);
-
-       deb_info(1, "PID_F  (%02x)", onoff);
-
-       ret = it913x_wr_reg(udev, pro, PID_LSB, (u8)(pid & 0xff));
-
-       ret |= it913x_wr_reg(udev, pro, PID_MSB, (u8)(pid >> 8));
-
-       ret |= it913x_wr_reg(udev, pro, PID_INX_EN, (u8)onoff);
-
-       ret |= it913x_wr_reg(udev, pro, PID_INX, (u8)(index & 0x1f));
-
-       if (udev->speed == USB_SPEED_HIGH && pid == 0x2000) {
-                       ret |= it913x_wr_reg(udev, pro, PID_EN, !onoff);
-                       st->pid_filter_onoff = !onoff;
-       } else
-               st->pid_filter_onoff =
-                       adap->fe_adap[adap->active_fe].pid_filtering;
-
-       mutex_unlock(&adap->dev->i2c_mutex);
-       return 0;
-}
-
-
-static int it913x_return_status(struct usb_device *udev)
-{
-       u32 firm = 0;
-
-       firm = it913x_query(udev, DEV_0);
-       if (firm > 0)
-               info("Firmware Version %d", firm);
-
-       return (firm > 0) ? firm : 0;
-}
-
-static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-                                int num)
-{
-       struct dvb_usb_device *d = i2c_get_adapdata(adap);
-       static u8 data[256];
-       int ret;
-       u32 reg;
-       u8 pro;
-
-       mutex_lock(&d->i2c_mutex);
-
-       debug_data_snipet(1, "Message out", msg[0].buf);
-       deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
-
-       pro = (msg[0].addr & 0x2) ?  DEV_0_DMOD : 0x0;
-       pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
-       memcpy(data, msg[0].buf, msg[0].len);
-       reg = (data[0] << 24) + (data[1] << 16) +
-                       (data[2] << 8) + data[3];
-       if (num == 2) {
-               ret = it913x_io(d->udev, READ_LONG, pro,
-                       CMD_DEMOD_READ, reg, 0, data, msg[1].len);
-               memcpy(msg[1].buf, data, msg[1].len);
-       } else
-               ret = it913x_io(d->udev, WRITE_LONG, pro, CMD_DEMOD_WRITE,
-                       reg, 0, &data[4], msg[0].len - 4);
-
-       mutex_unlock(&d->i2c_mutex);
-
-       return ret;
-}
-
-static u32 it913x_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C;
-}
-
-static struct i2c_algorithm it913x_i2c_algo = {
-       .master_xfer   = it913x_i2c_xfer,
-       .functionality = it913x_i2c_func,
-};
-
-/* Callbacks for DVB USB */
-#define IT913X_POLL 250
-static int it913x_rc_query(struct dvb_usb_device *d)
-{
-       u8 ibuf[4];
-       int ret;
-       u32 key;
-       /* Avoid conflict with frontends*/
-       mutex_lock(&d->i2c_mutex);
-
-       ret = it913x_io(d->udev, READ_LONG, PRO_LINK, CMD_IR_GET,
-               0, 0, &ibuf[0], sizeof(ibuf));
-
-       if ((ibuf[2] + ibuf[3]) == 0xff) {
-               key = ibuf[2];
-               key += ibuf[0] << 16;
-               key += ibuf[1] << 8;
-               deb_info(1, "NEC Extended Key =%08x", key);
-               if (d->rc_dev != NULL)
-                       rc_keydown(d->rc_dev, key, 0);
-       }
-
-       mutex_unlock(&d->i2c_mutex);
-
-       return ret;
-}
-
-/* Firmware sets raw */
-const char fw_it9135_v1[] = "dvb-usb-it9135-01.fw";
-const char fw_it9135_v2[] = "dvb-usb-it9135-02.fw";
-const char fw_it9137[] = "dvb-usb-it9137-01.fw";
-
-static int ite_firmware_select(struct usb_device *udev,
-       struct dvb_usb_device_properties *props)
-{
-       int sw;
-       /* auto switch */
-       if (le16_to_cpu(udev->descriptor.idVendor) == USB_VID_KWORLD_2)
-               sw = IT9137_FW;
-       else if (it913x_config.chip_ver == 1)
-               sw = IT9135_V1_FW;
-       else
-               sw = IT9135_V2_FW;
-
-       /* force switch */
-       if (dvb_usb_it913x_firmware != IT9135_AUTO)
-               sw = dvb_usb_it913x_firmware;
-
-       switch (sw) {
-       case IT9135_V1_FW:
-               it913x_config.firmware_ver = 1;
-               it913x_config.adc_x2 = 1;
-               it913x_config.read_slevel = false;
-               props->firmware = fw_it9135_v1;
-               break;
-       case IT9135_V2_FW:
-               it913x_config.firmware_ver = 1;
-               it913x_config.adc_x2 = 1;
-               it913x_config.read_slevel = false;
-               props->firmware = fw_it9135_v2;
-               switch (it913x_config.tuner_id_0) {
-               case IT9135_61:
-               case IT9135_62:
-                       break;
-               default:
-                       info("Unknown tuner ID applying default 0x60");
-               case IT9135_60:
-                       it913x_config.tuner_id_0 = IT9135_60;
-               }
-               break;
-       case IT9137_FW:
-       default:
-               it913x_config.firmware_ver = 0;
-               it913x_config.adc_x2 = 0;
-               it913x_config.read_slevel = true;
-               props->firmware = fw_it9137;
-       }
-
-       return 0;
-}
-
-static void it913x_select_remote(struct usb_device *udev,
-       struct dvb_usb_device_properties *props)
-{
-       switch (le16_to_cpu(udev->descriptor.idProduct)) {
-       case USB_PID_ITETECH_IT9135_9005:
-               props->rc.core.rc_codes = RC_MAP_IT913X_V2;
-               return;
-       default:
-               props->rc.core.rc_codes = RC_MAP_IT913X_V1;
-       }
-       return;
-}
-
-#define TS_MPEG_PKT_SIZE       188
-#define EP_LOW                 21
-#define TS_BUFFER_SIZE_PID     (EP_LOW*TS_MPEG_PKT_SIZE)
-#define EP_HIGH                        348
-#define TS_BUFFER_SIZE_MAX     (EP_HIGH*TS_MPEG_PKT_SIZE)
-
-static int it913x_select_config(struct usb_device *udev,
-       struct dvb_usb_device_properties *props)
-{
-       int ret = 0, reg;
-       bool proprietary_ir = false;
-
-       if (it913x_config.chip_ver == 0x02
-                       && it913x_config.chip_type == 0x9135)
-               reg = it913x_read_reg(udev, 0x461d);
-       else
-               reg = it913x_read_reg(udev, 0x461b);
-
-       if (reg < 0)
-               return reg;
-
-       if (reg == 0) {
-               it913x_config.dual_mode = 0;
-               it913x_config.tuner_id_0 = IT9135_38;
-               proprietary_ir = true;
-       } else {
-               /* TS mode */
-               reg =  it913x_read_reg(udev, 0x49c5);
-               if (reg < 0)
-                       return reg;
-               it913x_config.dual_mode = reg;
-
-               /* IR mode type */
-               reg = it913x_read_reg(udev, 0x49ac);
-               if (reg < 0)
-                       return reg;
-               if (reg == 5) {
-                       info("Remote propriety (raw) mode");
-                       proprietary_ir = true;
-               } else if (reg == 1) {
-                       info("Remote HID mode NOT SUPPORTED");
-                       proprietary_ir = false;
-                       props->rc.core.rc_codes = NULL;
-               } else
-                       props->rc.core.rc_codes = NULL;
-
-               /* Tuner_id */
-               reg = it913x_read_reg(udev, 0x49d0);
-               if (reg < 0)
-                       return reg;
-               it913x_config.tuner_id_0 = reg;
-       }
-
-       if (proprietary_ir)
-               it913x_select_remote(udev, props);
-
-       if (udev->speed != USB_SPEED_HIGH) {
-               props->adapter[0].fe[0].pid_filter_count = 5;
-               info("USB 1 low speed mode - connect to USB 2 port");
-               if (pid_filter > 0)
-                       pid_filter = 0;
-               if (it913x_config.dual_mode) {
-                       it913x_config.dual_mode = 0;
-                       info("Dual mode not supported in USB 1");
-               }
-       } else /* For replugging */
-               if(props->adapter[0].fe[0].pid_filter_count == 5)
-                       props->adapter[0].fe[0].pid_filter_count = 31;
-
-       /* Select Stream Buffer Size and pid filter option*/
-       if (pid_filter) {
-               props->adapter[0].fe[0].stream.u.bulk.buffersize =
-                       TS_BUFFER_SIZE_MAX;
-               props->adapter[0].fe[0].caps &=
-                       ~DVB_USB_ADAP_NEED_PID_FILTERING;
-       } else
-               props->adapter[0].fe[0].stream.u.bulk.buffersize =
-                       TS_BUFFER_SIZE_PID;
-
-       if (it913x_config.dual_mode) {
-               props->adapter[1].fe[0].stream.u.bulk.buffersize =
-                       props->adapter[0].fe[0].stream.u.bulk.buffersize;
-               props->num_adapters = 2;
-               if (pid_filter)
-                       props->adapter[1].fe[0].caps =
-                               props->adapter[0].fe[0].caps;
-       } else
-               props->num_adapters = 1;
-
-       info("Dual mode=%x Tuner Type=%x", it913x_config.dual_mode,
-               it913x_config.tuner_id_0);
-
-       ret = ite_firmware_select(udev, props);
-
-       return ret;
-}
-
-static int it913x_identify_state(struct usb_device *udev,
-               struct dvb_usb_device_properties *props,
-               struct dvb_usb_device_description **desc,
-               int *cold)
-{
-       int ret = 0, firm_no;
-       u8 reg;
-
-       firm_no = it913x_return_status(udev);
-
-       /* Read and select config */
-       ret = it913x_select_config(udev, props);
-       if (ret < 0)
-               return ret;
-
-       if (firm_no > 0) {
-               *cold = 0;
-               return 0;
-       }
-
-       if (it913x_config.dual_mode) {
-               it913x_config.tuner_id_1 = it913x_read_reg(udev, 0x49e0);
-               ret = it913x_wr_reg(udev, DEV_0, GPIOH1_EN, 0x1);
-               ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_ON, 0x1);
-               ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x1);
-               msleep(50);
-               ret |= it913x_wr_reg(udev, DEV_0, GPIOH1_O, 0x0);
-               msleep(50);
-               reg = it913x_read_reg(udev, GPIOH1_O);
-               if (reg == 0) {
-                       ret |= it913x_wr_reg(udev, DEV_0,  GPIOH1_O, 0x1);
-                       ret |= it913x_return_status(udev);
-                       if (ret != 0)
-                               ret = it913x_wr_reg(udev, DEV_0,
-                                       GPIOH1_O, 0x0);
-               }
-       }
-
-       reg = it913x_read_reg(udev, IO_MUX_POWER_CLK);
-
-       if (it913x_config.dual_mode) {
-               ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
-               if (it913x_config.firmware_ver == 1)
-                       ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x1);
-               else
-                       ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x1);
-       } else {
-               ret |= it913x_wr_reg(udev, DEV_0, 0x4bfb, 0x0);
-               if (it913x_config.firmware_ver == 1)
-                       ret |= it913x_wr_reg(udev, DEV_0,  0xcfff, 0x0);
-               else
-                       ret |= it913x_wr_reg(udev, DEV_0,  CLK_O_EN, 0x0);
-       }
-
-       *cold = 1;
-
-       return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct it913x_state *st = adap->dev->priv;
-       int ret = 0;
-       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
-
-       deb_info(1, "STM  (%02x)", onoff);
-
-       if (!onoff) {
-               mutex_lock(&adap->dev->i2c_mutex);
-
-               ret = it913x_wr_reg(adap->dev->udev, pro, PID_RST, 0x1);
-
-               mutex_unlock(&adap->dev->i2c_mutex);
-               st->pid_filter_onoff =
-                       adap->fe_adap[adap->active_fe].pid_filtering;
-
-       }
-
-       return ret;
-}
-
-static int it913x_download_firmware(struct usb_device *udev,
-                                       const struct firmware *fw)
-{
-       int ret = 0, i = 0, pos = 0;
-       u8 packet_size, min_pkt;
-       u8 *fw_data;
-
-       ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_100);
-
-       info("FRM Starting Firmware Download");
-
-       /* Multi firmware loader */
-       /* This uses scatter write firmware headers */
-       /* The firmware must start with 03 XX 00 */
-       /* and be the extact firmware length */
-
-       if (it913x_config.chip_ver == 2)
-               min_pkt = 0x11;
-       else
-               min_pkt = 0x19;
-
-       while (i <= fw->size) {
-               if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0))
-                       || (i == fw->size)) {
-                       packet_size = i - pos;
-                       if ((packet_size > min_pkt) || (i == fw->size)) {
-                               fw_data = (u8 *)(fw->data + pos);
-                               pos += packet_size;
-                               if (packet_size > 0) {
-                                       ret = it913x_io(udev, WRITE_DATA,
-                                               DEV_0, CMD_SCATTER_WRITE, 0,
-                                               0, fw_data, packet_size);
-                                       if (ret < 0)
-                                               break;
-                               }
-                               udelay(1000);
-                       }
-               }
-               i++;
-       }
-
-       if (ret < 0)
-               info("FRM Firmware Download Failed (%d)" , ret);
-       else
-               info("FRM Firmware Download Completed - Resetting Device");
-
-       msleep(30);
-
-       ret = it913x_io(udev, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
-       if (ret < 0)
-               info("FRM Device not responding to reboot");
-
-       ret = it913x_return_status(udev);
-       if (ret == 0) {
-               info("FRM Failed to reboot device");
-               return -ENODEV;
-       }
-
-       msleep(30);
-
-       ret = it913x_wr_reg(udev, DEV_0,  I2C_CLK, I2C_CLK_400);
-
-       msleep(30);
-
-       /* Tuner function */
-       if (it913x_config.dual_mode)
-               ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0xa0);
-       else
-               ret |= it913x_wr_reg(udev, DEV_0_DMOD , 0xec4c, 0x68);
-
-       if ((it913x_config.chip_ver == 1) &&
-               (it913x_config.chip_type == 0x9135)) {
-               ret |= it913x_wr_reg(udev, DEV_0,  PADODPU, 0x0);
-               ret |= it913x_wr_reg(udev, DEV_0,  AGC_O_D, 0x0);
-               if (it913x_config.dual_mode) {
-                       ret |= it913x_wr_reg(udev, DEV_1,  PADODPU, 0x0);
-                       ret |= it913x_wr_reg(udev, DEV_1,  AGC_O_D, 0x0);
-               }
-       }
-
-       return (ret < 0) ? -ENODEV : 0;
-}
-
-static int it913x_name(struct dvb_usb_adapter *adap)
-{
-       const char *desc = adap->dev->desc->name;
-       char *fe_name[] = {"_1", "_2", "_3", "_4"};
-       char *name = adap->fe_adap[0].fe->ops.info.name;
-
-       strlcpy(name, desc, 128);
-       strlcat(name, fe_name[adap->id], 128);
-
-       return 0;
-}
-
-static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       struct usb_device *udev = adap->dev->udev;
-       struct it913x_state *st = adap->dev->priv;
-       int ret = 0;
-       u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
-       u16 ep_size = adap->props.fe[0].stream.u.bulk.buffersize / 4;
-       u8 pkt_size = 0x80;
-
-       if (adap->dev->udev->speed != USB_SPEED_HIGH)
-               pkt_size = 0x10;
-
-       it913x_config.adf = it913x_read_reg(udev, IO_MUX_POWER_CLK);
-
-       if (adap->id == 0)
-               memcpy(&st->it913x_config, &it913x_config,
-                       sizeof(struct ite_config));
-
-       adap->fe_adap[0].fe = dvb_attach(it913x_fe_attach,
-               &adap->dev->i2c_adap, adap_addr, &st->it913x_config);
-
-       if (adap->id == 0 && adap->fe_adap[0].fe) {
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x1);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
-               ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x0f);
-               ret = it913x_wr_reg(udev, DEV_0, EP0_TX_NAK, 0x1b);
-               ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x2f);
-               ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_LSB,
-                                       ep_size & 0xff);
-               ret = it913x_wr_reg(udev, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
-               ret = it913x_wr_reg(udev, DEV_0, EP4_MAX_PKT, pkt_size);
-       } else if (adap->id == 1 && adap->fe_adap[0].fe) {
-               ret = it913x_wr_reg(udev, DEV_0, EP0_TX_EN, 0x6f);
-               ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_LSB,
-                                       ep_size & 0xff);
-               ret = it913x_wr_reg(udev, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
-               ret = it913x_wr_reg(udev, DEV_0, EP5_MAX_PKT, pkt_size);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_EN, 0x1);
-               ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
-               ret = it913x_wr_reg(udev, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, TSIS_ENABLE, 0x1);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2_SW_RST, 0x0);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
-               ret = it913x_wr_reg(udev, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
-               ret = it913x_wr_reg(udev, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
-               ret = it913x_wr_reg(udev, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
-       } else
-               return -ENODEV;
-
-       ret = it913x_name(adap);
-
-       return ret;
-}
-
-/* DVB USB Driver */
-static struct dvb_usb_device_properties it913x_properties;
-
-static int it913x_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
-{
-       cmd_counter = 0;
-       if (0 == dvb_usb_device_init(intf, &it913x_properties,
-                                    THIS_MODULE, NULL, adapter_nr)) {
-               info("DEV registering device driver");
-               return 0;
-       }
-
-       info("DEV it913x Error");
-       return -ENODEV;
-
-}
-
-static struct usb_device_id it913x_table[] = {
-       { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09) },
-       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135) },
-       { USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137) },
-       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005) },
-       { USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006) },
-       {}              /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, it913x_table);
-
-static struct dvb_usb_device_properties it913x_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-       .usb_ctrl = DEVICE_SPECIFIC,
-       .download_firmware = it913x_download_firmware,
-       .firmware = "dvb-usb-it9137-01.fw",
-       .no_reconnect = 1,
-       .size_of_priv = sizeof(struct it913x_state),
-       .num_adapters = 2,
-       .adapter = {
-               {
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
-                               DVB_USB_ADAP_NEED_PID_FILTERING|
-                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-                       .streaming_ctrl   = it913x_streaming_ctrl,
-                       .pid_filter_count = 31,
-                       .pid_filter = it913x_pid_filter,
-                       .pid_filter_ctrl  = it913x_pid_filter_ctrl,
-                       .frontend_attach  = it913x_frontend_attach,
-                       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 10,
-                               .endpoint = 0x04,
-                               .u = {/* Keep Low if PID filter on */
-                                       .bulk = {
-                                       .buffersize =
-                                               TS_BUFFER_SIZE_PID,
-                                       }
-                               }
-                       }
-               }},
-               },
-                       {
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
-                               DVB_USB_ADAP_NEED_PID_FILTERING|
-                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-                       .streaming_ctrl   = it913x_streaming_ctrl,
-                       .pid_filter_count = 31,
-                       .pid_filter = it913x_pid_filter,
-                       .pid_filter_ctrl  = it913x_pid_filter_ctrl,
-                       .frontend_attach  = it913x_frontend_attach,
-                       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 5,
-                               .endpoint = 0x05,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize =
-                                                       TS_BUFFER_SIZE_PID,
-                                       }
-                               }
-                       }
-               }},
-               }
-       },
-       .identify_state   = it913x_identify_state,
-       .rc.core = {
-               .protocol       = RC_TYPE_NEC,
-               .module_name    = "it913x",
-               .rc_query       = it913x_rc_query,
-               .rc_interval    = IT913X_POLL,
-               .allowed_protos = RC_TYPE_NEC,
-               .rc_codes       = RC_MAP_IT913X_V1,
-       },
-       .i2c_algo         = &it913x_i2c_algo,
-       .num_device_descs = 5,
-       .devices = {
-               {   "Kworld UB499-2T T09(IT9137)",
-                       { &it913x_table[0], NULL },
-                       },
-               {   "ITE 9135 Generic",
-                       { &it913x_table[1], NULL },
-                       },
-               {   "Sveon STV22 Dual DVB-T HDTV(IT9137)",
-                       { &it913x_table[2], NULL },
-                       },
-               {   "ITE 9135(9005) Generic",
-                       { &it913x_table[3], NULL },
-                       },
-               {   "ITE 9135(9006) Generic",
-                       { &it913x_table[4], NULL },
-                       },
-       }
-};
-
-static struct usb_driver it913x_driver = {
-       .name           = "it913x",
-       .probe          = it913x_probe,
-       .disconnect     = dvb_usb_device_exit,
-       .id_table       = it913x_table,
-};
-
-module_usb_driver(it913x_driver);
-
-MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
-MODULE_DESCRIPTION("it913x USB 2 Driver");
-MODULE_VERSION("1.28");
-MODULE_LICENSE("GPL");
diff --git a/drivers/media/dvb/dvb-usb/mxl111sf.c b/drivers/media/dvb/dvb-usb/mxl111sf.c
deleted file mode 100644 (file)
index cd84279..0000000
+++ /dev/null
@@ -1,1835 +0,0 @@
-/*
- * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
- *
- * see Documentation/dvb/README.dvb-usb for more information
- */
-
-#include <linux/vmalloc.h>
-#include <linux/i2c.h>
-
-#include "mxl111sf.h"
-#include "mxl111sf-reg.h"
-#include "mxl111sf-phy.h"
-#include "mxl111sf-i2c.h"
-#include "mxl111sf-gpio.h"
-
-#include "mxl111sf-demod.h"
-#include "mxl111sf-tuner.h"
-
-#include "lgdt3305.h"
-#include "lg2160.h"
-
-int dvb_usb_mxl111sf_debug;
-module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level "
-                "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
-
-int dvb_usb_mxl111sf_isoc;
-module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
-MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
-
-int dvb_usb_mxl111sf_spi;
-module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644);
-MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi).");
-
-#define ANT_PATH_AUTO 0
-#define ANT_PATH_EXTERNAL 1
-#define ANT_PATH_INTERNAL 2
-
-int dvb_usb_mxl111sf_rfswitch =
-#if 0
-               ANT_PATH_AUTO;
-#else
-               ANT_PATH_EXTERNAL;
-#endif
-
-module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
-MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
-
-DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
-#define deb_info(args...)   dprintk(dvb_usb_mxl111sf_debug, 0x13, args)
-#define deb_reg(args...)    dprintk(dvb_usb_mxl111sf_debug, 0x08, args)
-#define deb_adv(args...)    dprintk(dvb_usb_mxl111sf_debug, MXL_ADV_DBG, args)
-
-int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
-                     u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
-{
-       int wo = (rbuf == NULL || rlen == 0); /* write-only */
-       int ret;
-       u8 sndbuf[1+wlen];
-
-       deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
-
-       memset(sndbuf, 0, 1+wlen);
-
-       sndbuf[0] = cmd;
-       memcpy(&sndbuf[1], wbuf, wlen);
-
-       ret = (wo) ? dvb_usb_generic_write(d, sndbuf, 1+wlen) :
-               dvb_usb_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen, 0);
-       mxl_fail(ret);
-
-       return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-#define MXL_CMD_REG_READ       0xaa
-#define MXL_CMD_REG_WRITE      0x55
-
-int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
-{
-       u8 buf[2];
-       int ret;
-
-       ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
-       if (mxl_fail(ret)) {
-               mxl_debug("error reading reg: 0x%02x", addr);
-               goto fail;
-       }
-
-       if (buf[0] == addr)
-               *data = buf[1];
-       else {
-               err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
-                   addr, buf[0], buf[1]);
-               ret = -EINVAL;
-       }
-
-       deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
-fail:
-       return ret;
-}
-
-int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
-{
-       u8 buf[] = { addr, data };
-       int ret;
-
-       deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
-
-       ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
-       if (mxl_fail(ret))
-               err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
-       return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
-                                  u8 addr, u8 mask, u8 data)
-{
-       int ret;
-       u8 val;
-
-       if (mask != 0xff) {
-               ret = mxl111sf_read_reg(state, addr, &val);
-#if 1
-               /* dont know why this usually errors out on the first try */
-               if (mxl_fail(ret))
-                       err("error writing addr: 0x%02x, mask: 0x%02x, "
-                           "data: 0x%02x, retrying...", addr, mask, data);
-
-               ret = mxl111sf_read_reg(state, addr, &val);
-#endif
-               if (mxl_fail(ret))
-                       goto fail;
-       }
-       val &= ~mask;
-       val |= data;
-
-       ret = mxl111sf_write_reg(state, addr, val);
-       mxl_fail(ret);
-fail:
-       return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
-                              struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
-{
-       int i, ret = 0;
-
-       for (i = 0;  ctrl_reg_info[i].addr |
-                    ctrl_reg_info[i].mask |
-                    ctrl_reg_info[i].data;  i++) {
-
-               ret = mxl111sf_write_reg_mask(state,
-                                             ctrl_reg_info[i].addr,
-                                             ctrl_reg_info[i].mask,
-                                             ctrl_reg_info[i].data);
-               if (mxl_fail(ret)) {
-                       err("failed on reg #%d (0x%02x)", i,
-                           ctrl_reg_info[i].addr);
-                       break;
-               }
-       }
-       return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
-{
-       int ret;
-       u8 id, ver;
-       char *mxl_chip, *mxl_rev;
-
-       if ((state->chip_id) && (state->chip_ver))
-               return 0;
-
-       ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
-       if (mxl_fail(ret))
-               goto fail;
-       state->chip_id = id;
-
-       ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
-       if (mxl_fail(ret))
-               goto fail;
-       state->chip_ver = ver;
-
-       switch (id) {
-       case 0x61:
-               mxl_chip = "MxL101SF";
-               break;
-       case 0x63:
-               mxl_chip = "MxL111SF";
-               break;
-       default:
-               mxl_chip = "UNKNOWN MxL1X1";
-               break;
-       }
-       switch (ver) {
-       case 0x36:
-               state->chip_rev = MXL111SF_V6;
-               mxl_rev = "v6";
-               break;
-       case 0x08:
-               state->chip_rev = MXL111SF_V8_100;
-               mxl_rev = "v8_100";
-               break;
-       case 0x18:
-               state->chip_rev = MXL111SF_V8_200;
-               mxl_rev = "v8_200";
-               break;
-       default:
-               state->chip_rev = 0;
-               mxl_rev = "UNKNOWN REVISION";
-               break;
-       }
-       info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
-fail:
-       return ret;
-}
-
-#define get_chip_info(state)                                           \
-({                                                                     \
-       int ___ret;                                                     \
-       ___ret = mxl1x1sf_get_chip_info(state);                         \
-       if (mxl_fail(___ret)) {                                         \
-               mxl_debug("failed to get chip info"                     \
-                         " on first probe attempt");                   \
-               ___ret = mxl1x1sf_get_chip_info(state);                 \
-               if (mxl_fail(___ret))                                   \
-                       err("failed to get chip info during probe");    \
-               else                                                    \
-                       mxl_debug("probe needed a retry "               \
-                                 "in order to succeed.");              \
-       }                                                               \
-       ___ret;                                                         \
-})
-
-/* ------------------------------------------------------------------------ */
-
-static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
-{
-       /* power control depends on which adapter is being woken:
-        * save this for init, instead, via mxl111sf_adap_fe_init */
-       return 0;
-}
-
-static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
-{
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
-
-       int err;
-
-       /* exit if we didnt initialize the driver yet */
-       if (!state->chip_id) {
-               mxl_debug("driver not yet initialized, exit.");
-               goto fail;
-       }
-
-       deb_info("%s()\n", __func__);
-
-       mutex_lock(&state->fe_lock);
-
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       err = mxl1x1sf_soft_reset(state);
-       mxl_fail(err);
-       err = mxl111sf_init_tuner_demod(state);
-       mxl_fail(err);
-       err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-
-       mxl_fail(err);
-       mxl111sf_enable_usb_output(state);
-       mxl_fail(err);
-       mxl1x1sf_top_master_ctrl(state, 1);
-       mxl_fail(err);
-
-       if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
-           (state->chip_rev > MXL111SF_V6)) {
-               mxl111sf_config_pin_mux_modes(state,
-                                             PIN_MUX_TS_SPI_IN_MODE_1);
-               mxl_fail(err);
-       }
-       err = mxl111sf_init_port_expander(state);
-       if (!mxl_fail(err)) {
-               state->gpio_mode = adap_state->gpio_mode;
-               err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-               mxl_fail(err);
-#if 0
-               err = fe->ops.init(fe);
-#endif
-               msleep(100); /* add short delay after enabling
-                             * the demod before touching it */
-       }
-
-       return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
-fail:
-       return -ENODEV;
-}
-
-static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
-{
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe->id].priv;
-       int err;
-
-       /* exit if we didnt initialize the driver yet */
-       if (!state->chip_id) {
-               mxl_debug("driver not yet initialized, exit.");
-               goto fail;
-       }
-
-       deb_info("%s()\n", __func__);
-
-       err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
-
-       mutex_unlock(&state->fe_lock);
-
-       return err;
-fail:
-       return -ENODEV;
-}
-
-
-static int mxl111sf_ep6_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[adap->active_fe].priv;
-       int ret = 0;
-
-       deb_info("%s(%d)\n", __func__, onoff);
-
-       if (onoff) {
-               ret = mxl111sf_enable_usb_output(state);
-               mxl_fail(ret);
-               ret = mxl111sf_config_mpeg_in(state, 1, 1,
-                                             adap_state->ep6_clockphase,
-                                             0, 0);
-               mxl_fail(ret);
-#if 0
-       } else {
-               ret = mxl111sf_disable_656_port(state);
-               mxl_fail(ret);
-#endif
-       }
-
-       return ret;
-}
-
-static int mxl111sf_ep5_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int ret = 0;
-
-       deb_info("%s(%d)\n", __func__, onoff);
-
-       if (onoff) {
-               ret = mxl111sf_enable_usb_output(state);
-               mxl_fail(ret);
-
-               ret = mxl111sf_init_i2s_port(state, 200);
-               mxl_fail(ret);
-               ret = mxl111sf_config_i2s(state, 0, 15);
-               mxl_fail(ret);
-       } else {
-               ret = mxl111sf_disable_i2s_port(state);
-               mxl_fail(ret);
-       }
-       if (state->chip_rev > MXL111SF_V6)
-               ret = mxl111sf_config_spi(state, onoff);
-       mxl_fail(ret);
-
-       return ret;
-}
-
-static int mxl111sf_ep4_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int ret = 0;
-
-       deb_info("%s(%d)\n", __func__, onoff);
-
-       if (onoff) {
-               ret = mxl111sf_enable_usb_output(state);
-               mxl_fail(ret);
-       }
-
-       return ret;
-}
-
-/* ------------------------------------------------------------------------ */
-
-static struct lgdt3305_config hauppauge_lgdt3305_config = {
-       .i2c_addr           = 0xb2 >> 1,
-       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
-       .tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
-       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .qam_if_khz         = 6000,
-       .vsb_if_khz         = 6000,
-};
-
-static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-       int ret;
-
-       deb_adv("%s()\n", __func__);
-
-       /* save a pointer to the dvb_usb_device in device state */
-       state->d = d;
-       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
-       adap_state->gpio_mode = state->gpio_mode;
-       adap_state->device_mode = MXL_TUNER_MODE;
-       adap_state->ep6_clockphase = 1;
-
-       ret = mxl1x1sf_soft_reset(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_init_tuner_demod(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_enable_usb_output(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl1x1sf_top_master_ctrl(state, 1);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_init_port_expander(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       adap->fe_adap[fe_id].fe = dvb_attach(lgdt3305_attach,
-                                &hauppauge_lgdt3305_config,
-                                &adap->dev->i2c_adap);
-       if (adap->fe_adap[fe_id].fe) {
-               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-               return 0;
-       }
-       ret = -EIO;
-fail:
-       return ret;
-}
-
-static struct lg2160_config hauppauge_lg2160_config = {
-       .lg_chip            = LG2160,
-       .i2c_addr           = 0x1c >> 1,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .if_khz             = 6000,
-};
-
-static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-       int ret;
-
-       deb_adv("%s()\n", __func__);
-
-       /* save a pointer to the dvb_usb_device in device state */
-       state->d = d;
-       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-       adap_state->gpio_mode = state->gpio_mode;
-       adap_state->device_mode = MXL_TUNER_MODE;
-       adap_state->ep6_clockphase = 1;
-
-       ret = mxl1x1sf_soft_reset(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_init_tuner_demod(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_enable_usb_output(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl1x1sf_top_master_ctrl(state, 1);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_init_port_expander(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = get_chip_info(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-                             &hauppauge_lg2160_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe_adap[fe_id].fe) {
-               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-               return 0;
-       }
-       ret = -EIO;
-fail:
-       return ret;
-}
-
-static struct lg2160_config hauppauge_lg2161_1019_config = {
-       .lg_chip            = LG2161_1019,
-       .i2c_addr           = 0x1c >> 1,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .if_khz             = 6000,
-       .output_if          = 2, /* LG2161_OIF_SPI_MAS */
-};
-
-static struct lg2160_config hauppauge_lg2161_1040_config = {
-       .lg_chip            = LG2161_1040,
-       .i2c_addr           = 0x1c >> 1,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .if_khz             = 6000,
-       .output_if          = 4, /* LG2161_OIF_SPI_MAS */
-};
-
-static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-       int ret;
-
-       deb_adv("%s()\n", __func__);
-
-       /* save a pointer to the dvb_usb_device in device state */
-       state->d = d;
-       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-       adap_state->gpio_mode = state->gpio_mode;
-       adap_state->device_mode = MXL_TUNER_MODE;
-       adap_state->ep6_clockphase = 1;
-
-       ret = mxl1x1sf_soft_reset(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_init_tuner_demod(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_enable_usb_output(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl1x1sf_top_master_ctrl(state, 1);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_init_port_expander(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = get_chip_info(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-                             (MXL111SF_V8_200 == state->chip_rev) ?
-                             &hauppauge_lg2161_1040_config :
-                             &hauppauge_lg2161_1019_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe_adap[fe_id].fe) {
-               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-               return 0;
-       }
-       ret = -EIO;
-fail:
-       return ret;
-}
-
-static struct lg2160_config hauppauge_lg2161_1019_ep6_config = {
-       .lg_chip            = LG2161_1019,
-       .i2c_addr           = 0x1c >> 1,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .if_khz             = 6000,
-       .output_if          = 1, /* LG2161_OIF_SERIAL_TS */
-};
-
-static struct lg2160_config hauppauge_lg2161_1040_ep6_config = {
-       .lg_chip            = LG2161_1040,
-       .i2c_addr           = 0x1c >> 1,
-       .deny_i2c_rptr      = 1,
-       .spectral_inversion = 0,
-       .if_khz             = 6000,
-       .output_if          = 7, /* LG2161_OIF_SERIAL_TS */
-};
-
-static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-       int ret;
-
-       deb_adv("%s()\n", __func__);
-
-       /* save a pointer to the dvb_usb_device in device state */
-       state->d = d;
-       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
-       adap_state->gpio_mode = state->gpio_mode;
-       adap_state->device_mode = MXL_TUNER_MODE;
-       adap_state->ep6_clockphase = 0;
-
-       ret = mxl1x1sf_soft_reset(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_init_tuner_demod(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_enable_usb_output(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl1x1sf_top_master_ctrl(state, 1);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_init_port_expander(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = get_chip_info(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       adap->fe_adap[fe_id].fe = dvb_attach(lg2160_attach,
-                             (MXL111SF_V8_200 == state->chip_rev) ?
-                             &hauppauge_lg2161_1040_ep6_config :
-                             &hauppauge_lg2161_1019_ep6_config,
-                             &adap->dev->i2c_adap);
-       if (adap->fe_adap[fe_id].fe) {
-               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-               return 0;
-       }
-       ret = -EIO;
-fail:
-       return ret;
-}
-
-static struct mxl111sf_demod_config mxl_demod_config = {
-       .read_reg        = mxl111sf_read_reg,
-       .write_reg       = mxl111sf_write_reg,
-       .program_regs    = mxl111sf_ctrl_program_regs,
-};
-
-static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-       struct mxl111sf_adap_state *adap_state = adap->fe_adap[fe_id].priv;
-       int ret;
-
-       deb_adv("%s()\n", __func__);
-
-       /* save a pointer to the dvb_usb_device in device state */
-       state->d = d;
-       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
-       state->alt_mode = adap_state->alt_mode;
-
-       if (usb_set_interface(adap->dev->udev, 0, state->alt_mode) < 0)
-               err("set interface failed");
-
-       state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
-       adap_state->gpio_mode = state->gpio_mode;
-       adap_state->device_mode = MXL_SOC_MODE;
-       adap_state->ep6_clockphase = 1;
-
-       ret = mxl1x1sf_soft_reset(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl111sf_init_tuner_demod(state);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
-       if (mxl_fail(ret))
-               goto fail;
-
-       ret = mxl111sf_enable_usb_output(state);
-       if (mxl_fail(ret))
-               goto fail;
-       ret = mxl1x1sf_top_master_ctrl(state, 1);
-       if (mxl_fail(ret))
-               goto fail;
-
-       /* dont care if this fails */
-       mxl111sf_init_port_expander(state);
-
-       adap->fe_adap[fe_id].fe = dvb_attach(mxl111sf_demod_attach, state,
-                             &mxl_demod_config);
-       if (adap->fe_adap[fe_id].fe) {
-               adap_state->fe_init = adap->fe_adap[fe_id].fe->ops.init;
-               adap->fe_adap[fe_id].fe->ops.init = mxl111sf_adap_fe_init;
-               adap_state->fe_sleep = adap->fe_adap[fe_id].fe->ops.sleep;
-               adap->fe_adap[fe_id].fe->ops.sleep = mxl111sf_adap_fe_sleep;
-               return 0;
-       }
-       ret = -EIO;
-fail:
-       return ret;
-}
-
-static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
-                                       int antpath)
-{
-       return mxl111sf_idac_config(state, 1, 1,
-                                   (antpath == ANT_PATH_INTERNAL) ?
-                                   0x3f : 0x00, 0);
-}
-
-#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
-       err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
-           __func__, __LINE__, \
-           (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
-           pwr0, pwr1, pwr2, pwr3)
-
-#define ANT_HUNT_SLEEP 90
-#define ANT_EXT_TWEAK 0
-
-static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
-{
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-
-       int antctrl = dvb_usb_mxl111sf_rfswitch;
-
-       u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
-
-       /* FIXME: must force EXTERNAL for QAM - done elsewhere */
-       mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
-                             ANT_PATH_EXTERNAL : antctrl);
-
-       if (antctrl == ANT_PATH_AUTO) {
-#if 0
-               msleep(ANT_HUNT_SLEEP);
-#endif
-               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
-
-               mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-               msleep(ANT_HUNT_SLEEP);
-               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
-
-               mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-               msleep(ANT_HUNT_SLEEP);
-               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
-
-               mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
-               msleep(ANT_HUNT_SLEEP);
-               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
-
-               if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
-                       /* return with EXTERNAL enabled */
-                       mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
-                       DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
-                                  rxPwr0, rxPwr1, rxPwr2);
-               } else {
-                       /* return with INTERNAL enabled */
-                       DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
-                                  rxPwr0, rxPwr1, rxPwr2);
-               }
-       }
-       return 0;
-}
-
-static struct mxl111sf_tuner_config mxl_tuner_config = {
-       .if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
-       .invert_spectrum = 0,
-       .read_reg        = mxl111sf_read_reg,
-       .write_reg       = mxl111sf_write_reg,
-       .program_regs    = mxl111sf_ctrl_program_regs,
-       .top_master_ctrl = mxl1x1sf_top_master_ctrl,
-       .ant_hunt        = mxl111sf_ant_hunt,
-};
-
-static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
-{
-       struct dvb_usb_device *d = adap->dev;
-       struct mxl111sf_state *state = d->priv;
-       int fe_id = adap->num_frontends_initialized;
-
-       deb_adv("%s()\n", __func__);
-
-       if (NULL != dvb_attach(mxl111sf_tuner_attach,
-                              adap->fe_adap[fe_id].fe, state,
-                              &mxl_tuner_config))
-               return 0;
-
-       return -EIO;
-}
-
-static int mxl111sf_fe_ioctl_override(struct dvb_frontend *fe,
-                                     unsigned int cmd, void *parg,
-                                     unsigned int stage)
-{
-       int err = 0;
-
-       switch (stage) {
-       case DVB_FE_IOCTL_PRE:
-
-               switch (cmd) {
-               case FE_READ_SIGNAL_STRENGTH:
-                       err = fe->ops.tuner_ops.get_rf_strength(fe, parg);
-                       /* If no error occurs, prevent dvb-core from handling
-                        * this IOCTL, otherwise return the error */
-                       if (0 == err)
-                               err = 1;
-                       break;
-               }
-               break;
-
-       case DVB_FE_IOCTL_POST:
-               /* no post-ioctl handling required */
-               break;
-       }
-       return err;
-};
-
-static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
-{
-       return I2C_FUNC_I2C;
-}
-
-struct i2c_algorithm mxl111sf_i2c_algo = {
-       .master_xfer   = mxl111sf_i2c_xfer,
-       .functionality = mxl111sf_i2c_func,
-#ifdef NEED_ALGO_CONTROL
-       .algo_control = dummy_algo_control,
-#endif
-};
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties;
-static struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties;
-
-static int mxl111sf_probe(struct usb_interface *intf,
-                         const struct usb_device_id *id)
-{
-       struct dvb_usb_device *d = NULL;
-
-       deb_adv("%s()\n", __func__);
-
-       if (((dvb_usb_mxl111sf_isoc) &&
-            (0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_dvbt_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_atsc_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_atsc_mh_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_mh_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             ((dvb_usb_mxl111sf_spi) &&
-              (0 == dvb_usb_device_init(intf,
-                                        &mxl111sf_mercury_spi_isoc_properties,
-                                        THIS_MODULE, &d, adapter_nr) ||
-               0 == dvb_usb_device_init(intf,
-                                        &mxl111sf_mercury_mh_spi_isoc_properties,
-                                        THIS_MODULE, &d, adapter_nr))) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_mercury_tp_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_mercury_mh_tp_isoc_properties,
-                                      THIS_MODULE, &d, adapter_nr))) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_dvbt_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_atsc_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_atsc_mh_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_mh_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) ||
-           ((dvb_usb_mxl111sf_spi) &&
-            (0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_mercury_spi_bulk_properties,
-                                      THIS_MODULE, &d, adapter_nr) ||
-             0 == dvb_usb_device_init(intf,
-                                      &mxl111sf_mercury_mh_spi_bulk_properties,
-                                      THIS_MODULE, &d, adapter_nr))) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_mercury_tp_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) ||
-           0 == dvb_usb_device_init(intf,
-                                    &mxl111sf_mercury_mh_tp_bulk_properties,
-                                    THIS_MODULE, &d, adapter_nr) || 0) {
-
-               struct mxl111sf_state *state = d->priv;
-               static u8 eeprom[256];
-               struct i2c_client c;
-               int ret;
-
-               ret = get_chip_info(state);
-               if (mxl_fail(ret))
-                       err("failed to get chip info during probe");
-
-               mutex_init(&state->fe_lock);
-
-               if (state->chip_rev > MXL111SF_V6)
-                       mxl111sf_config_pin_mux_modes(state,
-                                                     PIN_MUX_TS_SPI_IN_MODE_1);
-
-               c.adapter = &d->i2c_adap;
-               c.addr = 0xa0 >> 1;
-
-               ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
-               if (mxl_fail(ret))
-                       return 0;
-               tveeprom_hauppauge_analog(&c, &state->tv,
-                                         (0x84 == eeprom[0xa0]) ?
-                                         eeprom + 0xa0 : eeprom + 0x80);
-#if 0
-               switch (state->tv.model) {
-               case 117001:
-               case 126001:
-               case 138001:
-                       break;
-               default:
-                       printk(KERN_WARNING "%s: warning: "
-                              "unknown hauppauge model #%d\n",
-                              __func__, state->tv.model);
-               }
-#endif
-               return 0;
-       }
-       err("Your device is not yet supported by this driver. "
-           "See kernellabs.com for more info");
-       return -EINVAL;
-}
-
-static struct usb_device_id mxl111sf_table[] = {
-/* 0 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600) }, /* ATSC+ IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601) }, /* ATSC         */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602) }, /*     +        */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603) }, /* ATSC+        */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604) }, /* DVBT         */
-/* 5 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609) }, /* ATSC  IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a) }, /*     + IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b) }, /* ATSC+ IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c) }, /* DVBT  IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653) }, /* ATSC+        */
-/*10 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b) }, /* ATSC+ IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700) }, /* ATSC+ sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701) }, /* ATSC  sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702) }, /*     + sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703) }, /* ATSC+ sw     */
-/*15 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704) }, /* DVBT  sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753) }, /* ATSC+ sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763) }, /* ATSC+ no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764) }, /* DVBT  no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853) }, /* ATSC+ sw     */
-/*20 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854) }, /* DVBT  sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863) }, /* ATSC+ no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864) }, /* DVBT  no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3) }, /* ATSC+ sw     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4) }, /* DVBT  sw     */
-/*25 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3) }, /* ATSC+ no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4) }, /* DVBT  no     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff) }, /* ATSC+        */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612) }, /*     +        */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613) }, /* ATSC+        */
-/*30 */        { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a) }, /*     + IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b) }, /* ATSC+ IR     */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757) }, /* ATSC+DVBT sw */
-       { USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767) }, /* ATSC+DVBT no */
-       {}              /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, mxl111sf_table);
-
-
-#define MXL111SF_EP4_BULK_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_BULK,                       \
-               .count = 5,                             \
-               .endpoint = 0x04,                       \
-               .u = {                                  \
-                       .bulk = {                       \
-                               .buffersize = 8192,     \
-                       }                               \
-               }                                       \
-       }
-
-/* FIXME: works for v6 but not v8 silicon */
-#define MXL111SF_EP4_ISOC_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep4_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_ISOC,                       \
-               .count = 5,                             \
-               .endpoint = 0x04,                       \
-               .u = {                                  \
-                       .isoc = {                       \
-                               .framesperurb = 96,     \
-                               /* FIXME: v6 SILICON: */        \
-                               .framesize = 564,       \
-                               .interval = 1,          \
-                       }                               \
-               }                                       \
-       }
-
-#define MXL111SF_EP5_BULK_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep5_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_BULK,                       \
-               .count = 5,                             \
-               .endpoint = 0x05,                       \
-               .u = {                                  \
-                       .bulk = {                       \
-                               .buffersize = 8192,     \
-                       }                               \
-               }                                       \
-       }
-
-#define MXL111SF_EP5_ISOC_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep5_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_ISOC,                       \
-               .count = 5,                             \
-               .endpoint = 0x05,                       \
-               .u = {                                  \
-                       .isoc = {                       \
-                               .framesperurb = 96,     \
-                               .framesize = 200,       \
-                               .interval = 1,          \
-                       }                               \
-               }                                       \
-       }
-
-#define MXL111SF_EP6_BULK_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep6_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_BULK,                       \
-               .count = 5,                             \
-               .endpoint = 0x06,                       \
-               .u = {                                  \
-                       .bulk = {                       \
-                               .buffersize = 8192,     \
-                       }                               \
-               }                                       \
-       }
-
-/* FIXME */
-#define MXL111SF_EP6_ISOC_STREAMING_CONFIG             \
-       .size_of_priv = sizeof(struct mxl111sf_adap_state), \
-       .streaming_ctrl = mxl111sf_ep6_streaming_ctrl,  \
-       .stream = {                                     \
-               .type = USB_ISOC,                       \
-               .count = 5,                             \
-               .endpoint = 0x06,                       \
-               .u = {                                  \
-                       .isoc = {                       \
-                               .framesperurb = 24,     \
-                               .framesize = 3072,      \
-                               .interval = 1,          \
-                       }                               \
-               }                                       \
-       }
-
-#define MXL111SF_DEFAULT_DEVICE_PROPERTIES                     \
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,                      \
-       .usb_ctrl = DEVICE_SPECIFIC,                            \
-       /* use usb alt setting 1 for EP4 ISOC transfer (dvb-t), \
-                                    EP6 BULK transfer (atsc/qam), \
-          use usb alt setting 2 for EP4 BULK transfer (dvb-t), \
-                                    EP6 ISOC transfer (atsc/qam), \
-       */                                                      \
-       .power_ctrl       = mxl111sf_power_ctrl,                \
-       .i2c_algo         = &mxl111sf_i2c_algo,                 \
-       .generic_bulk_ctrl_endpoint          = MXL_EP2_REG_WRITE, \
-       .generic_bulk_ctrl_endpoint_response = MXL_EP1_REG_READ, \
-       .size_of_priv     = sizeof(struct mxl111sf_state)
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               } },
-               },
-       },
-       .num_device_descs = 3,
-       .devices = {
-               {   "Hauppauge 126xxx DVBT (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[4], &mxl111sf_table[8],
-                         NULL },
-               },
-               {   "Hauppauge 117xxx DVBT (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[15], &mxl111sf_table[18],
-                         NULL },
-               },
-               {   "Hauppauge 138xxx DVBT (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[20], &mxl111sf_table[22],
-                         &mxl111sf_table[24], &mxl111sf_table[26],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_dvbt_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               } },
-               },
-       },
-       .num_device_descs = 3,
-       .devices = {
-               {   "Hauppauge 126xxx DVBT (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[4], &mxl111sf_table[8],
-                         NULL },
-               },
-               {   "Hauppauge 117xxx DVBT (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[15], &mxl111sf_table[18],
-                         NULL },
-               },
-               {   "Hauppauge 138xxx DVBT (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[20], &mxl111sf_table[22],
-                         &mxl111sf_table[24], &mxl111sf_table[26],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge 126xxx ATSC (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[1], &mxl111sf_table[5],
-                         NULL },
-               },
-               {   "Hauppauge 117xxx ATSC (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[12],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge 126xxx ATSC (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[1], &mxl111sf_table[5],
-                         NULL },
-               },
-               {   "Hauppauge 117xxx ATSC (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[12],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mh_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2160_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "HCW 126xxx (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[2], &mxl111sf_table[6],
-                         NULL },
-               },
-               {   "HCW 117xxx (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[13],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mh_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2160_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "HCW 126xxx (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[2], &mxl111sf_table[6],
-                         NULL },
-               },
-               {   "HCW 117xxx (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[13],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2160_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge 126xxx ATSC+ (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[0], &mxl111sf_table[3],
-                         &mxl111sf_table[7], &mxl111sf_table[9],
-                         &mxl111sf_table[10], NULL },
-               },
-               {   "Hauppauge 117xxx ATSC+ (bulk)",
-                       { NULL },
-                       { &mxl111sf_table[11], &mxl111sf_table[14],
-                         &mxl111sf_table[16], &mxl111sf_table[17],
-                         &mxl111sf_table[32], &mxl111sf_table[33],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_atsc_mh_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2160_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge 126xxx ATSC+ (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[0], &mxl111sf_table[3],
-                         &mxl111sf_table[7], &mxl111sf_table[9],
-                         &mxl111sf_table[10], NULL },
-               },
-               {   "Hauppauge 117xxx ATSC+ (isoc)",
-                       { NULL },
-                       { &mxl111sf_table[11], &mxl111sf_table[14],
-                         &mxl111sf_table[16], &mxl111sf_table[17],
-                         &mxl111sf_table[32], &mxl111sf_table[33],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge Mercury (spi-bulk)",
-                       { NULL },
-                       { &mxl111sf_table[19], &mxl111sf_table[21],
-                         &mxl111sf_table[23], &mxl111sf_table[25],
-                         NULL },
-               },
-               {   "Hauppauge WinTV-Aero-M (spi-bulk)",
-                       { NULL },
-                       { &mxl111sf_table[29], &mxl111sf_table[31],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_spi_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge Mercury (spi-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[19], &mxl111sf_table[21],
-                         &mxl111sf_table[23], &mxl111sf_table[25],
-                         NULL },
-               },
-               {   "Hauppauge WinTV-Aero-M (spi-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[29], &mxl111sf_table[31],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge Mercury (tp-bulk)",
-                       { NULL },
-                       { &mxl111sf_table[19], &mxl111sf_table[21],
-                         &mxl111sf_table[23], &mxl111sf_table[25],
-                         &mxl111sf_table[27], NULL },
-               },
-               {   "Hauppauge WinTV-Aero-M",
-                       { NULL },
-                       { &mxl111sf_table[29], &mxl111sf_table[31],
-                         NULL },
-               },
-       }
-};
-
-static struct dvb_usb_device_properties mxl111sf_mercury_tp_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 3,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_lgdt3305_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 2,
-       .devices = {
-               {   "Hauppauge Mercury (tp-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[19], &mxl111sf_table[21],
-                         &mxl111sf_table[23], &mxl111sf_table[25],
-                         &mxl111sf_table[27], NULL },
-               },
-               {   "Hauppauge WinTV-Aero-M (tp-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[29], &mxl111sf_table[31],
-                         NULL },
-               },
-       }
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 2,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 1,
-       .devices = {
-               {   "Hauppauge 126xxx (tp-bulk)",
-                       { NULL },
-                       { &mxl111sf_table[28], &mxl111sf_table[30],
-                         NULL },
-               },
-       }
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_tp_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 2,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_ep6_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP6_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 1,
-       .devices = {
-               {   "Hauppauge 126xxx (tp-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[28], &mxl111sf_table[30],
-                         NULL },
-               },
-       }
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_bulk_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 2,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_BULK_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_BULK_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 1,
-       .devices = {
-               {   "Hauppauge 126xxx (spi-bulk)",
-                       { NULL },
-                       { &mxl111sf_table[28], &mxl111sf_table[30],
-                         NULL },
-               },
-       }
-};
-
-static
-struct dvb_usb_device_properties mxl111sf_mercury_mh_spi_isoc_properties = {
-       MXL111SF_DEFAULT_DEVICE_PROPERTIES,
-
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .fe_ioctl_override = mxl111sf_fe_ioctl_override,
-               .num_frontends = 2,
-               .fe = {{
-                       .frontend_attach  = mxl111sf_attach_demod,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP4_ISOC_STREAMING_CONFIG,
-               },
-               {
-                       .caps = DVB_USB_ADAP_RECEIVES_RAW_PAYLOAD,
-
-                       .frontend_attach  = mxl111sf_lg2161_frontend_attach,
-                       .tuner_attach     = mxl111sf_attach_tuner,
-
-                       MXL111SF_EP5_ISOC_STREAMING_CONFIG,
-               }},
-               },
-       },
-       .num_device_descs = 1,
-       .devices = {
-               {   "Hauppauge 126xxx (spi-isoc)",
-                       { NULL },
-                       { &mxl111sf_table[28], &mxl111sf_table[30],
-                         NULL },
-               },
-       }
-};
-
-static struct usb_driver mxl111sf_driver = {
-       .name           = "dvb_usb_mxl111sf",
-       .probe          = mxl111sf_probe,
-       .disconnect     = dvb_usb_device_exit,
-       .id_table       = mxl111sf_table,
-};
-
-module_usb_driver(mxl111sf_driver);
-
-MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
-MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
-MODULE_VERSION("1.0");
-MODULE_LICENSE("GPL");
-
-/*
- * Local variables:
- * c-basic-offset: 8
- * End:
- */
diff --git a/drivers/media/dvb/frontends/ec100_priv.h b/drivers/media/dvb/frontends/ec100_priv.h
deleted file mode 100644 (file)
index 5c99014..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * E3C EC100 demodulator driver
- *
- * Copyright (C) 2009 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.
- *
- *    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 EC100_PRIV
-#define EC100_PRIV
-
-#define LOG_PREFIX "ec100"
-
-#define dprintk(var, level, args...) \
-       do { if ((var & level)) printk(args); } while (0)
-
-#define deb_info(args...) dprintk(ec100_debug, 0x01, args)
-
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
-
-#endif /* EC100_PRIV */
diff --git a/drivers/media/dvb/ngene/Kconfig b/drivers/media/dvb/ngene/Kconfig
deleted file mode 100644 (file)
index 64c8470..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-config DVB_NGENE
-       tristate "Micronas nGene support"
-       depends on DVB_CORE && PCI && I2C
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110x if !DVB_FE_CUSTOMISE
-       select DVB_STV090x if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_DRXK if !DVB_FE_CUSTOMISE
-       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         Support for Micronas PCI express cards with nGene bridge.
-
diff --git a/drivers/media/dvb/pluto2/Makefile b/drivers/media/dvb/pluto2/Makefile
deleted file mode 100644 (file)
index 7008223..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
diff --git a/drivers/media/dvb/siano/Kconfig b/drivers/media/dvb/siano/Kconfig
deleted file mode 100644 (file)
index bc6456e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-#
-# Siano Mobile Silicon Digital TV device configuration
-#
-
-config SMS_SIANO_MDTV
-       tristate "Siano SMS1xxx based MDTV receiver"
-       depends on DVB_CORE && RC_CORE && HAS_DMA
-       ---help---
-         Choose Y or M here if you have MDTV receiver with a Siano chipset.
-
-         To compile this driver as a module, choose M here
-         (The module will be called smsmdtv).
-
-         Further documentation on this driver can be found on the WWW
-         at http://www.siano-ms.com/
-
-if SMS_SIANO_MDTV
-menu "Siano module components"
-
-# Hardware interfaces support
-
-config SMS_USB_DRV
-       tristate "USB interface support"
-       depends on DVB_CORE && USB
-       ---help---
-         Choose if you would like to have Siano's support for USB interface
-
-config SMS_SDIO_DRV
-       tristate "SDIO interface support"
-       depends on DVB_CORE && MMC
-       ---help---
-         Choose if you would like to have Siano's support for SDIO interface
-endmenu
-endif # SMS_SIANO_MDTV
diff --git a/drivers/media/dvb/ttusb-budget/Makefile b/drivers/media/dvb/ttusb-budget/Makefile
deleted file mode 100644 (file)
index 8d6c4ac..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
-
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends
similarity index 51%
rename from drivers/media/dvb/firewire/Makefile
rename to drivers/media/firewire/Makefile
index 357b3aab186b2d1645419a073bee2e26acdf9ba7..239481344d7ca858692d8493a1a1c1c4cef2f9b3 100644 (file)
@@ -1,6 +1,6 @@
 obj-$(CONFIG_DVB_FIREDTV) += firedtv.o
 
-firedtv-y := firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
+firedtv-y += firedtv-avc.o firedtv-ci.o firedtv-dvb.o firedtv-fe.o firedtv-fw.o
 firedtv-$(CONFIG_DVB_FIREDTV_INPUT)    += firedtv-rc.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb-core
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
new file mode 100644 (file)
index 0000000..24d78e2
--- /dev/null
@@ -0,0 +1,591 @@
+#
+# Generic video config states
+#
+
+config VIDEO_BTCX
+       depends on PCI
+       tristate
+
+config VIDEO_TVEEPROM
+       tristate
+       depends on I2C
+
+#
+# Multimedia Video device configuration
+#
+
+if VIDEO_V4L2
+
+config VIDEO_IR_I2C
+       tristate "I2C module for IR" if !MEDIA_SUBDRV_AUTOSELECT
+       depends on I2C && RC_CORE
+       default y
+       ---help---
+         Most boards have an IR chip directly connected via GPIO. However,
+         some video boards have the IR connected via I2C bus.
+
+         If your board doesn't have an I2C IR chip, you may disable this
+         option.
+
+         In doubt, say Y.
+
+#
+# Encoder / Decoder module configuration
+#
+
+menu "Encoders, decoders, sensors and other helper chips"
+       visible if !MEDIA_SUBDRV_AUTOSELECT
+
+comment "Audio decoders, processors and mixers"
+
+config VIDEO_TVAUDIO
+       tristate "Simple audio decoder chips"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for several audio decoder chips found on some bt8xx boards:
+         Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
+                  tea6320, tea6420, tda8425, ta8874z.
+         Microchip: pic16c54 based design on ProVideo PV951 board.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvaudio.
+
+config VIDEO_TDA7432
+       tristate "Philips TDA7432 audio processor"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for tda7432 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda7432.
+
+config VIDEO_TDA9840
+       tristate "Philips TDA9840 audio processor"
+       depends on I2C
+       ---help---
+         Support for tda9840 audio decoder chip found on some Zoran boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tda9840.
+
+config VIDEO_TEA6415C
+       tristate "Philips TEA6415C audio processor"
+       depends on I2C
+       ---help---
+         Support for tea6415c audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6415c.
+
+config VIDEO_TEA6420
+       tristate "Philips TEA6420 audio processor"
+       depends on I2C
+       ---help---
+         Support for tea6420 audio decoder chip found on some bt8xx boards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tea6420.
+
+config VIDEO_MSP3400
+       tristate "Micronas MSP34xx audio decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Micronas MSP34xx series of audio decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called msp3400.
+
+config VIDEO_CS5345
+       tristate "Cirrus Logic CS5345 audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Cirrus Logic CS5345 24-bit, 192 kHz
+         stereo A/D converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cs5345.
+
+config VIDEO_CS53L32A
+       tristate "Cirrus Logic CS53L32A audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Cirrus Logic CS53L32A low voltage
+         stereo A/D converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cs53l32a.
+
+config VIDEO_TLV320AIC23B
+       tristate "Texas Instruments TLV320AIC23B audio codec"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TLV320AIC23B audio codec.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tlv320aic23b.
+
+config VIDEO_WM8775
+       tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Wolfson Microelectronics WM8775 high
+         performance stereo A/D Converter with a 4 channel input mixer.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8775.
+
+config VIDEO_WM8739
+       tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Wolfson Microelectronics WM8739
+         stereo A/D Converter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called wm8739.
+
+config VIDEO_VP27SMPX
+       tristate "Panasonic VP27s internal MPX"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the internal MPX of the Panasonic VP27s tuner.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vp27smpx.
+
+comment "RDS decoders"
+
+config VIDEO_SAA6588
+       tristate "SAA6588 Radio Chip RDS decoder support"
+       depends on VIDEO_V4L2 && I2C
+
+       help
+         Support for this Radio Data System (RDS) decoder. This allows
+         seeing radio station identification transmitted using this
+         standard.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa6588.
+
+comment "Video decoders"
+
+config VIDEO_ADV7180
+       tristate "Analog Devices ADV7180 decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7180 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7180.
+
+config VIDEO_ADV7183
+       tristate "Analog Devices ADV7183 decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         V4l2 subdevice driver for the Analog Devices
+         ADV7183 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7183.
+
+config VIDEO_ADV7604
+       tristate "Analog Devices ADV7604 decoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices ADV7604 video decoder.
+
+         This is a Analog Devices Component/Graphics Digitizer
+         with 4:1 Multiplexed HDMI Receiver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7604.
+
+config VIDEO_BT819
+       tristate "BT819A VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT819A video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt819.
+
+config VIDEO_BT856
+       tristate "BT856 VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT856 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt856.
+
+config VIDEO_BT866
+       tristate "BT866 VideoStream decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for BT866 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bt866.
+
+config VIDEO_KS0127
+       tristate "KS0127 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for KS0127 video decoder.
+
+         This chip is used on AverMedia AVS6EYES Zoran-based MJPEG
+         cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ks0127.
+
+config VIDEO_SAA7110
+       tristate "Philips SAA7110 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7110 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7110.
+
+config VIDEO_SAA711X
+       tristate "Philips SAA7111/3/4/5 video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7111/3/4/5 video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7115.
+
+config VIDEO_SAA7191
+       tristate "Philips SAA7191 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7191 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7191.
+
+config VIDEO_TVP514X
+       tristate "Texas Instruments TVP514x video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the TI TVP5146/47
+         decoder. It is currently working with the TI OMAP3 camera
+         controller.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp514x.
+
+config VIDEO_TVP5150
+       tristate "Texas Instruments TVP5150 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TVP5150 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp5150.
+
+config VIDEO_TVP7002
+       tristate "Texas Instruments TVP7002 video decoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Texas Instruments TVP7002 video decoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called tvp7002.
+
+config VIDEO_VPX3220
+       tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for VPX322x video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vpx3220.
+
+comment "Video and audio decoders"
+
+config VIDEO_SAA717X
+       tristate "Philips SAA7171/3/4 audio/video decoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7171/3/4 audio/video decoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa717x.
+
+source "drivers/media/i2c/cx25840/Kconfig"
+
+comment "MPEG video encoders"
+
+config VIDEO_CX2341X
+       tristate "Conexant CX2341x MPEG encoders"
+       depends on VIDEO_V4L2
+       ---help---
+         Support for the Conexant CX23416 MPEG encoders
+         and CX23415 MPEG encoder/decoders.
+
+         This module currently supports the encoding functions only.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx2341x.
+
+comment "Video encoders"
+
+config VIDEO_SAA7127
+       tristate "Philips SAA7127/9 digital video encoders"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7127/9 digital video encoders.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7127.
+
+config VIDEO_SAA7185
+       tristate "Philips SAA7185 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Philips SAA7185 video encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called saa7185.
+
+config VIDEO_ADV7170
+       tristate "Analog Devices ADV7170 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7170 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7170.
+
+config VIDEO_ADV7175
+       tristate "Analog Devices ADV7175 video encoder"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the Analog Devices ADV7175 video encoder driver
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7175.
+
+config VIDEO_ADV7343
+       tristate "ADV7343 video encoder"
+       depends on I2C
+       help
+         Support for Analog Devices I2C bus based ADV7343 encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7343.
+
+config VIDEO_ADV7393
+       tristate "ADV7393 video encoder"
+       depends on I2C
+       help
+         Support for Analog Devices I2C bus based ADV7393 encoder.
+
+         To compile this driver as a module, choose M here: the
+         module will be called adv7393.
+
+config VIDEO_AD9389B
+       tristate "Analog Devices AD9389B encoder"
+       depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         Support for the Analog Devices AD9389B video encoder.
+
+         This is a Analog Devices HDMI transmitter.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ad9389b.
+
+config VIDEO_AK881X
+       tristate "AK8813/AK8814 video encoders"
+       depends on I2C
+       help
+         Video output driver for AKM AK8813 and AK8814 TV encoders
+
+comment "Camera sensor devices"
+
+config VIDEO_APTINA_PLL
+       tristate
+
+config VIDEO_SMIAPP_PLL
+       tristate
+
+config VIDEO_OV7670
+       tristate "OmniVision OV7670 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the OmniVision
+         OV7670 VGA camera.  It currently only works with the M88ALP01
+         controller.
+
+config VIDEO_VS6624
+       tristate "ST VS6624 sensor support"
+       depends on VIDEO_V4L2 && I2C
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the ST VS6624
+         camera.
+
+         To compile this driver as a module, choose M here: the
+         module will be called vs6624.
+
+config VIDEO_MT9M032
+       tristate "MT9M032 camera sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       select VIDEO_APTINA_PLL
+       ---help---
+         This driver supports MT9M032 camera sensors from Aptina, monochrome
+         models only.
+
+config VIDEO_MT9P031
+       tristate "Aptina MT9P031 support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       select VIDEO_APTINA_PLL
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Aptina
+         (Micron) mt9p031 5 Mpixel camera.
+
+config VIDEO_MT9T001
+       tristate "Aptina MT9T001 support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Aptina
+         (Micron) mt0t001 3 Mpixel camera.
+
+config VIDEO_MT9V011
+       tristate "Micron mt9v011 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Micron
+         mt0v011 1.3 Mpixel camera.  It currently only works with the
+         em28xx driver.
+
+config VIDEO_MT9V032
+       tristate "Micron MT9V032 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a Video4Linux2 sensor-level driver for the Micron
+         MT9V032 752x480 CMOS sensor.
+
+config VIDEO_TCM825X
+       tristate "TCM825x camera sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a driver for the Toshiba TCM825x VGA camera sensor.
+         It is used for example in Nokia N800.
+
+config VIDEO_SR030PC30
+       tristate "Siliconfile SR030PC30 sensor support"
+       depends on I2C && VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This driver supports SR030PC30 VGA camera from Siliconfile
+
+config VIDEO_NOON010PC30
+       tristate "Siliconfile NOON010PC30 sensor support"
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This driver supports NOON010PC30 CIF camera from Siliconfile
+
+source "drivers/media/i2c/m5mols/Kconfig"
+
+config VIDEO_S5K6AA
+       tristate "Samsung S5K6AAFX sensor support"
+       depends on MEDIA_CAMERA_SUPPORT
+       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+       ---help---
+         This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
+         camera sensor with an embedded SoC image signal processor.
+
+config VIDEO_S5K4ECGX
+        tristate "Samsung S5K4ECGX sensor support"
+        depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
+        ---help---
+          This is a V4L2 sensor-level driver for Samsung S5K4ECGX 5M
+          camera sensor with an embedded SoC image signal processor.
+
+source "drivers/media/i2c/smiapp/Kconfig"
+
+comment "Flash devices"
+
+config VIDEO_ADP1653
+       tristate "ADP1653 flash support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a driver for the ADP1653 flash controller. It is used for
+         example in Nokia N900.
+
+config VIDEO_AS3645A
+       tristate "AS3645A flash driver support"
+       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
+       depends on MEDIA_CAMERA_SUPPORT
+       ---help---
+         This is a driver for the AS3645A and LM3555 flash controllers. It has
+         build in control for flash, torch and indicator LEDs.
+
+comment "Video improvement chips"
+
+config VIDEO_UPD64031A
+       tristate "NEC Electronics uPD64031A Ghost Reduction"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the NEC Electronics uPD64031A Ghost Reduction
+         video chip. It is most often found in NTSC TV cards made for
+         Japan and is used to reduce the 'ghosting' effect that can
+         be present in analog TV broadcasts.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64031a.
+
+config VIDEO_UPD64083
+       tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+         Support for the NEC Electronics uPD64083 3-Dimensional Y/C
+         separation video chip. It is used to improve the quality of
+         the colors of a composite signal.
+
+         To compile this driver as a module, choose M here: the
+         module will be called upd64083.
+
+comment "Miscelaneous helper chips"
+
+config VIDEO_THS7303
+       tristate "THS7303 Video Amplifier"
+       depends on I2C
+       help
+         Support for TI THS7303 video amplifier
+
+         To compile this driver as a module, choose M here: the
+         module will be called ths7303.
+
+config VIDEO_M52790
+       tristate "Mitsubishi M52790 A/V switch"
+       depends on VIDEO_V4L2 && I2C
+       ---help---
+        Support for the Mitsubishi M52790 A/V switch.
+
+        To compile this driver as a module, choose M here: the
+        module will be called m52790.
+endmenu
+
+menu "Sensors used on soc_camera driver"
+
+if SOC_CAMERA
+       source "drivers/media/i2c/soc_camera/Kconfig"
+endif
+
+endmenu
+
+endif
diff --git a/drivers/media/i2c/Makefile b/drivers/media/i2c/Makefile
new file mode 100644 (file)
index 0000000..b1d62df
--- /dev/null
@@ -0,0 +1,67 @@
+msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
+obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
+
+obj-$(CONFIG_VIDEO_SMIAPP)     += smiapp/
+obj-$(CONFIG_VIDEO_CX25840) += cx25840/
+obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
+obj-y                          += soc_camera/
+
+obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
+obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
+obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
+obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
+obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
+obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
+obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
+obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
+obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
+obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
+obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
+obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
+obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
+obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
+obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
+obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
+obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
+obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
+obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
+obj-$(CONFIG_VIDEO_ADV7604) += adv7604.o
+obj-$(CONFIG_VIDEO_AD9389B) += ad9389b.o
+obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
+obj-$(CONFIG_VIDEO_VS6624)  += vs6624.o
+obj-$(CONFIG_VIDEO_BT819) += bt819.o
+obj-$(CONFIG_VIDEO_BT856) += bt856.o
+obj-$(CONFIG_VIDEO_BT866) += bt866.o
+obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
+obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
+obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
+obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
+obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
+obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
+obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
+obj-$(CONFIG_VIDEO_M52790) += m52790.o
+obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
+obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
+obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
+obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
+obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
+obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
+obj-$(CONFIG_VIDEO_OV7670)     += ov7670.o
+obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
+obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
+obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
+obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
+obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
+obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
+obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
+obj-$(CONFIG_VIDEO_SR030PC30)  += sr030pc30.o
+obj-$(CONFIG_VIDEO_NOON010PC30)        += noon010pc30.o
+obj-$(CONFIG_VIDEO_S5K6AA)     += s5k6aa.o
+obj-$(CONFIG_VIDEO_S5K4ECGX)   += s5k4ecgx.o
+obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
+obj-$(CONFIG_VIDEO_AS3645A)    += as3645a.o
+obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
+obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
+obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
+obj-$(CONFIG_VIDEO_AK881X)             += ak881x.o
+obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
diff --git a/drivers/media/i2c/ad9389b.c b/drivers/media/i2c/ad9389b.c
new file mode 100644 (file)
index 0000000..c2886b6
--- /dev/null
@@ -0,0 +1,1328 @@
+/*
+ * Analog Devices AD9389B/AD9889B video encoder driver
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ */
+
+/*
+ * References (c = chapter, p = page):
+ * REF_01 - Analog Devices, Programming Guide, AD9889B/AD9389B,
+ * HDMI Transitter, Rev. A, October 2010
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ctrls.h>
+#include <media/ad9389b.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+
+MODULE_DESCRIPTION("Analog Devices AD9389B/AD9889B video encoder driver");
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Martin Bugge <marbugge@cisco.com>");
+MODULE_LICENSE("GPL");
+
+#define MASK_AD9389B_EDID_RDY_INT   0x04
+#define MASK_AD9389B_MSEN_INT       0x40
+#define MASK_AD9389B_HPD_INT        0x80
+
+#define MASK_AD9389B_HPD_DETECT     0x40
+#define MASK_AD9389B_MSEN_DETECT    0x20
+#define MASK_AD9389B_EDID_RDY       0x10
+
+#define EDID_MAX_RETRIES (8)
+#define EDID_DELAY 250
+#define EDID_MAX_SEGM 8
+
+/*
+**********************************************************************
+*
+*  Arrays with configuration parameters for the AD9389B
+*
+**********************************************************************
+*/
+
+struct i2c_reg_value {
+       u8 reg;
+       u8 value;
+};
+
+struct ad9389b_state_edid {
+       /* total number of blocks */
+       u32 blocks;
+       /* Number of segments read */
+       u32 segments;
+       u8 data[EDID_MAX_SEGM * 256];
+       /* Number of EDID read retries left */
+       unsigned read_retries;
+};
+
+struct ad9389b_state {
+       struct ad9389b_platform_data pdata;
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+       struct v4l2_ctrl_handler hdl;
+       int chip_revision;
+       /* Is the ad9389b powered on? */
+       bool power_on;
+       /* Did we receive hotplug and rx-sense signals? */
+       bool have_monitor;
+       /* timings from s_dv_timings */
+       struct v4l2_dv_timings dv_timings;
+       /* controls */
+       struct v4l2_ctrl *hdmi_mode_ctrl;
+       struct v4l2_ctrl *hotplug_ctrl;
+       struct v4l2_ctrl *rx_sense_ctrl;
+       struct v4l2_ctrl *have_edid0_ctrl;
+       struct v4l2_ctrl *rgb_quantization_range_ctrl;
+       struct i2c_client *edid_i2c_client;
+       struct ad9389b_state_edid edid;
+       /* Running counter of the number of detected EDIDs (for debugging) */
+       unsigned edid_detect_counter;
+       struct workqueue_struct *work_queue;
+       struct delayed_work edid_handler; /* work entry */
+};
+
+static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd);
+static bool ad9389b_check_edid_status(struct v4l2_subdev *sd);
+static void ad9389b_setup(struct v4l2_subdev *sd);
+static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq);
+
+static inline struct ad9389b_state *get_ad9389b_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct ad9389b_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+       return &container_of(ctrl->handler, struct ad9389b_state, hdl)->sd;
+}
+
+/* ------------------------ I2C ----------------------------------------------- */
+
+static int ad9389b_rd(struct v4l2_subdev *sd, u8 reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return i2c_smbus_read_byte_data(client, reg);
+}
+
+static int ad9389b_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+       int i;
+
+       for (i = 0; i < 3; i++) {
+               ret = i2c_smbus_write_byte_data(client, reg, val);
+               if (ret == 0)
+                       return 0;
+       }
+       v4l2_err(sd, "I2C Write Problem\n");
+       return ret;
+}
+
+/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
+   and then the value-mask (to be OR-ed). */
+static inline void ad9389b_wr_and_or(struct v4l2_subdev *sd, u8 reg,
+                                               u8 clr_mask, u8 val_mask)
+{
+       ad9389b_wr(sd, reg, (ad9389b_rd(sd, reg) & clr_mask) | val_mask);
+}
+
+static void ad9389b_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       int i;
+
+       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+       for (i = 0; i < len; i++)
+               buf[i] = i2c_smbus_read_byte_data(state->edid_i2c_client, i);
+}
+
+static inline bool ad9389b_have_hotplug(struct v4l2_subdev *sd)
+{
+       return ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT;
+}
+
+static inline bool ad9389b_have_rx_sense(struct v4l2_subdev *sd)
+{
+       return ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT;
+}
+
+static void ad9389b_csc_conversion_mode(struct v4l2_subdev *sd, u8 mode)
+{
+       ad9389b_wr_and_or(sd, 0x17, 0xe7, (mode & 0x3)<<3);
+       ad9389b_wr_and_or(sd, 0x18, 0x9f, (mode & 0x3)<<5);
+}
+
+static void ad9389b_csc_coeff(struct v4l2_subdev *sd,
+                             u16 A1, u16 A2, u16 A3, u16 A4,
+                             u16 B1, u16 B2, u16 B3, u16 B4,
+                             u16 C1, u16 C2, u16 C3, u16 C4)
+{
+       /* A */
+       ad9389b_wr_and_or(sd, 0x18, 0xe0, A1>>8);
+       ad9389b_wr(sd, 0x19, A1);
+       ad9389b_wr_and_or(sd, 0x1A, 0xe0, A2>>8);
+       ad9389b_wr(sd, 0x1B, A2);
+       ad9389b_wr_and_or(sd, 0x1c, 0xe0, A3>>8);
+       ad9389b_wr(sd, 0x1d, A3);
+       ad9389b_wr_and_or(sd, 0x1e, 0xe0, A4>>8);
+       ad9389b_wr(sd, 0x1f, A4);
+
+       /* B */
+       ad9389b_wr_and_or(sd, 0x20, 0xe0, B1>>8);
+       ad9389b_wr(sd, 0x21, B1);
+       ad9389b_wr_and_or(sd, 0x22, 0xe0, B2>>8);
+       ad9389b_wr(sd, 0x23, B2);
+       ad9389b_wr_and_or(sd, 0x24, 0xe0, B3>>8);
+       ad9389b_wr(sd, 0x25, B3);
+       ad9389b_wr_and_or(sd, 0x26, 0xe0, B4>>8);
+       ad9389b_wr(sd, 0x27, B4);
+
+       /* C */
+       ad9389b_wr_and_or(sd, 0x28, 0xe0, C1>>8);
+       ad9389b_wr(sd, 0x29, C1);
+       ad9389b_wr_and_or(sd, 0x2A, 0xe0, C2>>8);
+       ad9389b_wr(sd, 0x2B, C2);
+       ad9389b_wr_and_or(sd, 0x2C, 0xe0, C3>>8);
+       ad9389b_wr(sd, 0x2D, C3);
+       ad9389b_wr_and_or(sd, 0x2E, 0xe0, C4>>8);
+       ad9389b_wr(sd, 0x2F, C4);
+}
+
+static void ad9389b_csc_rgb_full2limit(struct v4l2_subdev *sd, bool enable)
+{
+       if (enable) {
+               u8 csc_mode = 0;
+
+               ad9389b_csc_conversion_mode(sd, csc_mode);
+               ad9389b_csc_coeff(sd,
+                                 4096-564, 0, 0, 256,
+                                 0, 4096-564, 0, 256,
+                                 0, 0, 4096-564, 256);
+               /* enable CSC */
+               ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x1);
+               /* AVI infoframe: Limited range RGB (16-235) */
+               ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x02);
+       } else {
+               /* disable CSC */
+               ad9389b_wr_and_or(sd, 0x3b, 0xfe, 0x0);
+               /* AVI infoframe: Full range RGB (0-255) */
+               ad9389b_wr_and_or(sd, 0xcd, 0xf9, 0x04);
+       }
+}
+
+static void ad9389b_set_IT_content_AVI_InfoFrame(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+               /* CEA format, not IT  */
+               ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x00);
+       } else {
+               /* IT format */
+               ad9389b_wr_and_or(sd, 0xcd, 0xbf, 0x40);
+       }
+}
+
+static int ad9389b_set_rgb_quantization_mode(struct v4l2_subdev *sd, struct v4l2_ctrl *ctrl)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       switch (ctrl->val) {
+       case V4L2_DV_RGB_RANGE_AUTO:
+               /* automatic */
+               if (state->dv_timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+                       /* cea format, RGB limited range (16-235) */
+                       ad9389b_csc_rgb_full2limit(sd, true);
+               } else {
+                       /* not cea format, RGB full range (0-255) */
+                       ad9389b_csc_rgb_full2limit(sd, false);
+               }
+               break;
+       case V4L2_DV_RGB_RANGE_LIMITED:
+               /* RGB limited range (16-235) */
+               ad9389b_csc_rgb_full2limit(sd, true);
+               break;
+       case V4L2_DV_RGB_RANGE_FULL:
+               /* RGB full range (0-255) */
+               ad9389b_csc_rgb_full2limit(sd, false);
+               break;
+       default:
+               return -EINVAL;
+       }
+       return 0;
+}
+
+static void ad9389b_set_manual_pll_gear(struct v4l2_subdev *sd, u32 pixelclock)
+{
+       u8 gear;
+
+       /* Workaround for TMDS PLL problem
+        * The TMDS PLL in AD9389b change gear when the chip is heated above a
+        * certain temperature. The output is disabled when the PLL change gear
+        * so the monitor has to lock on the signal again. A workaround for
+        * this is to use the manual PLL gears. This is a solution from Analog
+        * Devices that is not documented in the datasheets.
+        * 0x98 [7] = enable manual gearing. 0x98 [6:4] = gear
+        *
+        * The pixel frequency ranges are based on readout of the gear the
+        * automatic gearing selects for different pixel clocks
+        * (read from 0x9e [3:1]).
+        */
+
+       if (pixelclock > 140000000)
+               gear = 0xc0; /* 4th gear */
+       else if (pixelclock > 117000000)
+               gear = 0xb0; /* 3rd gear */
+       else if (pixelclock > 87000000)
+               gear = 0xa0; /* 2nd gear */
+       else if (pixelclock > 60000000)
+               gear = 0x90; /* 1st gear */
+       else
+               gear = 0x80; /* 0th gear */
+
+       ad9389b_wr_and_or(sd, 0x98, 0x0f, gear);
+}
+
+/* ------------------------------ CTRL OPS ------------------------------ */
+
+static int ad9389b_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = to_sd(ctrl);
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       v4l2_dbg(1, debug, sd,
+               "%s: ctrl id: %d, ctrl->val %d\n", __func__, ctrl->id, ctrl->val);
+
+       if (state->hdmi_mode_ctrl == ctrl) {
+               /* Set HDMI or DVI-D */
+               ad9389b_wr_and_or(sd, 0xaf, 0xfd,
+                               ctrl->val == V4L2_DV_TX_MODE_HDMI ? 0x02 : 0x00);
+               return 0;
+       }
+       if (state->rgb_quantization_range_ctrl == ctrl)
+               return ad9389b_set_rgb_quantization_mode(sd, ctrl);
+       return -EINVAL;
+}
+
+static const struct v4l2_ctrl_ops ad9389b_ctrl_ops = {
+       .s_ctrl = ad9389b_s_ctrl,
+};
+
+/* ---------------------------- CORE OPS ------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int ad9389b_g_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       reg->val = ad9389b_rd(sd, reg->reg & 0xff);
+       reg->size = 1;
+       return 0;
+}
+
+static int ad9389b_s_register(struct v4l2_subdev *sd, struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       ad9389b_wr(sd, reg->reg & 0xff, reg->val & 0xff);
+       return 0;
+}
+#endif
+
+static int ad9389b_g_chip_ident(struct v4l2_subdev *sd, struct v4l2_dbg_chip_ident *chip)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_AD9389B, 0);
+}
+
+static int ad9389b_log_status(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       struct ad9389b_state_edid *edid = &state->edid;
+
+       static const char * const states[] = {
+               "in reset",
+               "reading EDID",
+               "idle",
+               "initializing HDCP",
+               "HDCP enabled",
+               "initializing HDCP repeater",
+               "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"
+       };
+       static const char * const errors[] = {
+               "no error",
+               "bad receiver BKSV",
+               "Ri mismatch",
+               "Pj mismatch",
+               "i2c error",
+               "timed out",
+               "max repeater cascade exceeded",
+               "hash check failed",
+               "too many devices",
+               "9", "A", "B", "C", "D", "E", "F"
+       };
+
+       u8 manual_gear;
+
+       v4l2_info(sd, "chip revision %d\n", state->chip_revision);
+       v4l2_info(sd, "power %s\n", state->power_on ? "on" : "off");
+       v4l2_info(sd, "%s hotplug, %s Rx Sense, %s EDID (%d block(s))\n",
+                       (ad9389b_rd(sd, 0x42) & MASK_AD9389B_HPD_DETECT) ?
+                                                       "detected" : "no",
+                       (ad9389b_rd(sd, 0x42) & MASK_AD9389B_MSEN_DETECT) ?
+                                                       "detected" : "no",
+                       edid->segments ? "found" : "no", edid->blocks);
+       if (state->have_monitor) {
+               v4l2_info(sd, "%s output %s\n",
+                                 (ad9389b_rd(sd, 0xaf) & 0x02) ?
+                                 "HDMI" : "DVI-D",
+                                 (ad9389b_rd(sd, 0xa1) & 0x3c) ?
+                                 "disabled" : "enabled");
+       }
+       v4l2_info(sd, "ad9389b: %s\n", (ad9389b_rd(sd, 0xb8) & 0x40) ?
+                                       "encrypted" : "no encryption");
+       v4l2_info(sd, "state: %s, error: %s, detect count: %u, msk/irq: %02x/%02x\n",
+                       states[ad9389b_rd(sd, 0xc8) & 0xf],
+                       errors[ad9389b_rd(sd, 0xc8) >> 4],
+                       state->edid_detect_counter,
+                       ad9389b_rd(sd, 0x94), ad9389b_rd(sd, 0x96));
+       manual_gear = ad9389b_rd(sd, 0x98) & 0x80;
+       v4l2_info(sd, "ad9389b: RGB quantization: %s range\n",
+                       ad9389b_rd(sd, 0x3b) & 0x01 ? "limited" : "full");
+       v4l2_info(sd, "ad9389b: %s gear %d\n",
+                 manual_gear ? "manual" : "automatic",
+                 manual_gear ? ((ad9389b_rd(sd, 0x98) & 0x70) >> 4) :
+                               ((ad9389b_rd(sd, 0x9e) & 0x0e) >> 1));
+       if (state->have_monitor) {
+               if (ad9389b_rd(sd, 0xaf) & 0x02) {
+                       /* HDMI only */
+                       u8 manual_cts = ad9389b_rd(sd, 0x0a) & 0x80;
+                       u32 N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
+                                ad9389b_rd(sd, 0x02) << 8 |
+                                ad9389b_rd(sd, 0x03);
+                       u8 vic_detect = ad9389b_rd(sd, 0x3e) >> 2;
+                       u8 vic_sent = ad9389b_rd(sd, 0x3d) & 0x3f;
+                       u32 CTS;
+
+                       if (manual_cts)
+                               CTS = (ad9389b_rd(sd, 0x07) & 0xf) << 16 |
+                                      ad9389b_rd(sd, 0x08) << 8 |
+                                      ad9389b_rd(sd, 0x09);
+                       else
+                               CTS = (ad9389b_rd(sd, 0x04) & 0xf) << 16 |
+                                      ad9389b_rd(sd, 0x05) << 8 |
+                                      ad9389b_rd(sd, 0x06);
+                       N = (ad9389b_rd(sd, 0x01) & 0xf) << 16 |
+                            ad9389b_rd(sd, 0x02) << 8 |
+                            ad9389b_rd(sd, 0x03);
+
+                       v4l2_info(sd, "ad9389b: CTS %s mode: N %d, CTS %d\n",
+                               manual_cts ? "manual" : "automatic", N, CTS);
+
+                       v4l2_info(sd, "ad9389b: VIC: detected %d, sent %d\n",
+                               vic_detect, vic_sent);
+               }
+       }
+       if (state->dv_timings.type == V4L2_DV_BT_656_1120) {
+               struct v4l2_bt_timings *bt = bt = &state->dv_timings.bt;
+               u32 frame_width = bt->width + bt->hfrontporch +
+                       bt->hsync + bt->hbackporch;
+               u32 frame_height = bt->height + bt->vfrontporch +
+                       bt->vsync + bt->vbackporch;
+               u32 frame_size = frame_width * frame_height;
+
+               v4l2_info(sd, "timings: %ux%u%s%u (%ux%u). Pix freq. = %u Hz. Polarities = 0x%x\n",
+                       bt->width, bt->height, bt->interlaced ? "i" : "p",
+                       frame_size > 0 ?  (unsigned)bt->pixelclock / frame_size : 0,
+                       frame_width, frame_height,
+                       (unsigned)bt->pixelclock, bt->polarities);
+       } else {
+               v4l2_info(sd, "no timings set\n");
+       }
+       return 0;
+}
+
+/* Power up/down ad9389b */
+static int ad9389b_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       struct ad9389b_platform_data *pdata = &state->pdata;
+       const int retries = 20;
+       int i;
+
+       v4l2_dbg(1, debug, sd, "%s: power %s\n", __func__, on ? "on" : "off");
+
+       state->power_on = on;
+
+       if (!on) {
+               /* Power down */
+               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
+               return true;
+       }
+
+       /* Power up */
+       /* The ad9389b does not always come up immediately.
+          Retry multiple times. */
+       for (i = 0; i < retries; i++) {
+               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x0);
+               if ((ad9389b_rd(sd, 0x41) & 0x40) == 0)
+                       break;
+               ad9389b_wr_and_or(sd, 0x41, 0xbf, 0x40);
+               msleep(10);
+       }
+       if (i == retries) {
+               v4l2_dbg(1, debug, sd, "failed to powerup the ad9389b\n");
+               ad9389b_s_power(sd, 0);
+               return false;
+       }
+       if (i > 1)
+               v4l2_dbg(1, debug, sd,
+                       "needed %d retries to powerup the ad9389b\n", i);
+
+       /* Select chip: AD9389B */
+       ad9389b_wr_and_or(sd, 0xba, 0xef, 0x10);
+
+       /* Reserved registers that must be set according to REF_01 p. 11*/
+       ad9389b_wr_and_or(sd, 0x98, 0xf0, 0x07);
+       ad9389b_wr(sd, 0x9c, 0x38);
+       ad9389b_wr_and_or(sd, 0x9d, 0xfc, 0x01);
+
+       /* Differential output drive strength */
+       if (pdata->diff_data_drive_strength > 0)
+               ad9389b_wr(sd, 0xa2, pdata->diff_data_drive_strength);
+       else
+               ad9389b_wr(sd, 0xa2, 0x87);
+
+       if (pdata->diff_clk_drive_strength > 0)
+               ad9389b_wr(sd, 0xa3, pdata->diff_clk_drive_strength);
+       else
+               ad9389b_wr(sd, 0xa3, 0x87);
+
+       ad9389b_wr(sd, 0x0a, 0x01);
+       ad9389b_wr(sd, 0xbb, 0xff);
+
+       /* Set number of attempts to read the EDID */
+       ad9389b_wr(sd, 0xc9, 0xf);
+       return true;
+}
+
+/* Enable interrupts */
+static void ad9389b_set_isr(struct v4l2_subdev *sd, bool enable)
+{
+       u8 irqs = MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT;
+       u8 irqs_rd;
+       int retries = 100;
+
+       /* The datasheet says that the EDID ready interrupt should be
+          disabled if there is no hotplug. */
+       if (!enable)
+               irqs = 0;
+       else if (ad9389b_have_hotplug(sd))
+               irqs |= MASK_AD9389B_EDID_RDY_INT;
+
+       /*
+        * This i2c write can fail (approx. 1 in 1000 writes). But it
+        * is essential that this register is correct, so retry it
+        * multiple times.
+        *
+        * Note that the i2c write does not report an error, but the readback
+        * clearly shows the wrong value.
+        */
+       do {
+               ad9389b_wr(sd, 0x94, irqs);
+               irqs_rd = ad9389b_rd(sd, 0x94);
+       } while (retries-- && irqs_rd != irqs);
+
+       if (irqs_rd != irqs)
+               v4l2_err(sd, "Could not set interrupts: hw failure?\n");
+}
+
+/* Interrupt handler */
+static int ad9389b_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+       u8 irq_status;
+
+       /* disable interrupts to prevent a race condition */
+       ad9389b_set_isr(sd, false);
+       irq_status = ad9389b_rd(sd, 0x96);
+       /* clear detected interrupts */
+       ad9389b_wr(sd, 0x96, irq_status);
+
+       if (irq_status & (MASK_AD9389B_HPD_INT | MASK_AD9389B_MSEN_INT))
+               ad9389b_check_monitor_present_status(sd);
+       if (irq_status & MASK_AD9389B_EDID_RDY_INT)
+               ad9389b_check_edid_status(sd);
+
+       /* enable interrupts */
+       ad9389b_set_isr(sd, true);
+       *handled = true;
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops ad9389b_core_ops = {
+       .log_status = ad9389b_log_status,
+       .g_chip_ident = ad9389b_g_chip_ident,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = ad9389b_g_register,
+       .s_register = ad9389b_s_register,
+#endif
+       .s_power = ad9389b_s_power,
+       .interrupt_service_routine = ad9389b_isr,
+};
+
+/* ------------------------------ PAD OPS ------------------------------ */
+
+static int ad9389b_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       if (edid->pad != 0)
+               return -EINVAL;
+       if (edid->blocks == 0 || edid->blocks > 256)
+               return -EINVAL;
+       if (!edid->edid)
+               return -EINVAL;
+       if (!state->edid.segments) {
+               v4l2_dbg(1, debug, sd, "EDID segment 0 not found\n");
+               return -ENODATA;
+       }
+       if (edid->start_block >= state->edid.segments * 2)
+               return -E2BIG;
+       if (edid->blocks + edid->start_block >= state->edid.segments * 2)
+               edid->blocks = state->edid.segments * 2 - edid->start_block;
+       memcpy(edid->edid, &state->edid.data[edid->start_block * 128],
+                               128 * edid->blocks);
+       return 0;
+}
+
+static const struct v4l2_subdev_pad_ops ad9389b_pad_ops = {
+       .get_edid = ad9389b_get_edid,
+};
+
+/* ------------------------------ VIDEO OPS ------------------------------ */
+
+/* Enable/disable ad9389b output */
+static int ad9389b_s_stream(struct v4l2_subdev *sd, int enable)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
+
+       ad9389b_wr_and_or(sd, 0xa1, ~0x3c, (enable ? 0 : 0x3c));
+       if (enable) {
+               ad9389b_check_monitor_present_status(sd);
+       } else {
+               ad9389b_s_power(sd, 0);
+               state->have_monitor = false;
+       }
+       return 0;
+}
+
+static const struct v4l2_dv_timings ad9389b_timings[] = {
+       V4L2_DV_BT_CEA_720X480P59_94,
+       V4L2_DV_BT_CEA_720X576P50,
+       V4L2_DV_BT_CEA_1280X720P24,
+       V4L2_DV_BT_CEA_1280X720P25,
+       V4L2_DV_BT_CEA_1280X720P30,
+       V4L2_DV_BT_CEA_1280X720P50,
+       V4L2_DV_BT_CEA_1280X720P60,
+       V4L2_DV_BT_CEA_1920X1080P24,
+       V4L2_DV_BT_CEA_1920X1080P25,
+       V4L2_DV_BT_CEA_1920X1080P30,
+       V4L2_DV_BT_CEA_1920X1080P50,
+       V4L2_DV_BT_CEA_1920X1080P60,
+
+       V4L2_DV_BT_DMT_640X350P85,
+       V4L2_DV_BT_DMT_640X400P85,
+       V4L2_DV_BT_DMT_720X400P85,
+       V4L2_DV_BT_DMT_640X480P60,
+       V4L2_DV_BT_DMT_640X480P72,
+       V4L2_DV_BT_DMT_640X480P75,
+       V4L2_DV_BT_DMT_640X480P85,
+       V4L2_DV_BT_DMT_800X600P56,
+       V4L2_DV_BT_DMT_800X600P60,
+       V4L2_DV_BT_DMT_800X600P72,
+       V4L2_DV_BT_DMT_800X600P75,
+       V4L2_DV_BT_DMT_800X600P85,
+       V4L2_DV_BT_DMT_848X480P60,
+       V4L2_DV_BT_DMT_1024X768P60,
+       V4L2_DV_BT_DMT_1024X768P70,
+       V4L2_DV_BT_DMT_1024X768P75,
+       V4L2_DV_BT_DMT_1024X768P85,
+       V4L2_DV_BT_DMT_1152X864P75,
+       V4L2_DV_BT_DMT_1280X768P60_RB,
+       V4L2_DV_BT_DMT_1280X768P60,
+       V4L2_DV_BT_DMT_1280X768P75,
+       V4L2_DV_BT_DMT_1280X768P85,
+       V4L2_DV_BT_DMT_1280X800P60_RB,
+       V4L2_DV_BT_DMT_1280X800P60,
+       V4L2_DV_BT_DMT_1280X800P75,
+       V4L2_DV_BT_DMT_1280X800P85,
+       V4L2_DV_BT_DMT_1280X960P60,
+       V4L2_DV_BT_DMT_1280X960P85,
+       V4L2_DV_BT_DMT_1280X1024P60,
+       V4L2_DV_BT_DMT_1280X1024P75,
+       V4L2_DV_BT_DMT_1280X1024P85,
+       V4L2_DV_BT_DMT_1360X768P60,
+       V4L2_DV_BT_DMT_1400X1050P60_RB,
+       V4L2_DV_BT_DMT_1400X1050P60,
+       V4L2_DV_BT_DMT_1400X1050P75,
+       V4L2_DV_BT_DMT_1400X1050P85,
+       V4L2_DV_BT_DMT_1440X900P60_RB,
+       V4L2_DV_BT_DMT_1440X900P60,
+       V4L2_DV_BT_DMT_1600X1200P60,
+       V4L2_DV_BT_DMT_1680X1050P60_RB,
+       V4L2_DV_BT_DMT_1680X1050P60,
+       V4L2_DV_BT_DMT_1792X1344P60,
+       V4L2_DV_BT_DMT_1856X1392P60,
+       V4L2_DV_BT_DMT_1920X1200P60_RB,
+       V4L2_DV_BT_DMT_1366X768P60,
+       V4L2_DV_BT_DMT_1920X1080P60,
+       {},
+};
+
+static int ad9389b_s_dv_timings(struct v4l2_subdev *sd,
+                               struct v4l2_dv_timings *timings)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       int i;
+
+       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+       /* quick sanity check */
+       if (timings->type != V4L2_DV_BT_656_1120)
+               return -EINVAL;
+
+       if (timings->bt.interlaced)
+               return -EINVAL;
+       if (timings->bt.pixelclock < 27000000 ||
+           timings->bt.pixelclock > 170000000)
+               return -EINVAL;
+
+       /* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
+          if the format is listed in ad9389b_timings[] */
+       for (i = 0; ad9389b_timings[i].bt.width; i++) {
+               if (v4l_match_dv_timings(timings, &ad9389b_timings[i], 0)) {
+                       *timings = ad9389b_timings[i];
+                       break;
+               }
+       }
+
+       timings->bt.flags &= ~V4L2_DV_FL_REDUCED_FPS;
+
+       /* save timings */
+       state->dv_timings = *timings;
+
+       /* update quantization range based on new dv_timings */
+       ad9389b_set_rgb_quantization_mode(sd, state->rgb_quantization_range_ctrl);
+
+       /* update PLL gear based on new dv_timings */
+       if (state->pdata.tmds_pll_gear == AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC)
+               ad9389b_set_manual_pll_gear(sd, (u32)timings->bt.pixelclock);
+
+       /* update AVI infoframe */
+       ad9389b_set_IT_content_AVI_InfoFrame(sd);
+
+       return 0;
+}
+
+static int ad9389b_g_dv_timings(struct v4l2_subdev *sd,
+                               struct v4l2_dv_timings *timings)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+       if (!timings)
+               return -EINVAL;
+
+       *timings = state->dv_timings;
+
+       return 0;
+}
+
+static int ad9389b_enum_dv_timings(struct v4l2_subdev *sd,
+                       struct v4l2_enum_dv_timings *timings)
+{
+       if (timings->index >= ARRAY_SIZE(ad9389b_timings))
+               return -EINVAL;
+
+       memset(timings->reserved, 0, sizeof(timings->reserved));
+       timings->timings = ad9389b_timings[timings->index];
+       return 0;
+}
+
+static int ad9389b_dv_timings_cap(struct v4l2_subdev *sd,
+                       struct v4l2_dv_timings_cap *cap)
+{
+       cap->type = V4L2_DV_BT_656_1120;
+       cap->bt.max_width = 1920;
+       cap->bt.max_height = 1200;
+       cap->bt.min_pixelclock = 27000000;
+       cap->bt.max_pixelclock = 170000000;
+       cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
+       cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
+               V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM;
+       return 0;
+}
+
+static const struct v4l2_subdev_video_ops ad9389b_video_ops = {
+       .s_stream = ad9389b_s_stream,
+       .s_dv_timings = ad9389b_s_dv_timings,
+       .g_dv_timings = ad9389b_g_dv_timings,
+       .enum_dv_timings = ad9389b_enum_dv_timings,
+       .dv_timings_cap = ad9389b_dv_timings_cap,
+};
+
+static int ad9389b_s_audio_stream(struct v4l2_subdev *sd, int enable)
+{
+       v4l2_dbg(1, debug, sd, "%s: %sable\n", __func__, (enable ? "en" : "dis"));
+
+       if (enable)
+               ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x80);
+       else
+               ad9389b_wr_and_or(sd, 0x45, 0x3f, 0x40);
+
+       return 0;
+}
+
+static int ad9389b_s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+       u32 N;
+
+       switch (freq) {
+       case 32000: N = 4096; break;
+       case 44100: N = 6272; break;
+       case 48000: N = 6144; break;
+       case 88200: N = 12544; break;
+       case 96000: N = 12288; break;
+       case 176400: N = 25088; break;
+       case 192000: N = 24576; break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Set N (used with CTS to regenerate the audio clock) */
+       ad9389b_wr(sd, 0x01, (N >> 16) & 0xf);
+       ad9389b_wr(sd, 0x02, (N >> 8) & 0xff);
+       ad9389b_wr(sd, 0x03, N & 0xff);
+
+       return 0;
+}
+
+static int ad9389b_s_i2s_clock_freq(struct v4l2_subdev *sd, u32 freq)
+{
+       u32 i2s_sf;
+
+       switch (freq) {
+       case 32000: i2s_sf = 0x30; break;
+       case 44100: i2s_sf = 0x00; break;
+       case 48000: i2s_sf = 0x20; break;
+       case 88200: i2s_sf = 0x80; break;
+       case 96000: i2s_sf = 0xa0; break;
+       case 176400: i2s_sf = 0xc0; break;
+       case 192000: i2s_sf = 0xe0; break;
+       default:
+               return -EINVAL;
+       }
+
+       /* Set sampling frequency for I2S audio to 48 kHz */
+       ad9389b_wr_and_or(sd, 0x15, 0xf, i2s_sf);
+
+       return 0;
+}
+
+static int ad9389b_s_routing(struct v4l2_subdev *sd, u32 input, u32 output, u32 config)
+{
+       /* TODO based on input/output/config */
+       /* TODO See datasheet "Programmers guide" p. 39-40 */
+
+       /* Only 2 channels in use for application */
+       ad9389b_wr_and_or(sd, 0x50, 0x1f, 0x20);
+       /* Speaker mapping */
+       ad9389b_wr(sd, 0x51, 0x00);
+
+       /* TODO Where should this be placed? */
+       /* 16 bit audio word length */
+       ad9389b_wr_and_or(sd, 0x14, 0xf0, 0x02);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_audio_ops ad9389b_audio_ops = {
+       .s_stream = ad9389b_s_audio_stream,
+       .s_clock_freq = ad9389b_s_clock_freq,
+       .s_i2s_clock_freq = ad9389b_s_i2s_clock_freq,
+       .s_routing = ad9389b_s_routing,
+};
+
+/* --------------------- SUBDEV OPS --------------------------------------- */
+
+static const struct v4l2_subdev_ops ad9389b_ops = {
+       .core  = &ad9389b_core_ops,
+       .video = &ad9389b_video_ops,
+       .audio = &ad9389b_audio_ops,
+       .pad = &ad9389b_pad_ops,
+};
+
+/* ----------------------------------------------------------------------- */
+static void ad9389b_dbg_dump_edid(int lvl, int debug, struct v4l2_subdev *sd,
+                                                       int segment, u8 *buf)
+{
+       int i, j;
+
+       if (debug < lvl)
+               return;
+
+       v4l2_dbg(lvl, debug, sd, "edid segment %d\n", segment);
+       for (i = 0; i < 256; i += 16) {
+               u8 b[128];
+               u8 *bp = b;
+
+               if (i == 128)
+                       v4l2_dbg(lvl, debug, sd, "\n");
+               for (j = i; j < i + 16; j++) {
+                       sprintf(bp, "0x%02x, ", buf[j]);
+                       bp += 6;
+               }
+               bp[0] = '\0';
+               v4l2_dbg(lvl, debug, sd, "%s\n", b);
+       }
+}
+
+static void ad9389b_edid_handler(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct ad9389b_state *state = container_of(dwork,
+                       struct ad9389b_state, edid_handler);
+       struct v4l2_subdev *sd = &state->sd;
+       struct ad9389b_edid_detect ed;
+
+       v4l2_dbg(1, debug, sd, "%s:\n", __func__);
+
+       if (ad9389b_check_edid_status(sd)) {
+               /* Return if we received the EDID. */
+               return;
+       }
+
+       if (ad9389b_have_hotplug(sd)) {
+               /* We must retry reading the EDID several times, it is possible
+                * that initially the EDID couldn't be read due to i2c errors
+                * (DVI connectors are particularly prone to this problem). */
+               if (state->edid.read_retries) {
+                       state->edid.read_retries--;
+                       /* EDID read failed, trigger a retry */
+                       ad9389b_wr(sd, 0xc9, 0xf);
+                       queue_delayed_work(state->work_queue,
+                                       &state->edid_handler, EDID_DELAY);
+                       return;
+               }
+       }
+
+       /* We failed to read the EDID, so send an event for this. */
+       ed.present = false;
+       ed.segment = ad9389b_rd(sd, 0xc4);
+       v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
+       v4l2_dbg(1, debug, sd, "%s: no edid found\n", __func__);
+}
+
+static void ad9389b_audio_setup(struct v4l2_subdev *sd)
+{
+       v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+       ad9389b_s_i2s_clock_freq(sd, 48000);
+       ad9389b_s_clock_freq(sd, 48000);
+       ad9389b_s_routing(sd, 0, 0, 0);
+}
+
+/* Initial setup of AD9389b */
+
+/* Configure hdmi transmitter. */
+static void ad9389b_setup(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+       /* Input format: RGB 4:4:4 */
+       ad9389b_wr_and_or(sd, 0x15, 0xf1, 0x0);
+       /* Output format: RGB 4:4:4 */
+       ad9389b_wr_and_or(sd, 0x16, 0x3f, 0x0);
+       /* CSC fixed point: +/-2, 1st order interpolation 4:2:2 -> 4:4:4 up
+          conversion, Aspect ratio: 16:9 */
+       ad9389b_wr_and_or(sd, 0x17, 0xe1, 0x0e);
+       /* Disable pixel repetition and CSC */
+       ad9389b_wr_and_or(sd, 0x3b, 0x9e, 0x0);
+       /* Output format: RGB 4:4:4, Active Format Information is valid. */
+       ad9389b_wr_and_or(sd, 0x45, 0xc7, 0x08);
+       /* Underscanned */
+       ad9389b_wr_and_or(sd, 0x46, 0x3f, 0x80);
+       /* Setup video format */
+       ad9389b_wr(sd, 0x3c, 0x0);
+       /* Active format aspect ratio: same as picure. */
+       ad9389b_wr(sd, 0x47, 0x80);
+       /* No encryption */
+       ad9389b_wr_and_or(sd, 0xaf, 0xef, 0x0);
+       /* Positive clk edge capture for input video clock */
+       ad9389b_wr_and_or(sd, 0xba, 0x1f, 0x60);
+
+       ad9389b_audio_setup(sd);
+
+       v4l2_ctrl_handler_setup(&state->hdl);
+
+       ad9389b_set_IT_content_AVI_InfoFrame(sd);
+}
+
+static void ad9389b_notify_monitor_detect(struct v4l2_subdev *sd)
+{
+       struct ad9389b_monitor_detect mdt;
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       mdt.present = state->have_monitor;
+       v4l2_subdev_notify(sd, AD9389B_MONITOR_DETECT, (void *)&mdt);
+}
+
+static void ad9389b_check_monitor_present_status(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       /* read hotplug and rx-sense state */
+       u8 status = ad9389b_rd(sd, 0x42);
+
+       v4l2_dbg(1, debug, sd, "%s: status: 0x%x%s%s\n",
+                        __func__,
+                        status,
+                        status & MASK_AD9389B_HPD_DETECT ? ", hotplug" : "",
+                        status & MASK_AD9389B_MSEN_DETECT ? ", rx-sense" : "");
+
+       if ((status & MASK_AD9389B_HPD_DETECT) &&
+           ((status & MASK_AD9389B_MSEN_DETECT) || state->edid.segments)) {
+               v4l2_dbg(1, debug, sd,
+                               "%s: hotplug and (rx-sense or edid)\n", __func__);
+               if (!state->have_monitor) {
+                       v4l2_dbg(1, debug, sd, "%s: monitor detected\n", __func__);
+                       state->have_monitor = true;
+                       ad9389b_set_isr(sd, true);
+                       if (!ad9389b_s_power(sd, true)) {
+                               v4l2_dbg(1, debug, sd,
+                                       "%s: monitor detected, powerup failed\n", __func__);
+                               return;
+                       }
+                       ad9389b_setup(sd);
+                       ad9389b_notify_monitor_detect(sd);
+                       state->edid.read_retries = EDID_MAX_RETRIES;
+                       queue_delayed_work(state->work_queue,
+                                       &state->edid_handler, EDID_DELAY);
+               }
+       } else if (status & MASK_AD9389B_HPD_DETECT) {
+               v4l2_dbg(1, debug, sd, "%s: hotplug detected\n", __func__);
+               state->edid.read_retries = EDID_MAX_RETRIES;
+               queue_delayed_work(state->work_queue,
+                               &state->edid_handler, EDID_DELAY);
+       } else if (!(status & MASK_AD9389B_HPD_DETECT)) {
+               v4l2_dbg(1, debug, sd, "%s: hotplug not detected\n", __func__);
+               if (state->have_monitor) {
+                       v4l2_dbg(1, debug, sd, "%s: monitor not detected\n", __func__);
+                       state->have_monitor = false;
+                       ad9389b_notify_monitor_detect(sd);
+               }
+               ad9389b_s_power(sd, false);
+               memset(&state->edid, 0, sizeof(struct ad9389b_state_edid));
+       }
+
+       /* update read only ctrls */
+       v4l2_ctrl_s_ctrl(state->hotplug_ctrl, ad9389b_have_hotplug(sd) ? 0x1 : 0x0);
+       v4l2_ctrl_s_ctrl(state->rx_sense_ctrl, ad9389b_have_rx_sense(sd) ? 0x1 : 0x0);
+       v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+}
+
+static bool edid_block_verify_crc(u8 *edid_block)
+{
+       int i;
+       u8 sum = 0;
+
+       for (i = 0; i < 127; i++)
+               sum += *(edid_block + i);
+       return ((255 - sum + 1) == edid_block[127]);
+}
+
+static bool edid_segment_verify_crc(struct v4l2_subdev *sd, u32 segment)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       u32 blocks = state->edid.blocks;
+       u8 *data = state->edid.data;
+
+       if (edid_block_verify_crc(&data[segment * 256])) {
+               if ((segment + 1) * 2 <= blocks)
+                       return edid_block_verify_crc(&data[segment * 256 + 128]);
+               return true;
+       }
+       return false;
+}
+
+static bool ad9389b_check_edid_status(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       struct ad9389b_edid_detect ed;
+       int segment;
+       u8 edidRdy = ad9389b_rd(sd, 0xc5);
+
+       v4l2_dbg(1, debug, sd, "%s: edid ready (retries: %d)\n",
+                        __func__, EDID_MAX_RETRIES - state->edid.read_retries);
+
+       if (!(edidRdy & MASK_AD9389B_EDID_RDY))
+               return false;
+
+       segment = ad9389b_rd(sd, 0xc4);
+       if (segment >= EDID_MAX_SEGM) {
+               v4l2_err(sd, "edid segment number too big\n");
+               return false;
+       }
+       v4l2_dbg(1, debug, sd, "%s: got segment %d\n", __func__, segment);
+       ad9389b_edid_rd(sd, 256, &state->edid.data[segment * 256]);
+       ad9389b_dbg_dump_edid(2, debug, sd, segment,
+                       &state->edid.data[segment * 256]);
+       if (segment == 0) {
+               state->edid.blocks = state->edid.data[0x7e] + 1;
+               v4l2_dbg(1, debug, sd, "%s: %d blocks in total\n",
+                               __func__, state->edid.blocks);
+       }
+       if (!edid_segment_verify_crc(sd, segment)) {
+               /* edid crc error, force reread of edid segment */
+               ad9389b_s_power(sd, false);
+               ad9389b_s_power(sd, true);
+               return false;
+       }
+       /* one more segment read ok */
+       state->edid.segments = segment + 1;
+       if (((state->edid.data[0x7e] >> 1) + 1) > state->edid.segments) {
+               /* Request next EDID segment */
+               v4l2_dbg(1, debug, sd, "%s: request segment %d\n",
+                               __func__, state->edid.segments);
+               ad9389b_wr(sd, 0xc9, 0xf);
+               ad9389b_wr(sd, 0xc4, state->edid.segments);
+               state->edid.read_retries = EDID_MAX_RETRIES;
+               queue_delayed_work(state->work_queue,
+                               &state->edid_handler, EDID_DELAY);
+               return false;
+       }
+
+       /* report when we have all segments but report only for segment 0 */
+       ed.present = true;
+       ed.segment = 0;
+       v4l2_subdev_notify(sd, AD9389B_EDID_DETECT, (void *)&ed);
+       state->edid_detect_counter++;
+       v4l2_ctrl_s_ctrl(state->have_edid0_ctrl, state->edid.segments ? 0x1 : 0x0);
+       return ed.present;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void ad9389b_init_setup(struct v4l2_subdev *sd)
+{
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+       struct ad9389b_state_edid *edid = &state->edid;
+
+       v4l2_dbg(1, debug, sd, "%s\n", __func__);
+
+       /* clear all interrupts */
+       ad9389b_wr(sd, 0x96, 0xff);
+
+       memset(edid, 0, sizeof(struct ad9389b_state_edid));
+       state->have_monitor = false;
+       ad9389b_set_isr(sd, false);
+}
+
+static int ad9389b_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       const struct v4l2_dv_timings dv1080p60 = V4L2_DV_BT_CEA_1920X1080P60;
+       struct ad9389b_state *state;
+       struct ad9389b_platform_data *pdata = client->dev.platform_data;
+       struct v4l2_ctrl_handler *hdl;
+       struct v4l2_subdev *sd;
+       int err = -EIO;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+
+       v4l_dbg(1, debug, client, "detecting ad9389b client on address 0x%x\n",
+                       client->addr << 1);
+
+       state = kzalloc(sizeof(struct ad9389b_state), GFP_KERNEL);
+       if (!state)
+               return -ENOMEM;
+
+       /* Platform data */
+       if (pdata == NULL) {
+               v4l_err(client, "No platform data!\n");
+               err = -ENODEV;
+               goto err_free;
+       }
+       memcpy(&state->pdata, pdata, sizeof(state->pdata));
+
+       sd = &state->sd;
+       v4l2_i2c_subdev_init(sd, client, &ad9389b_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       hdl = &state->hdl;
+       v4l2_ctrl_handler_init(hdl, 5);
+
+       /* private controls */
+
+       state->hdmi_mode_ctrl = v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
+                       V4L2_CID_DV_TX_MODE, V4L2_DV_TX_MODE_HDMI,
+                       0, V4L2_DV_TX_MODE_DVI_D);
+       state->hdmi_mode_ctrl->is_private = true;
+       state->hotplug_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_DV_TX_HOTPLUG, 0, 1, 0, 0);
+       state->hotplug_ctrl->is_private = true;
+       state->rx_sense_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_DV_TX_RXSENSE, 0, 1, 0, 0);
+       state->rx_sense_ctrl->is_private = true;
+       state->have_edid0_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_DV_TX_EDID_PRESENT, 0, 1, 0, 0);
+       state->have_edid0_ctrl->is_private = true;
+       state->rgb_quantization_range_ctrl =
+               v4l2_ctrl_new_std_menu(hdl, &ad9389b_ctrl_ops,
+                       V4L2_CID_DV_TX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
+                       0, V4L2_DV_RGB_RANGE_AUTO);
+       state->rgb_quantization_range_ctrl->is_private = true;
+       sd->ctrl_handler = hdl;
+       if (hdl->error) {
+               err = hdl->error;
+
+               goto err_hdl;
+       }
+
+       state->pad.flags = MEDIA_PAD_FL_SINK;
+       err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+       if (err)
+               goto err_hdl;
+
+       state->chip_revision = ad9389b_rd(sd, 0x0);
+       if (state->chip_revision != 2) {
+               v4l2_err(sd, "chip_revision %d != 2\n", state->chip_revision);
+               err = -EIO;
+               goto err_entity;
+       }
+       v4l2_dbg(1, debug, sd, "reg 0x41 0x%x, chip version (reg 0x00) 0x%x\n",
+                       ad9389b_rd(sd, 0x41), state->chip_revision);
+
+       state->edid_i2c_client = i2c_new_dummy(client->adapter, (0x7e>>1));
+       if (state->edid_i2c_client == NULL) {
+               v4l2_err(sd, "failed to register edid i2c client\n");
+               goto err_entity;
+       }
+
+       state->work_queue = create_singlethread_workqueue(sd->name);
+       if (state->work_queue == NULL) {
+               v4l2_err(sd, "could not create workqueue\n");
+               goto err_unreg;
+       }
+
+       INIT_DELAYED_WORK(&state->edid_handler, ad9389b_edid_handler);
+       state->dv_timings = dv1080p60;
+
+       ad9389b_init_setup(sd);
+       ad9389b_set_isr(sd, true);
+
+       v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+                         client->addr << 1, client->adapter->name);
+       return 0;
+
+err_unreg:
+       i2c_unregister_device(state->edid_i2c_client);
+err_entity:
+       media_entity_cleanup(&sd->entity);
+err_hdl:
+       v4l2_ctrl_handler_free(&state->hdl);
+err_free:
+       kfree(state);
+       return err;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int ad9389b_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct ad9389b_state *state = get_ad9389b_state(sd);
+
+       state->chip_revision = -1;
+
+       v4l2_dbg(1, debug, sd, "%s removed @ 0x%x (%s)\n", client->name,
+                client->addr << 1, client->adapter->name);
+
+       ad9389b_s_stream(sd, false);
+       ad9389b_s_audio_stream(sd, false);
+       ad9389b_init_setup(sd);
+       cancel_delayed_work(&state->edid_handler);
+       i2c_unregister_device(state->edid_i2c_client);
+       destroy_workqueue(state->work_queue);
+       v4l2_device_unregister_subdev(sd);
+       media_entity_cleanup(&sd->entity);
+       v4l2_ctrl_handler_free(sd->ctrl_handler);
+       kfree(get_ad9389b_state(sd));
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_device_id ad9389b_id[] = {
+       { "ad9389b", V4L2_IDENT_AD9389B },
+       { "ad9889b", V4L2_IDENT_AD9389B },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, ad9389b_id);
+
+static struct i2c_driver ad9389b_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "ad9389b",
+       },
+       .probe = ad9389b_probe,
+       .remove = ad9389b_remove,
+       .id_table = ad9389b_id,
+};
+
+module_i2c_driver(ad9389b_driver);
similarity index 99%
rename from drivers/media/video/adp1653.c
rename to drivers/media/i2c/adp1653.c
index 57e87090388d174089f68e920e72fe6752e2f884..18a38b38fcb8c9796b16549b2707c8551b6f86fa 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/adp1653.c
+ * drivers/media/i2c/adp1653.c
  *
  * Copyright (C) 2008--2011 Nokia Corporation
  *
diff --git a/drivers/media/i2c/adv7604.c b/drivers/media/i2c/adv7604.c
new file mode 100644 (file)
index 0000000..109bc9b
--- /dev/null
@@ -0,0 +1,1959 @@
+/*
+ * adv7604 - Analog Devices ADV7604 video decoder driver
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ */
+
+/*
+ * References (c = chapter, p = page):
+ * REF_01 - Analog devices, ADV7604, Register Settings Recommendations,
+ *             Revision 2.5, June 2010
+ * REF_02 - Analog devices, Register map documentation, Documentation of
+ *             the register maps, Software manual, Rev. F, June 2010
+ * REF_03 - Analog devices, ADV7604, Hardware Manual, Rev. F, August 2010
+ */
+
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/delay.h>
+#include <linux/videodev2.h>
+#include <linux/workqueue.h>
+#include <linux/v4l2-dv-timings.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/adv7604.h>
+
+static int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "debug level (0-2)");
+
+MODULE_DESCRIPTION("Analog Devices ADV7604 video decoder driver");
+MODULE_AUTHOR("Hans Verkuil <hans.verkuil@cisco.com>");
+MODULE_AUTHOR("Mats Randgaard <mats.randgaard@cisco.com>");
+MODULE_LICENSE("GPL");
+
+/* ADV7604 system clock frequency */
+#define ADV7604_fsc (28636360)
+
+#define DIGITAL_INPUT ((state->prim_mode == ADV7604_PRIM_MODE_HDMI_COMP) || \
+                       (state->prim_mode == ADV7604_PRIM_MODE_HDMI_GR))
+
+/*
+ **********************************************************************
+ *
+ *  Arrays with configuration parameters for the ADV7604
+ *
+ **********************************************************************
+ */
+struct adv7604_state {
+       struct adv7604_platform_data pdata;
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+       struct v4l2_ctrl_handler hdl;
+       enum adv7604_prim_mode prim_mode;
+       struct v4l2_dv_timings timings;
+       u8 edid[256];
+       unsigned edid_blocks;
+       struct v4l2_fract aspect_ratio;
+       u32 rgb_quantization_range;
+       struct workqueue_struct *work_queues;
+       struct delayed_work delayed_work_enable_hotplug;
+       bool connector_hdmi;
+
+       /* i2c clients */
+       struct i2c_client *i2c_avlink;
+       struct i2c_client *i2c_cec;
+       struct i2c_client *i2c_infoframe;
+       struct i2c_client *i2c_esdp;
+       struct i2c_client *i2c_dpp;
+       struct i2c_client *i2c_afe;
+       struct i2c_client *i2c_repeater;
+       struct i2c_client *i2c_edid;
+       struct i2c_client *i2c_hdmi;
+       struct i2c_client *i2c_test;
+       struct i2c_client *i2c_cp;
+       struct i2c_client *i2c_vdp;
+
+       /* controls */
+       struct v4l2_ctrl *detect_tx_5v_ctrl;
+       struct v4l2_ctrl *analog_sampling_phase_ctrl;
+       struct v4l2_ctrl *free_run_color_manual_ctrl;
+       struct v4l2_ctrl *free_run_color_ctrl;
+       struct v4l2_ctrl *rgb_quantization_range_ctrl;
+};
+
+/* Supported CEA and DMT timings */
+static const struct v4l2_dv_timings adv7604_timings[] = {
+       V4L2_DV_BT_CEA_720X480P59_94,
+       V4L2_DV_BT_CEA_720X576P50,
+       V4L2_DV_BT_CEA_1280X720P24,
+       V4L2_DV_BT_CEA_1280X720P25,
+       V4L2_DV_BT_CEA_1280X720P30,
+       V4L2_DV_BT_CEA_1280X720P50,
+       V4L2_DV_BT_CEA_1280X720P60,
+       V4L2_DV_BT_CEA_1920X1080P24,
+       V4L2_DV_BT_CEA_1920X1080P25,
+       V4L2_DV_BT_CEA_1920X1080P30,
+       V4L2_DV_BT_CEA_1920X1080P50,
+       V4L2_DV_BT_CEA_1920X1080P60,
+
+       V4L2_DV_BT_DMT_640X350P85,
+       V4L2_DV_BT_DMT_640X400P85,
+       V4L2_DV_BT_DMT_720X400P85,
+       V4L2_DV_BT_DMT_640X480P60,
+       V4L2_DV_BT_DMT_640X480P72,
+       V4L2_DV_BT_DMT_640X480P75,
+       V4L2_DV_BT_DMT_640X480P85,
+       V4L2_DV_BT_DMT_800X600P56,
+       V4L2_DV_BT_DMT_800X600P60,
+       V4L2_DV_BT_DMT_800X600P72,
+       V4L2_DV_BT_DMT_800X600P75,
+       V4L2_DV_BT_DMT_800X600P85,
+       V4L2_DV_BT_DMT_848X480P60,
+       V4L2_DV_BT_DMT_1024X768P60,
+       V4L2_DV_BT_DMT_1024X768P70,
+       V4L2_DV_BT_DMT_1024X768P75,
+       V4L2_DV_BT_DMT_1024X768P85,
+       V4L2_DV_BT_DMT_1152X864P75,
+       V4L2_DV_BT_DMT_1280X768P60_RB,
+       V4L2_DV_BT_DMT_1280X768P60,
+       V4L2_DV_BT_DMT_1280X768P75,
+       V4L2_DV_BT_DMT_1280X768P85,
+       V4L2_DV_BT_DMT_1280X800P60_RB,
+       V4L2_DV_BT_DMT_1280X800P60,
+       V4L2_DV_BT_DMT_1280X800P75,
+       V4L2_DV_BT_DMT_1280X800P85,
+       V4L2_DV_BT_DMT_1280X960P60,
+       V4L2_DV_BT_DMT_1280X960P85,
+       V4L2_DV_BT_DMT_1280X1024P60,
+       V4L2_DV_BT_DMT_1280X1024P75,
+       V4L2_DV_BT_DMT_1280X1024P85,
+       V4L2_DV_BT_DMT_1360X768P60,
+       V4L2_DV_BT_DMT_1400X1050P60_RB,
+       V4L2_DV_BT_DMT_1400X1050P60,
+       V4L2_DV_BT_DMT_1400X1050P75,
+       V4L2_DV_BT_DMT_1400X1050P85,
+       V4L2_DV_BT_DMT_1440X900P60_RB,
+       V4L2_DV_BT_DMT_1440X900P60,
+       V4L2_DV_BT_DMT_1600X1200P60,
+       V4L2_DV_BT_DMT_1680X1050P60_RB,
+       V4L2_DV_BT_DMT_1680X1050P60,
+       V4L2_DV_BT_DMT_1792X1344P60,
+       V4L2_DV_BT_DMT_1856X1392P60,
+       V4L2_DV_BT_DMT_1920X1200P60_RB,
+       V4L2_DV_BT_DMT_1366X768P60,
+       V4L2_DV_BT_DMT_1920X1080P60,
+       { },
+};
+
+/* ----------------------------------------------------------------------- */
+
+static inline struct adv7604_state *to_state(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct adv7604_state, sd);
+}
+
+static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
+{
+       return &container_of(ctrl->handler, struct adv7604_state, hdl)->sd;
+}
+
+static inline unsigned hblanking(const struct v4l2_bt_timings *t)
+{
+       return t->hfrontporch + t->hsync + t->hbackporch;
+}
+
+static inline unsigned htotal(const struct v4l2_bt_timings *t)
+{
+       return t->width + t->hfrontporch + t->hsync + t->hbackporch;
+}
+
+static inline unsigned vblanking(const struct v4l2_bt_timings *t)
+{
+       return t->vfrontporch + t->vsync + t->vbackporch;
+}
+
+static inline unsigned vtotal(const struct v4l2_bt_timings *t)
+{
+       return t->height + t->vfrontporch + t->vsync + t->vbackporch;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static s32 adv_smbus_read_byte_data_check(struct i2c_client *client,
+               u8 command, bool check)
+{
+       union i2c_smbus_data data;
+
+       if (!i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                       I2C_SMBUS_READ, command,
+                       I2C_SMBUS_BYTE_DATA, &data))
+               return data.byte;
+       if (check)
+               v4l_err(client, "error reading %02x, %02x\n",
+                               client->addr, command);
+       return -EIO;
+}
+
+static s32 adv_smbus_read_byte_data(struct i2c_client *client, u8 command)
+{
+       return adv_smbus_read_byte_data_check(client, command, true);
+}
+
+static s32 adv_smbus_write_byte_data(struct i2c_client *client,
+                                       u8 command, u8 value)
+{
+       union i2c_smbus_data data;
+       int err;
+       int i;
+
+       data.byte = value;
+       for (i = 0; i < 3; i++) {
+               err = i2c_smbus_xfer(client->adapter, client->addr,
+                               client->flags,
+                               I2C_SMBUS_WRITE, command,
+                               I2C_SMBUS_BYTE_DATA, &data);
+               if (!err)
+                       break;
+       }
+       if (err < 0)
+               v4l_err(client, "error writing %02x, %02x, %02x\n",
+                               client->addr, command, value);
+       return err;
+}
+
+static s32 adv_smbus_write_i2c_block_data(struct i2c_client *client,
+              u8 command, unsigned length, const u8 *values)
+{
+       union i2c_smbus_data data;
+
+       if (length > I2C_SMBUS_BLOCK_MAX)
+               length = I2C_SMBUS_BLOCK_MAX;
+       data.block[0] = length;
+       memcpy(data.block + 1, values, length);
+       return i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                             I2C_SMBUS_WRITE, command,
+                             I2C_SMBUS_I2C_BLOCK_DATA, &data);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline int io_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return adv_smbus_read_byte_data(client, reg);
+}
+
+static inline int io_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return adv_smbus_write_byte_data(client, reg, val);
+}
+
+static inline int io_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+       return io_write(sd, reg, (io_read(sd, reg) & mask) | val);
+}
+
+static inline int avlink_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_avlink, reg);
+}
+
+static inline int avlink_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_avlink, reg, val);
+}
+
+static inline int cec_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_cec, reg);
+}
+
+static inline int cec_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_cec, reg, val);
+}
+
+static inline int cec_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+       return cec_write(sd, reg, (cec_read(sd, reg) & mask) | val);
+}
+
+static inline int infoframe_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_infoframe, reg);
+}
+
+static inline int infoframe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_infoframe, reg, val);
+}
+
+static inline int esdp_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_esdp, reg);
+}
+
+static inline int esdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_esdp, reg, val);
+}
+
+static inline int dpp_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_dpp, reg);
+}
+
+static inline int dpp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_dpp, reg, val);
+}
+
+static inline int afe_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_afe, reg);
+}
+
+static inline int afe_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_afe, reg, val);
+}
+
+static inline int rep_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_repeater, reg);
+}
+
+static inline int rep_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_repeater, reg, val);
+}
+
+static inline int rep_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+       return rep_write(sd, reg, (rep_read(sd, reg) & mask) | val);
+}
+
+static inline int edid_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_edid, reg);
+}
+
+static inline int edid_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_edid, reg, val);
+}
+
+static inline int edid_read_block(struct v4l2_subdev *sd, unsigned len, u8 *val)
+{
+       struct adv7604_state *state = to_state(sd);
+       struct i2c_client *client = state->i2c_edid;
+       u8 msgbuf0[1] = { 0 };
+       u8 msgbuf1[256];
+       struct i2c_msg msg[2] = { { client->addr, 0, 1, msgbuf0 },
+                                 { client->addr, 0 | I2C_M_RD, len, msgbuf1 }
+                               };
+
+       if (i2c_transfer(client->adapter, msg, 2) < 0)
+               return -EIO;
+       memcpy(val, msgbuf1, len);
+       return 0;
+}
+
+static void adv7604_delayed_work_enable_hotplug(struct work_struct *work)
+{
+       struct delayed_work *dwork = to_delayed_work(work);
+       struct adv7604_state *state = container_of(dwork, struct adv7604_state,
+                                               delayed_work_enable_hotplug);
+       struct v4l2_subdev *sd = &state->sd;
+
+       v4l2_dbg(2, debug, sd, "%s: enable hotplug\n", __func__);
+
+       v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)1);
+}
+
+static inline int edid_write_block(struct v4l2_subdev *sd,
+                                       unsigned len, const u8 *val)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct adv7604_state *state = to_state(sd);
+       int err = 0;
+       int i;
+
+       v4l2_dbg(2, debug, sd, "%s: write EDID block (%d byte)\n", __func__, len);
+
+       v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
+
+       /* Disables I2C access to internal EDID ram from DDC port */
+       rep_write_and_or(sd, 0x77, 0xf0, 0x0);
+
+       for (i = 0; !err && i < len; i += I2C_SMBUS_BLOCK_MAX)
+               err = adv_smbus_write_i2c_block_data(state->i2c_edid, i,
+                               I2C_SMBUS_BLOCK_MAX, val + i);
+       if (err)
+               return err;
+
+       /* adv7604 calculates the checksums and enables I2C access to internal
+          EDID ram from DDC port. */
+       rep_write_and_or(sd, 0x77, 0xf0, 0x1);
+
+       for (i = 0; i < 1000; i++) {
+               if (rep_read(sd, 0x7d) & 1)
+                       break;
+               mdelay(1);
+       }
+       if (i == 1000) {
+               v4l_err(client, "error enabling edid\n");
+               return -EIO;
+       }
+
+       /* enable hotplug after 100 ms */
+       queue_delayed_work(state->work_queues,
+                       &state->delayed_work_enable_hotplug, HZ / 10);
+       return 0;
+}
+
+static inline int hdmi_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_hdmi, reg);
+}
+
+static inline int hdmi_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_hdmi, reg, val);
+}
+
+static inline int test_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_test, reg);
+}
+
+static inline int test_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_test, reg, val);
+}
+
+static inline int cp_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_cp, reg);
+}
+
+static inline int cp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_cp, reg, val);
+}
+
+static inline int cp_write_and_or(struct v4l2_subdev *sd, u8 reg, u8 mask, u8 val)
+{
+       return cp_write(sd, reg, (cp_read(sd, reg) & mask) | val);
+}
+
+static inline int vdp_read(struct v4l2_subdev *sd, u8 reg)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_read_byte_data(state->i2c_vdp, reg);
+}
+
+static inline int vdp_write(struct v4l2_subdev *sd, u8 reg, u8 val)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       return adv_smbus_write_byte_data(state->i2c_vdp, reg, val);
+}
+
+/* ----------------------------------------------------------------------- */
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static void adv7604_inv_register(struct v4l2_subdev *sd)
+{
+       v4l2_info(sd, "0x000-0x0ff: IO Map\n");
+       v4l2_info(sd, "0x100-0x1ff: AVLink Map\n");
+       v4l2_info(sd, "0x200-0x2ff: CEC Map\n");
+       v4l2_info(sd, "0x300-0x3ff: InfoFrame Map\n");
+       v4l2_info(sd, "0x400-0x4ff: ESDP Map\n");
+       v4l2_info(sd, "0x500-0x5ff: DPP Map\n");
+       v4l2_info(sd, "0x600-0x6ff: AFE Map\n");
+       v4l2_info(sd, "0x700-0x7ff: Repeater Map\n");
+       v4l2_info(sd, "0x800-0x8ff: EDID Map\n");
+       v4l2_info(sd, "0x900-0x9ff: HDMI Map\n");
+       v4l2_info(sd, "0xa00-0xaff: Test Map\n");
+       v4l2_info(sd, "0xb00-0xbff: CP Map\n");
+       v4l2_info(sd, "0xc00-0xcff: VDP Map\n");
+}
+
+static int adv7604_g_register(struct v4l2_subdev *sd,
+                                       struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       reg->size = 1;
+       switch (reg->reg >> 8) {
+       case 0:
+               reg->val = io_read(sd, reg->reg & 0xff);
+               break;
+       case 1:
+               reg->val = avlink_read(sd, reg->reg & 0xff);
+               break;
+       case 2:
+               reg->val = cec_read(sd, reg->reg & 0xff);
+               break;
+       case 3:
+               reg->val = infoframe_read(sd, reg->reg & 0xff);
+               break;
+       case 4:
+               reg->val = esdp_read(sd, reg->reg & 0xff);
+               break;
+       case 5:
+               reg->val = dpp_read(sd, reg->reg & 0xff);
+               break;
+       case 6:
+               reg->val = afe_read(sd, reg->reg & 0xff);
+               break;
+       case 7:
+               reg->val = rep_read(sd, reg->reg & 0xff);
+               break;
+       case 8:
+               reg->val = edid_read(sd, reg->reg & 0xff);
+               break;
+       case 9:
+               reg->val = hdmi_read(sd, reg->reg & 0xff);
+               break;
+       case 0xa:
+               reg->val = test_read(sd, reg->reg & 0xff);
+               break;
+       case 0xb:
+               reg->val = cp_read(sd, reg->reg & 0xff);
+               break;
+       case 0xc:
+               reg->val = vdp_read(sd, reg->reg & 0xff);
+               break;
+       default:
+               v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
+               adv7604_inv_register(sd);
+               break;
+       }
+       return 0;
+}
+
+static int adv7604_s_register(struct v4l2_subdev *sd,
+                                       struct v4l2_dbg_register *reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (!v4l2_chip_match_i2c_client(client, &reg->match))
+               return -EINVAL;
+       if (!capable(CAP_SYS_ADMIN))
+               return -EPERM;
+       switch (reg->reg >> 8) {
+       case 0:
+               io_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 1:
+               avlink_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 2:
+               cec_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 3:
+               infoframe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 4:
+               esdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 5:
+               dpp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 6:
+               afe_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 7:
+               rep_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 8:
+               edid_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 9:
+               hdmi_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 0xa:
+               test_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 0xb:
+               cp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       case 0xc:
+               vdp_write(sd, reg->reg & 0xff, reg->val & 0xff);
+               break;
+       default:
+               v4l2_info(sd, "Register %03llx not supported\n", reg->reg);
+               adv7604_inv_register(sd);
+               break;
+       }
+       return 0;
+}
+#endif
+
+static int adv7604_s_detect_tx_5v_ctrl(struct v4l2_subdev *sd)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       /* port A only */
+       return v4l2_ctrl_s_ctrl(state->detect_tx_5v_ctrl,
+                               ((io_read(sd, 0x6f) & 0x10) >> 4));
+}
+
+static void configure_free_run(struct v4l2_subdev *sd, const struct v4l2_bt_timings *timings)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u32 width = htotal(timings);
+       u32 height = vtotal(timings);
+       u16 ch1_fr_ll = (((u32)timings->pixelclock / 100) > 0) ?
+               ((width * (ADV7604_fsc / 100)) / ((u32)timings->pixelclock / 100)) : 0;
+
+       v4l2_dbg(2, debug, sd, "%s\n", __func__);
+
+       cp_write(sd, 0x8f, (ch1_fr_ll >> 8) & 0x7);     /* CH1_FR_LL */
+       cp_write(sd, 0x90, ch1_fr_ll & 0xff);           /* CH1_FR_LL */
+       cp_write(sd, 0xab, (height >> 4) & 0xff); /* CP_LCOUNT_MAX */
+       cp_write(sd, 0xac, (height & 0x0f) << 4); /* CP_LCOUNT_MAX */
+       /* TODO support interlaced */
+       cp_write(sd, 0x91, 0x10);       /* INTERLACED */
+
+       /* Should only be set in auto-graphics mode [REF_02 p. 91-92] */
+       if ((io_read(sd, 0x00) == 0x07) && (io_read(sd, 0x01) == 0x02)) {
+               u16 cp_start_sav, cp_start_eav, cp_start_vbi, cp_end_vbi;
+               const u8 pll[2] = {
+                       (0xc0 | ((width >> 8) & 0x1f)),
+                       (width & 0xff)
+               };
+
+               /* setup PLL_DIV_MAN_EN and PLL_DIV_RATIO */
+               /* IO-map reg. 0x16 and 0x17 should be written in sequence */
+               if (adv_smbus_write_i2c_block_data(client, 0x16, 2, pll)) {
+                       v4l2_err(sd, "writing to reg 0x16 and 0x17 failed\n");
+                       return;
+               }
+
+               /* active video - horizontal timing */
+               cp_start_sav = timings->hsync + timings->hbackporch - 4;
+               cp_start_eav = width - timings->hfrontporch;
+               cp_write(sd, 0xa2, (cp_start_sav >> 4) & 0xff);
+               cp_write(sd, 0xa3, ((cp_start_sav & 0x0f) << 4) | ((cp_start_eav >> 8) & 0x0f));
+               cp_write(sd, 0xa4, cp_start_eav & 0xff);
+
+               /* active video - vertical timing */
+               cp_start_vbi = height - timings->vfrontporch;
+               cp_end_vbi = timings->vsync + timings->vbackporch;
+               cp_write(sd, 0xa5, (cp_start_vbi >> 4) & 0xff);
+               cp_write(sd, 0xa6, ((cp_start_vbi & 0xf) << 4) | ((cp_end_vbi >> 8) & 0xf));
+               cp_write(sd, 0xa7, cp_end_vbi & 0xff);
+       } else {
+               /* reset to default values */
+               io_write(sd, 0x16, 0x43);
+               io_write(sd, 0x17, 0x5a);
+               cp_write(sd, 0xa2, 0x00);
+               cp_write(sd, 0xa3, 0x00);
+               cp_write(sd, 0xa4, 0x00);
+               cp_write(sd, 0xa5, 0x00);
+               cp_write(sd, 0xa6, 0x00);
+               cp_write(sd, 0xa7, 0x00);
+       }
+}
+
+
+static void set_rgb_quantization_range(struct v4l2_subdev *sd)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       switch (state->rgb_quantization_range) {
+       case V4L2_DV_RGB_RANGE_AUTO:
+               /* automatic */
+               if ((hdmi_read(sd, 0x05) & 0x80) ||
+                               (state->prim_mode == ADV7604_PRIM_MODE_COMP) ||
+                               (state->prim_mode == ADV7604_PRIM_MODE_RGB)) {
+                       /* receiving HDMI or analog signal */
+                       io_write_and_or(sd, 0x02, 0x0f, 0xf0);
+               } else {
+                       /* receiving DVI-D signal */
+
+                       /* ADV7604 selects RGB limited range regardless of
+                          input format (CE/IT) in automatic mode */
+                       if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+                               /* RGB limited range (16-235) */
+                               io_write_and_or(sd, 0x02, 0x0f, 0x00);
+
+                       } else {
+                               /* RGB full range (0-255) */
+                               io_write_and_or(sd, 0x02, 0x0f, 0x10);
+                       }
+               }
+               break;
+       case V4L2_DV_RGB_RANGE_LIMITED:
+               /* RGB limited range (16-235) */
+               io_write_and_or(sd, 0x02, 0x0f, 0x00);
+               break;
+       case V4L2_DV_RGB_RANGE_FULL:
+               /* RGB full range (0-255) */
+               io_write_and_or(sd, 0x02, 0x0f, 0x10);
+               break;
+       }
+}
+
+
+static int adv7604_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = to_sd(ctrl);
+       struct adv7604_state *state = to_state(sd);
+
+       switch (ctrl->id) {
+       case V4L2_CID_BRIGHTNESS:
+               cp_write(sd, 0x3c, ctrl->val);
+               return 0;
+       case V4L2_CID_CONTRAST:
+               cp_write(sd, 0x3a, ctrl->val);
+               return 0;
+       case V4L2_CID_SATURATION:
+               cp_write(sd, 0x3b, ctrl->val);
+               return 0;
+       case V4L2_CID_HUE:
+               cp_write(sd, 0x3d, ctrl->val);
+               return 0;
+       case  V4L2_CID_DV_RX_RGB_RANGE:
+               state->rgb_quantization_range = ctrl->val;
+               set_rgb_quantization_range(sd);
+               return 0;
+       case V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE:
+               /* Set the analog sampling phase. This is needed to find the
+                  best sampling phase for analog video: an application or
+                  driver has to try a number of phases and analyze the picture
+                  quality before settling on the best performing phase. */
+               afe_write(sd, 0xc8, ctrl->val);
+               return 0;
+       case V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL:
+               /* Use the default blue color for free running mode,
+                  or supply your own. */
+               cp_write_and_or(sd, 0xbf, ~0x04, (ctrl->val << 2));
+               return 0;
+       case V4L2_CID_ADV_RX_FREE_RUN_COLOR:
+               cp_write(sd, 0xc0, (ctrl->val & 0xff0000) >> 16);
+               cp_write(sd, 0xc1, (ctrl->val & 0x00ff00) >> 8);
+               cp_write(sd, 0xc2, (u8)(ctrl->val & 0x0000ff));
+               return 0;
+       }
+       return -EINVAL;
+}
+
+static int adv7604_g_chip_ident(struct v4l2_subdev *sd,
+                                       struct v4l2_dbg_chip_ident *chip)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       return v4l2_chip_ident_i2c_client(client, chip, V4L2_IDENT_ADV7604, 0);
+}
+
+/* ----------------------------------------------------------------------- */
+
+static inline bool no_power(struct v4l2_subdev *sd)
+{
+       /* Entire chip or CP powered off */
+       return io_read(sd, 0x0c) & 0x24;
+}
+
+static inline bool no_signal_tmds(struct v4l2_subdev *sd)
+{
+       /* TODO port B, C and D */
+       return !(io_read(sd, 0x6a) & 0x10);
+}
+
+static inline bool no_lock_tmds(struct v4l2_subdev *sd)
+{
+       return (io_read(sd, 0x6a) & 0xe0) != 0xe0;
+}
+
+static inline bool no_lock_sspd(struct v4l2_subdev *sd)
+{
+       /* TODO channel 2 */
+       return ((cp_read(sd, 0xb5) & 0xd0) != 0xd0);
+}
+
+static inline bool no_lock_stdi(struct v4l2_subdev *sd)
+{
+       /* TODO channel 2 */
+       return !(cp_read(sd, 0xb1) & 0x80);
+}
+
+static inline bool no_signal(struct v4l2_subdev *sd)
+{
+       struct adv7604_state *state = to_state(sd);
+       bool ret;
+
+       ret = no_power(sd);
+
+       ret |= no_lock_stdi(sd);
+       ret |= no_lock_sspd(sd);
+
+       if (DIGITAL_INPUT) {
+               ret |= no_lock_tmds(sd);
+               ret |= no_signal_tmds(sd);
+       }
+
+       return ret;
+}
+
+static inline bool no_lock_cp(struct v4l2_subdev *sd)
+{
+       /* CP has detected a non standard number of lines on the incoming
+          video compared to what it is configured to receive by s_dv_timings */
+       return io_read(sd, 0x12) & 0x01;
+}
+
+static int adv7604_g_input_status(struct v4l2_subdev *sd, u32 *status)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       *status = 0;
+       *status |= no_power(sd) ? V4L2_IN_ST_NO_POWER : 0;
+       *status |= no_signal(sd) ? V4L2_IN_ST_NO_SIGNAL : 0;
+       if (no_lock_cp(sd))
+               *status |= DIGITAL_INPUT ? V4L2_IN_ST_NO_SYNC : V4L2_IN_ST_NO_H_LOCK;
+
+       v4l2_dbg(1, debug, sd, "%s: status = 0x%x\n", __func__, *status);
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static void adv7604_print_timings(struct v4l2_subdev *sd,
+       struct v4l2_dv_timings *timings, const char *txt, bool detailed)
+{
+       struct v4l2_bt_timings *bt = &timings->bt;
+       u32 htot, vtot;
+
+       if (timings->type != V4L2_DV_BT_656_1120)
+               return;
+
+       htot = htotal(bt);
+       vtot = vtotal(bt);
+
+       v4l2_info(sd, "%s %dx%d%s%d (%dx%d)",
+                       txt, bt->width, bt->height, bt->interlaced ? "i" : "p",
+                       (htot * vtot) > 0 ? ((u32)bt->pixelclock /
+                               (htot * vtot)) : 0,
+                       htot, vtot);
+
+       if (detailed) {
+               v4l2_info(sd, "    horizontal: fp = %d, %ssync = %d, bp = %d\n",
+                               bt->hfrontporch,
+                               (bt->polarities & V4L2_DV_HSYNC_POS_POL) ? "+" : "-",
+                               bt->hsync, bt->hbackporch);
+               v4l2_info(sd, "    vertical: fp = %d, %ssync = %d, bp = %d\n",
+                               bt->vfrontporch,
+                               (bt->polarities & V4L2_DV_VSYNC_POS_POL) ? "+" : "-",
+                               bt->vsync, bt->vbackporch);
+               v4l2_info(sd, "    pixelclock: %lld, flags: 0x%x, standards: 0x%x\n",
+                               bt->pixelclock, bt->flags, bt->standards);
+       }
+}
+
+struct stdi_readback {
+       u16 bl, lcf, lcvs;
+       u8 hs_pol, vs_pol;
+       bool interlaced;
+};
+
+static int stdi2dv_timings(struct v4l2_subdev *sd,
+               struct stdi_readback *stdi,
+               struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       u32 hfreq = (ADV7604_fsc * 8) / stdi->bl;
+       u32 pix_clk;
+       int i;
+
+       for (i = 0; adv7604_timings[i].bt.height; i++) {
+               if (vtotal(&adv7604_timings[i].bt) != stdi->lcf + 1)
+                       continue;
+               if (adv7604_timings[i].bt.vsync != stdi->lcvs)
+                       continue;
+
+               pix_clk = hfreq * htotal(&adv7604_timings[i].bt);
+
+               if ((pix_clk < adv7604_timings[i].bt.pixelclock + 1000000) &&
+                   (pix_clk > adv7604_timings[i].bt.pixelclock - 1000000)) {
+                       *timings = adv7604_timings[i];
+                       return 0;
+               }
+       }
+
+       if (v4l2_detect_cvt(stdi->lcf + 1, hfreq, stdi->lcvs,
+                       (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+                       (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+                       timings))
+               return 0;
+       if (v4l2_detect_gtf(stdi->lcf + 1, hfreq, stdi->lcvs,
+                       (stdi->hs_pol == '+' ? V4L2_DV_HSYNC_POS_POL : 0) |
+                       (stdi->vs_pol == '+' ? V4L2_DV_VSYNC_POS_POL : 0),
+                       state->aspect_ratio, timings))
+               return 0;
+
+       v4l2_dbg(2, debug, sd, "%s: No format candidate found for lcf=%d, bl = %d\n",
+                       __func__, stdi->lcf, stdi->bl);
+       return -1;
+}
+
+static int read_stdi(struct v4l2_subdev *sd, struct stdi_readback *stdi)
+{
+       if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
+               v4l2_dbg(2, debug, sd, "%s: STDI and/or SSPD not locked\n", __func__);
+               return -1;
+       }
+
+       /* read STDI */
+       stdi->bl = ((cp_read(sd, 0xb1) & 0x3f) << 8) | cp_read(sd, 0xb2);
+       stdi->lcf = ((cp_read(sd, 0xb3) & 0x7) << 8) | cp_read(sd, 0xb4);
+       stdi->lcvs = cp_read(sd, 0xb3) >> 3;
+       stdi->interlaced = io_read(sd, 0x12) & 0x10;
+
+       /* read SSPD */
+       if ((cp_read(sd, 0xb5) & 0x03) == 0x01) {
+               stdi->hs_pol = ((cp_read(sd, 0xb5) & 0x10) ?
+                               ((cp_read(sd, 0xb5) & 0x08) ? '+' : '-') : 'x');
+               stdi->vs_pol = ((cp_read(sd, 0xb5) & 0x40) ?
+                               ((cp_read(sd, 0xb5) & 0x20) ? '+' : '-') : 'x');
+       } else {
+               stdi->hs_pol = 'x';
+               stdi->vs_pol = 'x';
+       }
+
+       if (no_lock_stdi(sd) || no_lock_sspd(sd)) {
+               v4l2_dbg(2, debug, sd,
+                       "%s: signal lost during readout of STDI/SSPD\n", __func__);
+               return -1;
+       }
+
+       if (stdi->lcf < 239 || stdi->bl < 8 || stdi->bl == 0x3fff) {
+               v4l2_dbg(2, debug, sd, "%s: invalid signal\n", __func__);
+               memset(stdi, 0, sizeof(struct stdi_readback));
+               return -1;
+       }
+
+       v4l2_dbg(2, debug, sd,
+               "%s: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %chsync, %cvsync, %s\n",
+               __func__, stdi->lcf, stdi->bl, stdi->lcvs,
+               stdi->hs_pol, stdi->vs_pol,
+               stdi->interlaced ? "interlaced" : "progressive");
+
+       return 0;
+}
+
+static int adv7604_enum_dv_timings(struct v4l2_subdev *sd,
+                       struct v4l2_enum_dv_timings *timings)
+{
+       if (timings->index >= ARRAY_SIZE(adv7604_timings) - 1)
+               return -EINVAL;
+       memset(timings->reserved, 0, sizeof(timings->reserved));
+       timings->timings = adv7604_timings[timings->index];
+       return 0;
+}
+
+static int adv7604_dv_timings_cap(struct v4l2_subdev *sd,
+                       struct v4l2_dv_timings_cap *cap)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       cap->type = V4L2_DV_BT_656_1120;
+       cap->bt.max_width = 1920;
+       cap->bt.max_height = 1200;
+       cap->bt.min_pixelclock = 27000000;
+       if (DIGITAL_INPUT)
+               cap->bt.max_pixelclock = 225000000;
+       else
+               cap->bt.max_pixelclock = 170000000;
+       cap->bt.standards = V4L2_DV_BT_STD_CEA861 | V4L2_DV_BT_STD_DMT |
+                        V4L2_DV_BT_STD_GTF | V4L2_DV_BT_STD_CVT;
+       cap->bt.capabilities = V4L2_DV_BT_CAP_PROGRESSIVE |
+               V4L2_DV_BT_CAP_REDUCED_BLANKING | V4L2_DV_BT_CAP_CUSTOM;
+       return 0;
+}
+
+/* Fill the optional fields .standards and .flags in struct v4l2_dv_timings
+   if the format is listed in adv7604_timings[] */
+static void adv7604_fill_optional_dv_timings_fields(struct v4l2_subdev *sd,
+               struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       int i;
+
+       for (i = 0; adv7604_timings[i].bt.width; i++) {
+               if (v4l_match_dv_timings(timings, &adv7604_timings[i],
+                                       DIGITAL_INPUT ? 250000 : 1000000)) {
+                       *timings = adv7604_timings[i];
+                       break;
+               }
+       }
+}
+
+static int adv7604_query_dv_timings(struct v4l2_subdev *sd,
+                       struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       struct v4l2_bt_timings *bt = &timings->bt;
+       struct stdi_readback stdi;
+
+       if (!timings)
+               return -EINVAL;
+
+       memset(timings, 0, sizeof(struct v4l2_dv_timings));
+
+       if (no_signal(sd)) {
+               v4l2_dbg(1, debug, sd, "%s: no valid signal\n", __func__);
+               return -ENOLINK;
+       }
+
+       /* read STDI */
+       if (read_stdi(sd, &stdi)) {
+               v4l2_dbg(1, debug, sd, "%s: STDI/SSPD not locked\n", __func__);
+               return -ENOLINK;
+       }
+       bt->interlaced = stdi.interlaced ?
+               V4L2_DV_INTERLACED : V4L2_DV_PROGRESSIVE;
+
+       if (DIGITAL_INPUT) {
+               timings->type = V4L2_DV_BT_656_1120;
+
+               bt->width = (hdmi_read(sd, 0x07) & 0x0f) * 256 + hdmi_read(sd, 0x08);
+               bt->height = (hdmi_read(sd, 0x09) & 0x0f) * 256 + hdmi_read(sd, 0x0a);
+               bt->pixelclock = (hdmi_read(sd, 0x06) * 1000000) +
+                       ((hdmi_read(sd, 0x3b) & 0x30) >> 4) * 250000;
+               bt->hfrontporch = (hdmi_read(sd, 0x20) & 0x03) * 256 +
+                       hdmi_read(sd, 0x21);
+               bt->hsync = (hdmi_read(sd, 0x22) & 0x03) * 256 +
+                       hdmi_read(sd, 0x23);
+               bt->hbackporch = (hdmi_read(sd, 0x24) & 0x03) * 256 +
+                       hdmi_read(sd, 0x25);
+               bt->vfrontporch = ((hdmi_read(sd, 0x2a) & 0x1f) * 256 +
+                       hdmi_read(sd, 0x2b)) / 2;
+               bt->vsync = ((hdmi_read(sd, 0x2e) & 0x1f) * 256 +
+                       hdmi_read(sd, 0x2f)) / 2;
+               bt->vbackporch = ((hdmi_read(sd, 0x32) & 0x1f) * 256 +
+                       hdmi_read(sd, 0x33)) / 2;
+               bt->polarities = ((hdmi_read(sd, 0x05) & 0x10) ? V4L2_DV_VSYNC_POS_POL : 0) |
+                       ((hdmi_read(sd, 0x05) & 0x20) ? V4L2_DV_HSYNC_POS_POL : 0);
+               if (bt->interlaced == V4L2_DV_INTERLACED) {
+                       bt->height += (hdmi_read(sd, 0x0b) & 0x0f) * 256 +
+                                       hdmi_read(sd, 0x0c);
+                       bt->il_vfrontporch = ((hdmi_read(sd, 0x2c) & 0x1f) * 256 +
+                                       hdmi_read(sd, 0x2d)) / 2;
+                       bt->il_vsync = ((hdmi_read(sd, 0x30) & 0x1f) * 256 +
+                                       hdmi_read(sd, 0x31)) / 2;
+                       bt->vbackporch = ((hdmi_read(sd, 0x34) & 0x1f) * 256 +
+                                       hdmi_read(sd, 0x35)) / 2;
+               }
+               adv7604_fill_optional_dv_timings_fields(sd, timings);
+       } else {
+               /* find format
+                * Since LCVS values are inaccurate (REF_03, page 275-276),
+                * stdi2dv_timings() is called with lcvs +-1 if the first attempt fails.
+                */
+               if (!stdi2dv_timings(sd, &stdi, timings))
+                       goto found;
+               stdi.lcvs += 1;
+               v4l2_dbg(1, debug, sd, "%s: lcvs + 1 = %d\n", __func__, stdi.lcvs);
+               if (!stdi2dv_timings(sd, &stdi, timings))
+                       goto found;
+               stdi.lcvs -= 2;
+               v4l2_dbg(1, debug, sd, "%s: lcvs - 1 = %d\n", __func__, stdi.lcvs);
+               if (stdi2dv_timings(sd, &stdi, timings)) {
+                       v4l2_dbg(1, debug, sd, "%s: format not supported\n", __func__);
+                       return -ERANGE;
+               }
+       }
+found:
+
+       if (no_signal(sd)) {
+               v4l2_dbg(1, debug, sd, "%s: signal lost during readout\n", __func__);
+               memset(timings, 0, sizeof(struct v4l2_dv_timings));
+               return -ENOLINK;
+       }
+
+       if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
+                       (DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+               v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
+                               __func__, (u32)bt->pixelclock);
+               return -ERANGE;
+       }
+
+       if (debug > 1)
+               adv7604_print_timings(sd, timings,
+                               "adv7604_query_dv_timings:", true);
+
+       return 0;
+}
+
+static int adv7604_s_dv_timings(struct v4l2_subdev *sd,
+               struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+       struct v4l2_bt_timings *bt;
+
+       if (!timings)
+               return -EINVAL;
+
+       bt = &timings->bt;
+
+       if ((!DIGITAL_INPUT && bt->pixelclock > 170000000) ||
+                       (DIGITAL_INPUT && bt->pixelclock > 225000000)) {
+               v4l2_dbg(1, debug, sd, "%s: pixelclock out of range %d\n",
+                               __func__, (u32)bt->pixelclock);
+               return -ERANGE;
+       }
+       adv7604_fill_optional_dv_timings_fields(sd, timings);
+
+       state->timings = *timings;
+
+       /* freerun */
+       configure_free_run(sd, bt);
+
+       set_rgb_quantization_range(sd);
+
+
+       if (debug > 1)
+               adv7604_print_timings(sd, timings,
+                               "adv7604_s_dv_timings:", true);
+       return 0;
+}
+
+static int adv7604_g_dv_timings(struct v4l2_subdev *sd,
+               struct v4l2_dv_timings *timings)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       *timings = state->timings;
+       return 0;
+}
+
+static void enable_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+{
+       switch (prim_mode) {
+       case ADV7604_PRIM_MODE_COMP:
+       case ADV7604_PRIM_MODE_RGB:
+               /* enable */
+               io_write(sd, 0x15, 0xb0);   /* Disable Tristate of Pins (no audio) */
+               break;
+       case ADV7604_PRIM_MODE_HDMI_COMP:
+       case ADV7604_PRIM_MODE_HDMI_GR:
+               /* enable */
+               hdmi_write(sd, 0x1a, 0x0a); /* Unmute audio */
+               hdmi_write(sd, 0x01, 0x00); /* Enable HDMI clock terminators */
+               io_write(sd, 0x15, 0xa0);   /* Disable Tristate of Pins */
+               break;
+       default:
+               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n",
+                               __func__, prim_mode);
+               break;
+       }
+}
+
+static void disable_input(struct v4l2_subdev *sd)
+{
+       /* disable */
+       io_write(sd, 0x15, 0xbe);   /* Tristate all outputs from video core */
+       hdmi_write(sd, 0x1a, 0x1a); /* Mute audio */
+       hdmi_write(sd, 0x01, 0x78); /* Disable HDMI clock terminators */
+}
+
+static void select_input(struct v4l2_subdev *sd, enum adv7604_prim_mode prim_mode)
+{
+       switch (prim_mode) {
+       case ADV7604_PRIM_MODE_COMP:
+       case ADV7604_PRIM_MODE_RGB:
+               /* set mode and select free run resolution */
+               io_write(sd, 0x00, 0x07); /* video std */
+               io_write(sd, 0x01, 0x02); /* prim mode */
+               /* enable embedded syncs for auto graphics mode */
+               cp_write_and_or(sd, 0x81, 0xef, 0x10);
+
+               /* reset ADI recommended settings for HDMI: */
+               /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+               hdmi_write(sd, 0x0d, 0x04); /* HDMI filter optimization */
+               hdmi_write(sd, 0x3d, 0x00); /* DDC bus active pull-up control */
+               hdmi_write(sd, 0x3e, 0x74); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x57, 0x74); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x58, 0x63); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x8d, 0x18); /* equaliser */
+               hdmi_write(sd, 0x8e, 0x34); /* equaliser */
+               hdmi_write(sd, 0x93, 0x88); /* equaliser */
+               hdmi_write(sd, 0x94, 0x2e); /* equaliser */
+               hdmi_write(sd, 0x96, 0x00); /* enable automatic EQ changing */
+
+               afe_write(sd, 0x00, 0x08); /* power up ADC */
+               afe_write(sd, 0x01, 0x06); /* power up Analog Front End */
+               afe_write(sd, 0xc8, 0x00); /* phase control */
+
+               /* set ADI recommended settings for digitizer */
+               /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+               afe_write(sd, 0x12, 0x7b); /* ADC noise shaping filter controls */
+               afe_write(sd, 0x0c, 0x1f); /* CP core gain controls */
+               cp_write(sd, 0x3e, 0x04); /* CP core pre-gain control */
+               cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
+               cp_write(sd, 0x40, 0x5c); /* CP core pre-gain control. Graphics mode */
+               break;
+
+       case ADV7604_PRIM_MODE_HDMI_COMP:
+       case ADV7604_PRIM_MODE_HDMI_GR:
+               /* set mode and select free run resolution */
+               /* video std */
+               io_write(sd, 0x00,
+                       (prim_mode == ADV7604_PRIM_MODE_HDMI_GR) ? 0x02 : 0x1e);
+               io_write(sd, 0x01, prim_mode); /* prim mode */
+               /* disable embedded syncs for auto graphics mode */
+               cp_write_and_or(sd, 0x81, 0xef, 0x00);
+
+               /* set ADI recommended settings for HDMI: */
+               /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 4. */
+               hdmi_write(sd, 0x0d, 0x84); /* HDMI filter optimization */
+               hdmi_write(sd, 0x3d, 0x10); /* DDC bus active pull-up control */
+               hdmi_write(sd, 0x3e, 0x39); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x4e, 0x3b); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x57, 0xb6); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x58, 0x03); /* TMDS PLL optimization */
+               hdmi_write(sd, 0x8d, 0x18); /* equaliser */
+               hdmi_write(sd, 0x8e, 0x34); /* equaliser */
+               hdmi_write(sd, 0x93, 0x8b); /* equaliser */
+               hdmi_write(sd, 0x94, 0x2d); /* equaliser */
+               hdmi_write(sd, 0x96, 0x01); /* enable automatic EQ changing */
+
+               afe_write(sd, 0x00, 0xff); /* power down ADC */
+               afe_write(sd, 0x01, 0xfe); /* power down Analog Front End */
+               afe_write(sd, 0xc8, 0x40); /* phase control */
+
+               /* reset ADI recommended settings for digitizer */
+               /* "ADV7604 Register Settings Recommendations (rev. 2.5, June 2010)" p. 17. */
+               afe_write(sd, 0x12, 0xfb); /* ADC noise shaping filter controls */
+               afe_write(sd, 0x0c, 0x0d); /* CP core gain controls */
+               cp_write(sd, 0x3e, 0x00); /* CP core pre-gain control */
+               cp_write(sd, 0xc3, 0x39); /* CP coast control. Graphics mode */
+               cp_write(sd, 0x40, 0x80); /* CP core pre-gain control. Graphics mode */
+
+               break;
+       default:
+               v4l2_err(sd, "%s: reserved primary mode 0x%0x\n", __func__, prim_mode);
+               break;
+       }
+}
+
+static int adv7604_s_routing(struct v4l2_subdev *sd,
+               u32 input, u32 output, u32 config)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       v4l2_dbg(2, debug, sd, "%s: input %d", __func__, input);
+
+       switch (input) {
+       case 0:
+               /* TODO select HDMI_COMP or HDMI_GR */
+               state->prim_mode = ADV7604_PRIM_MODE_HDMI_COMP;
+               break;
+       case 1:
+               state->prim_mode = ADV7604_PRIM_MODE_RGB;
+               break;
+       case 2:
+               state->prim_mode = ADV7604_PRIM_MODE_COMP;
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       disable_input(sd);
+
+       select_input(sd, state->prim_mode);
+
+       enable_input(sd, state->prim_mode);
+
+       return 0;
+}
+
+static int adv7604_enum_mbus_fmt(struct v4l2_subdev *sd, unsigned int index,
+                            enum v4l2_mbus_pixelcode *code)
+{
+       if (index)
+               return -EINVAL;
+       /* Good enough for now */
+       *code = V4L2_MBUS_FMT_FIXED;
+       return 0;
+}
+
+static int adv7604_g_mbus_fmt(struct v4l2_subdev *sd,
+               struct v4l2_mbus_framefmt *fmt)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       fmt->width = state->timings.bt.width;
+       fmt->height = state->timings.bt.height;
+       fmt->code = V4L2_MBUS_FMT_FIXED;
+       fmt->field = V4L2_FIELD_NONE;
+       if (state->timings.bt.standards & V4L2_DV_BT_STD_CEA861) {
+               fmt->colorspace = (state->timings.bt.height <= 576) ?
+                       V4L2_COLORSPACE_SMPTE170M : V4L2_COLORSPACE_REC709;
+       }
+       return 0;
+}
+
+static int adv7604_isr(struct v4l2_subdev *sd, u32 status, bool *handled)
+{
+       struct adv7604_state *state = to_state(sd);
+       u8 fmt_change, fmt_change_digital, tx_5v;
+
+       /* format change */
+       fmt_change = io_read(sd, 0x43) & 0x98;
+       if (fmt_change)
+               io_write(sd, 0x44, fmt_change);
+       fmt_change_digital = DIGITAL_INPUT ? (io_read(sd, 0x6b) & 0xc0) : 0;
+       if (fmt_change_digital)
+               io_write(sd, 0x6c, fmt_change_digital);
+       if (fmt_change || fmt_change_digital) {
+               v4l2_dbg(1, debug, sd,
+                       "%s: ADV7604_FMT_CHANGE, fmt_change = 0x%x, fmt_change_digital = 0x%x\n",
+                       __func__, fmt_change, fmt_change_digital);
+               v4l2_subdev_notify(sd, ADV7604_FMT_CHANGE, NULL);
+               if (handled)
+                       *handled = true;
+       }
+       /* tx 5v detect */
+       tx_5v = io_read(sd, 0x70) & 0x10;
+       if (tx_5v) {
+               v4l2_dbg(1, debug, sd, "%s: tx_5v: 0x%x\n", __func__, tx_5v);
+               io_write(sd, 0x71, tx_5v);
+               adv7604_s_detect_tx_5v_ctrl(sd);
+               if (handled)
+                       *handled = true;
+       }
+       return 0;
+}
+
+static int adv7604_get_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+       struct adv7604_state *state = to_state(sd);
+
+       if (edid->pad != 0)
+               return -EINVAL;
+       if (edid->blocks == 0)
+               return -EINVAL;
+       if (edid->start_block >= state->edid_blocks)
+               return -EINVAL;
+       if (edid->start_block + edid->blocks > state->edid_blocks)
+               edid->blocks = state->edid_blocks - edid->start_block;
+       if (!edid->edid)
+               return -EINVAL;
+       memcpy(edid->edid + edid->start_block * 128,
+              state->edid + edid->start_block * 128,
+              edid->blocks * 128);
+       return 0;
+}
+
+static int adv7604_set_edid(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid)
+{
+       struct adv7604_state *state = to_state(sd);
+       int err;
+
+       if (edid->pad != 0)
+               return -EINVAL;
+       if (edid->start_block != 0)
+               return -EINVAL;
+       if (edid->blocks == 0) {
+               /* Pull down the hotplug pin */
+               v4l2_subdev_notify(sd, ADV7604_HOTPLUG, (void *)0);
+               /* Disables I2C access to internal EDID ram from DDC port */
+               rep_write_and_or(sd, 0x77, 0xf0, 0x0);
+               state->edid_blocks = 0;
+               /* Fall back to a 16:9 aspect ratio */
+               state->aspect_ratio.numerator = 16;
+               state->aspect_ratio.denominator = 9;
+               return 0;
+       }
+       if (edid->blocks > 2)
+               return -E2BIG;
+       if (!edid->edid)
+               return -EINVAL;
+       memcpy(state->edid, edid->edid, 128 * edid->blocks);
+       state->edid_blocks = edid->blocks;
+       state->aspect_ratio = v4l2_calc_aspect_ratio(edid->edid[0x15],
+                       edid->edid[0x16]);
+       err = edid_write_block(sd, 128 * edid->blocks, state->edid);
+       if (err < 0)
+               v4l2_err(sd, "error %d writing edid\n", err);
+       return err;
+}
+
+/*********** avi info frame CEA-861-E **************/
+
+static void print_avi_infoframe(struct v4l2_subdev *sd)
+{
+       int i;
+       u8 buf[14];
+       u8 avi_len;
+       u8 avi_ver;
+
+       if (!(hdmi_read(sd, 0x05) & 0x80)) {
+               v4l2_info(sd, "receive DVI-D signal (AVI infoframe not supported)\n");
+               return;
+       }
+       if (!(io_read(sd, 0x60) & 0x01)) {
+               v4l2_info(sd, "AVI infoframe not received\n");
+               return;
+       }
+
+       if (io_read(sd, 0x83) & 0x01) {
+               v4l2_info(sd, "AVI infoframe checksum error has occurred earlier\n");
+               io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
+               if (io_read(sd, 0x83) & 0x01) {
+                       v4l2_info(sd, "AVI infoframe checksum error still present\n");
+                       io_write(sd, 0x85, 0x01); /* clear AVI_INF_CKS_ERR_RAW */
+               }
+       }
+
+       avi_len = infoframe_read(sd, 0xe2);
+       avi_ver = infoframe_read(sd, 0xe1);
+       v4l2_info(sd, "AVI infoframe version %d (%d byte)\n",
+                       avi_ver, avi_len);
+
+       if (avi_ver != 0x02)
+               return;
+
+       for (i = 0; i < 14; i++)
+               buf[i] = infoframe_read(sd, i);
+
+       v4l2_info(sd,
+               "\t%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n",
+               buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7],
+               buf[8], buf[9], buf[10], buf[11], buf[12], buf[13]);
+}
+
+static int adv7604_log_status(struct v4l2_subdev *sd)
+{
+       struct adv7604_state *state = to_state(sd);
+       struct v4l2_dv_timings timings;
+       struct stdi_readback stdi;
+       u8 reg_io_0x02 = io_read(sd, 0x02);
+
+       char *csc_coeff_sel_rb[16] = {
+               "bypassed", "YPbPr601 -> RGB", "reserved", "YPbPr709 -> RGB",
+               "reserved", "RGB -> YPbPr601", "reserved", "RGB -> YPbPr709",
+               "reserved", "YPbPr709 -> YPbPr601", "YPbPr601 -> YPbPr709",
+               "reserved", "reserved", "reserved", "reserved", "manual"
+       };
+       char *input_color_space_txt[16] = {
+               "RGB limited range (16-235)", "RGB full range (0-255)",
+               "YCbCr Bt.601 (16-235)", "YCbCr Bt.709 (16-235)",
+               "XvYCC Bt.601", "XvYCC Bt.709",
+               "YCbCr Bt.601 (0-255)", "YCbCr Bt.709 (0-255)",
+               "invalid", "invalid", "invalid", "invalid", "invalid",
+               "invalid", "invalid", "automatic"
+       };
+       char *rgb_quantization_range_txt[] = {
+               "Automatic",
+               "RGB limited range (16-235)",
+               "RGB full range (0-255)",
+       };
+
+       v4l2_info(sd, "-----Chip status-----\n");
+       v4l2_info(sd, "Chip power: %s\n", no_power(sd) ? "off" : "on");
+       v4l2_info(sd, "Connector type: %s\n", state->connector_hdmi ?
+                       "HDMI" : (DIGITAL_INPUT ? "DVI-D" : "DVI-A"));
+       v4l2_info(sd, "EDID: %s\n", ((rep_read(sd, 0x7d) & 0x01) &&
+                       (rep_read(sd, 0x77) & 0x01)) ? "enabled" : "disabled ");
+       v4l2_info(sd, "CEC: %s\n", !!(cec_read(sd, 0x2a) & 0x01) ?
+                       "enabled" : "disabled");
+
+       v4l2_info(sd, "-----Signal status-----\n");
+       v4l2_info(sd, "Cable detected (+5V power): %s\n",
+                       (io_read(sd, 0x6f) & 0x10) ? "true" : "false");
+       v4l2_info(sd, "TMDS signal detected: %s\n",
+                       no_signal_tmds(sd) ? "false" : "true");
+       v4l2_info(sd, "TMDS signal locked: %s\n",
+                       no_lock_tmds(sd) ? "false" : "true");
+       v4l2_info(sd, "SSPD locked: %s\n", no_lock_sspd(sd) ? "false" : "true");
+       v4l2_info(sd, "STDI locked: %s\n", no_lock_stdi(sd) ? "false" : "true");
+       v4l2_info(sd, "CP locked: %s\n", no_lock_cp(sd) ? "false" : "true");
+       v4l2_info(sd, "CP free run: %s\n",
+                       (!!(cp_read(sd, 0xff) & 0x10) ? "on" : "off"));
+       v4l2_info(sd, "Prim-mode = 0x%x, video std = 0x%x\n",
+                       io_read(sd, 0x01) & 0x0f, io_read(sd, 0x00) & 0x3f);
+
+       v4l2_info(sd, "-----Video Timings-----\n");
+       if (read_stdi(sd, &stdi))
+               v4l2_info(sd, "STDI: not locked\n");
+       else
+               v4l2_info(sd, "STDI: lcf (frame height - 1) = %d, bl = %d, lcvs (vsync) = %d, %s, %chsync, %cvsync\n",
+                               stdi.lcf, stdi.bl, stdi.lcvs,
+                               stdi.interlaced ? "interlaced" : "progressive",
+                               stdi.hs_pol, stdi.vs_pol);
+       if (adv7604_query_dv_timings(sd, &timings))
+               v4l2_info(sd, "No video detected\n");
+       else
+               adv7604_print_timings(sd, &timings, "Detected format:", true);
+       adv7604_print_timings(sd, &state->timings, "Configured format:", true);
+
+       v4l2_info(sd, "-----Color space-----\n");
+       v4l2_info(sd, "RGB quantization range ctrl: %s\n",
+                       rgb_quantization_range_txt[state->rgb_quantization_range]);
+       v4l2_info(sd, "Input color space: %s\n",
+                       input_color_space_txt[reg_io_0x02 >> 4]);
+       v4l2_info(sd, "Output color space: %s %s, saturator %s\n",
+                       (reg_io_0x02 & 0x02) ? "RGB" : "YCbCr",
+                       (reg_io_0x02 & 0x04) ? "(16-235)" : "(0-255)",
+                       ((reg_io_0x02 & 0x04) ^ (reg_io_0x02 & 0x01)) ?
+                                       "enabled" : "disabled");
+       v4l2_info(sd, "Color space conversion: %s\n",
+                       csc_coeff_sel_rb[cp_read(sd, 0xfc) >> 4]);
+
+       /* Digital video */
+       if (DIGITAL_INPUT) {
+               v4l2_info(sd, "-----HDMI status-----\n");
+               v4l2_info(sd, "HDCP encrypted content: %s\n",
+                               hdmi_read(sd, 0x05) & 0x40 ? "true" : "false");
+
+               print_avi_infoframe(sd);
+       }
+
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static const struct v4l2_ctrl_ops adv7604_ctrl_ops = {
+       .s_ctrl = adv7604_s_ctrl,
+};
+
+static const struct v4l2_subdev_core_ops adv7604_core_ops = {
+       .log_status = adv7604_log_status,
+       .g_ext_ctrls = v4l2_subdev_g_ext_ctrls,
+       .try_ext_ctrls = v4l2_subdev_try_ext_ctrls,
+       .s_ext_ctrls = v4l2_subdev_s_ext_ctrls,
+       .g_ctrl = v4l2_subdev_g_ctrl,
+       .s_ctrl = v4l2_subdev_s_ctrl,
+       .queryctrl = v4l2_subdev_queryctrl,
+       .querymenu = v4l2_subdev_querymenu,
+       .g_chip_ident = adv7604_g_chip_ident,
+       .interrupt_service_routine = adv7604_isr,
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .g_register = adv7604_g_register,
+       .s_register = adv7604_s_register,
+#endif
+};
+
+static const struct v4l2_subdev_video_ops adv7604_video_ops = {
+       .s_routing = adv7604_s_routing,
+       .g_input_status = adv7604_g_input_status,
+       .s_dv_timings = adv7604_s_dv_timings,
+       .g_dv_timings = adv7604_g_dv_timings,
+       .query_dv_timings = adv7604_query_dv_timings,
+       .enum_dv_timings = adv7604_enum_dv_timings,
+       .dv_timings_cap = adv7604_dv_timings_cap,
+       .enum_mbus_fmt = adv7604_enum_mbus_fmt,
+       .g_mbus_fmt = adv7604_g_mbus_fmt,
+       .try_mbus_fmt = adv7604_g_mbus_fmt,
+       .s_mbus_fmt = adv7604_g_mbus_fmt,
+};
+
+static const struct v4l2_subdev_pad_ops adv7604_pad_ops = {
+       .get_edid = adv7604_get_edid,
+       .set_edid = adv7604_set_edid,
+};
+
+static const struct v4l2_subdev_ops adv7604_ops = {
+       .core = &adv7604_core_ops,
+       .video = &adv7604_video_ops,
+       .pad = &adv7604_pad_ops,
+};
+
+/* -------------------------- custom ctrls ---------------------------------- */
+
+static const struct v4l2_ctrl_config adv7604_ctrl_analog_sampling_phase = {
+       .ops = &adv7604_ctrl_ops,
+       .id = V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE,
+       .name = "Analog Sampling Phase",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0,
+       .max = 0x1f,
+       .step = 1,
+       .def = 0,
+};
+
+static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color_manual = {
+       .ops = &adv7604_ctrl_ops,
+       .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL,
+       .name = "Free Running Color, Manual",
+       .type = V4L2_CTRL_TYPE_BOOLEAN,
+       .min = false,
+       .max = true,
+       .step = 1,
+       .def = false,
+};
+
+static const struct v4l2_ctrl_config adv7604_ctrl_free_run_color = {
+       .ops = &adv7604_ctrl_ops,
+       .id = V4L2_CID_ADV_RX_FREE_RUN_COLOR,
+       .name = "Free Running Color",
+       .type = V4L2_CTRL_TYPE_INTEGER,
+       .min = 0x0,
+       .max = 0xffffff,
+       .step = 0x1,
+       .def = 0x0,
+};
+
+/* ----------------------------------------------------------------------- */
+
+static int adv7604_core_init(struct v4l2_subdev *sd)
+{
+       struct adv7604_state *state = to_state(sd);
+       struct adv7604_platform_data *pdata = &state->pdata;
+
+       hdmi_write(sd, 0x48,
+               (pdata->disable_pwrdnb ? 0x80 : 0) |
+               (pdata->disable_cable_det_rst ? 0x40 : 0));
+
+       disable_input(sd);
+
+       /* power */
+       io_write(sd, 0x0c, 0x42);   /* Power up part and power down VDP */
+       io_write(sd, 0x0b, 0x44);   /* Power down ESDP block */
+       cp_write(sd, 0xcf, 0x01);   /* Power down macrovision */
+
+       /* video format */
+       io_write_and_or(sd, 0x02, 0xf0,
+                       pdata->alt_gamma << 3 |
+                       pdata->op_656_range << 2 |
+                       pdata->rgb_out << 1 |
+                       pdata->alt_data_sat << 0);
+       io_write(sd, 0x03, pdata->op_format_sel);
+       io_write_and_or(sd, 0x04, 0x1f, pdata->op_ch_sel << 5);
+       io_write_and_or(sd, 0x05, 0xf0, pdata->blank_data << 3 |
+                                       pdata->insert_av_codes << 2 |
+                                       pdata->replicate_av_codes << 1 |
+                                       pdata->invert_cbcr << 0);
+
+       /* TODO from platform data */
+       cp_write(sd, 0x69, 0x30);   /* Enable CP CSC */
+       io_write(sd, 0x06, 0xa6);   /* positive VS and HS */
+       io_write(sd, 0x14, 0x7f);   /* Drive strength adjusted to max */
+       cp_write(sd, 0xba, (pdata->hdmi_free_run_mode << 1) | 0x01); /* HDMI free run */
+       cp_write(sd, 0xf3, 0xdc); /* Low threshold to enter/exit free run mode */
+       cp_write(sd, 0xf9, 0x23); /*  STDI ch. 1 - LCVS change threshold -
+                                     ADI recommended setting [REF_01 c. 2.3.3] */
+       cp_write(sd, 0x45, 0x23); /*  STDI ch. 2 - LCVS change threshold -
+                                     ADI recommended setting [REF_01 c. 2.3.3] */
+       cp_write(sd, 0xc9, 0x2d); /* use prim_mode and vid_std as free run resolution
+                                    for digital formats */
+
+       /* TODO from platform data */
+       afe_write(sd, 0xb5, 0x01);  /* Setting MCLK to 256Fs */
+
+       afe_write(sd, 0x02, pdata->ain_sel); /* Select analog input muxing mode */
+       io_write_and_or(sd, 0x30, ~(1 << 4), pdata->output_bus_lsb_to_msb << 4);
+
+       state->prim_mode = pdata->prim_mode;
+       select_input(sd, pdata->prim_mode);
+
+       enable_input(sd, pdata->prim_mode);
+
+       /* interrupts */
+       io_write(sd, 0x40, 0xc2); /* Configure INT1 */
+       io_write(sd, 0x41, 0xd7); /* STDI irq for any change, disable INT2 */
+       io_write(sd, 0x46, 0x98); /* Enable SSPD, STDI and CP unlocked interrupts */
+       io_write(sd, 0x6e, 0xc0); /* Enable V_LOCKED and DE_REGEN_LCK interrupts */
+       io_write(sd, 0x73, 0x10); /* Enable CABLE_DET_A_ST (+5v) interrupt */
+
+       return v4l2_ctrl_handler_setup(sd->ctrl_handler);
+}
+
+static void adv7604_unregister_clients(struct adv7604_state *state)
+{
+       if (state->i2c_avlink)
+               i2c_unregister_device(state->i2c_avlink);
+       if (state->i2c_cec)
+               i2c_unregister_device(state->i2c_cec);
+       if (state->i2c_infoframe)
+               i2c_unregister_device(state->i2c_infoframe);
+       if (state->i2c_esdp)
+               i2c_unregister_device(state->i2c_esdp);
+       if (state->i2c_dpp)
+               i2c_unregister_device(state->i2c_dpp);
+       if (state->i2c_afe)
+               i2c_unregister_device(state->i2c_afe);
+       if (state->i2c_repeater)
+               i2c_unregister_device(state->i2c_repeater);
+       if (state->i2c_edid)
+               i2c_unregister_device(state->i2c_edid);
+       if (state->i2c_hdmi)
+               i2c_unregister_device(state->i2c_hdmi);
+       if (state->i2c_test)
+               i2c_unregister_device(state->i2c_test);
+       if (state->i2c_cp)
+               i2c_unregister_device(state->i2c_cp);
+       if (state->i2c_vdp)
+               i2c_unregister_device(state->i2c_vdp);
+}
+
+static struct i2c_client *adv7604_dummy_client(struct v4l2_subdev *sd,
+                                                       u8 addr, u8 io_reg)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+
+       if (addr)
+               io_write(sd, io_reg, addr << 1);
+       return i2c_new_dummy(client->adapter, io_read(sd, io_reg) >> 1);
+}
+
+static int adv7604_probe(struct i2c_client *client,
+                        const struct i2c_device_id *id)
+{
+       struct adv7604_state *state;
+       struct adv7604_platform_data *pdata = client->dev.platform_data;
+       struct v4l2_ctrl_handler *hdl;
+       struct v4l2_subdev *sd;
+       int err;
+
+       /* Check if the adapter supports the needed features */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+               return -EIO;
+       v4l_dbg(1, debug, client, "detecting adv7604 client on address 0x%x\n",
+                       client->addr << 1);
+
+       state = kzalloc(sizeof(struct adv7604_state), GFP_KERNEL);
+       if (!state) {
+               v4l_err(client, "Could not allocate adv7604_state memory!\n");
+               return -ENOMEM;
+       }
+
+       /* platform data */
+       if (!pdata) {
+               v4l_err(client, "No platform data!\n");
+               err = -ENODEV;
+               goto err_state;
+       }
+       memcpy(&state->pdata, pdata, sizeof(state->pdata));
+
+       sd = &state->sd;
+       v4l2_i2c_subdev_init(sd, client, &adv7604_ops);
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+       state->connector_hdmi = pdata->connector_hdmi;
+
+       /* i2c access to adv7604? */
+       if (adv_smbus_read_byte_data_check(client, 0xfb, false) != 0x68) {
+               v4l2_info(sd, "not an adv7604 on address 0x%x\n",
+                               client->addr << 1);
+               err = -ENODEV;
+               goto err_state;
+       }
+
+       /* control handlers */
+       hdl = &state->hdl;
+       v4l2_ctrl_handler_init(hdl, 9);
+
+       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+                       V4L2_CID_BRIGHTNESS, -128, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+                       V4L2_CID_CONTRAST, 0, 255, 1, 128);
+       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+                       V4L2_CID_SATURATION, 0, 255, 1, 128);
+       v4l2_ctrl_new_std(hdl, &adv7604_ctrl_ops,
+                       V4L2_CID_HUE, 0, 128, 1, 0);
+
+       /* private controls */
+       state->detect_tx_5v_ctrl = v4l2_ctrl_new_std(hdl, NULL,
+                       V4L2_CID_DV_RX_POWER_PRESENT, 0, 1, 0, 0);
+       state->detect_tx_5v_ctrl->is_private = true;
+       state->rgb_quantization_range_ctrl =
+               v4l2_ctrl_new_std_menu(hdl, &adv7604_ctrl_ops,
+                       V4L2_CID_DV_RX_RGB_RANGE, V4L2_DV_RGB_RANGE_FULL,
+                       0, V4L2_DV_RGB_RANGE_AUTO);
+       state->rgb_quantization_range_ctrl->is_private = true;
+
+       /* custom controls */
+       state->analog_sampling_phase_ctrl =
+               v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_analog_sampling_phase, NULL);
+       state->analog_sampling_phase_ctrl->is_private = true;
+       state->free_run_color_manual_ctrl =
+               v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color_manual, NULL);
+       state->free_run_color_manual_ctrl->is_private = true;
+       state->free_run_color_ctrl =
+               v4l2_ctrl_new_custom(hdl, &adv7604_ctrl_free_run_color, NULL);
+       state->free_run_color_ctrl->is_private = true;
+
+       sd->ctrl_handler = hdl;
+       if (hdl->error) {
+               err = hdl->error;
+               goto err_hdl;
+       }
+       if (adv7604_s_detect_tx_5v_ctrl(sd)) {
+               err = -ENODEV;
+               goto err_hdl;
+       }
+
+       state->i2c_avlink = adv7604_dummy_client(sd, pdata->i2c_avlink, 0xf3);
+       state->i2c_cec = adv7604_dummy_client(sd, pdata->i2c_cec, 0xf4);
+       state->i2c_infoframe = adv7604_dummy_client(sd, pdata->i2c_infoframe, 0xf5);
+       state->i2c_esdp = adv7604_dummy_client(sd, pdata->i2c_esdp, 0xf6);
+       state->i2c_dpp = adv7604_dummy_client(sd, pdata->i2c_dpp, 0xf7);
+       state->i2c_afe = adv7604_dummy_client(sd, pdata->i2c_afe, 0xf8);
+       state->i2c_repeater = adv7604_dummy_client(sd, pdata->i2c_repeater, 0xf9);
+       state->i2c_edid = adv7604_dummy_client(sd, pdata->i2c_edid, 0xfa);
+       state->i2c_hdmi = adv7604_dummy_client(sd, pdata->i2c_hdmi, 0xfb);
+       state->i2c_test = adv7604_dummy_client(sd, pdata->i2c_test, 0xfc);
+       state->i2c_cp = adv7604_dummy_client(sd, pdata->i2c_cp, 0xfd);
+       state->i2c_vdp = adv7604_dummy_client(sd, pdata->i2c_vdp, 0xfe);
+       if (!state->i2c_avlink || !state->i2c_cec || !state->i2c_infoframe ||
+           !state->i2c_esdp || !state->i2c_dpp || !state->i2c_afe ||
+           !state->i2c_repeater || !state->i2c_edid || !state->i2c_hdmi ||
+           !state->i2c_test || !state->i2c_cp || !state->i2c_vdp) {
+               err = -ENOMEM;
+               v4l2_err(sd, "failed to create all i2c clients\n");
+               goto err_i2c;
+       }
+
+       /* work queues */
+       state->work_queues = create_singlethread_workqueue(client->name);
+       if (!state->work_queues) {
+               v4l2_err(sd, "Could not create work queue\n");
+               err = -ENOMEM;
+               goto err_i2c;
+       }
+
+       INIT_DELAYED_WORK(&state->delayed_work_enable_hotplug,
+                       adv7604_delayed_work_enable_hotplug);
+
+       state->pad.flags = MEDIA_PAD_FL_SOURCE;
+       err = media_entity_init(&sd->entity, 1, &state->pad, 0);
+       if (err)
+               goto err_work_queues;
+
+       err = adv7604_core_init(sd);
+       if (err)
+               goto err_entity;
+       v4l2_info(sd, "%s found @ 0x%x (%s)\n", client->name,
+                       client->addr << 1, client->adapter->name);
+       return 0;
+
+err_entity:
+       media_entity_cleanup(&sd->entity);
+err_work_queues:
+       cancel_delayed_work(&state->delayed_work_enable_hotplug);
+       destroy_workqueue(state->work_queues);
+err_i2c:
+       adv7604_unregister_clients(state);
+err_hdl:
+       v4l2_ctrl_handler_free(hdl);
+err_state:
+       kfree(state);
+       return err;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static int adv7604_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct adv7604_state *state = to_state(sd);
+
+       cancel_delayed_work(&state->delayed_work_enable_hotplug);
+       destroy_workqueue(state->work_queues);
+       v4l2_device_unregister_subdev(sd);
+       media_entity_cleanup(&sd->entity);
+       adv7604_unregister_clients(to_state(sd));
+       v4l2_ctrl_handler_free(sd->ctrl_handler);
+       kfree(to_state(sd));
+       return 0;
+}
+
+/* ----------------------------------------------------------------------- */
+
+static struct i2c_device_id adv7604_id[] = {
+       { "adv7604", 0 },
+       { }
+};
+MODULE_DEVICE_TABLE(i2c, adv7604_id);
+
+static struct i2c_driver adv7604_driver = {
+       .driver = {
+               .owner = THIS_MODULE,
+               .name = "adv7604",
+       },
+       .probe = adv7604_probe,
+       .remove = adv7604_remove,
+       .id_table = adv7604_id,
+};
+
+module_i2c_driver(adv7604_driver);
similarity index 99%
rename from drivers/media/video/as3645a.c
rename to drivers/media/i2c/as3645a.c
index c4b03572dce85862ea048026f8774693103f3fb6..3bfdbf9d9bf1b4accb9632dd2f831d64fe89c12f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/as3645a.c - AS3645A and LM3555 flash controllers driver
+ * drivers/media/i2c/as3645a.c - AS3645A and LM3555 flash controllers driver
  *
  * Copyright (C) 2008-2011 Nokia Corporation
  * Copyright (c) 2011, Intel Corporation.
similarity index 80%
rename from drivers/media/video/cx25840/Makefile
rename to drivers/media/i2c/cx25840/Makefile
index dc40dde2e0c8449a85bb81119b319168b99532e3..898eb13340ae193ef8937c709987f65dbcab209b 100644 (file)
@@ -3,4 +3,4 @@ cx25840-objs    := cx25840-core.o cx25840-audio.o cx25840-firmware.o \
 
 obj-$(CONFIG_VIDEO_CX25840) += cx25840.o
 
-ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/i2c
similarity index 92%
rename from drivers/media/video/cx25840/cx25840-firmware.c
rename to drivers/media/i2c/cx25840/cx25840-firmware.c
index 8150200511daed0ce52918e0e9024a2aa762002c..b3169f94ece879ee89ecb45d61e4a390927b5582 100644 (file)
@@ -61,6 +61,10 @@ static void end_fw_load(struct i2c_client *client)
        cx25840_write(client, 0x803, 0x03);
 }
 
+#define CX2388x_FIRMWARE "v4l-cx23885-avcore-01.fw"
+#define CX231xx_FIRMWARE "v4l-cx231xx-avcore-01.fw"
+#define CX25840_FIRMWARE "v4l-cx25840.fw"
+
 static const char *get_fw_name(struct i2c_client *client)
 {
        struct cx25840_state *state = to_state(i2c_get_clientdata(client));
@@ -68,10 +72,10 @@ static const char *get_fw_name(struct i2c_client *client)
        if (firmware[0])
                return firmware;
        if (is_cx2388x(state))
-               return "v4l-cx23885-avcore-01.fw";
+               return CX2388x_FIRMWARE;
        if (is_cx231xx(state))
-               return "v4l-cx231xx-avcore-01.fw";
-       return "v4l-cx25840.fw";
+               return CX231xx_FIRMWARE;
+       return CX25840_FIRMWARE;
 }
 
 static int check_fw_load(struct i2c_client *client, int size)
@@ -164,3 +168,8 @@ int cx25840_loadfw(struct i2c_client *client)
 
        return check_fw_load(client, size);
 }
+
+MODULE_FIRMWARE(CX2388x_FIRMWARE);
+MODULE_FIRMWARE(CX231xx_FIRMWARE);
+MODULE_FIRMWARE(CX25840_FIRMWARE);
+
similarity index 98%
rename from drivers/media/video/cx25840/cx25840-vbi.c
rename to drivers/media/i2c/cx25840/cx25840-vbi.c
index 64a4004f8a97c9f041296cd1da2799a5042129b2..c39e91dc113794b936fd484da0686a635724ff01 100644 (file)
@@ -96,7 +96,8 @@ int cx25840_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
        int is_pal = !(state->std & V4L2_STD_525_60);
        int i;
 
-       memset(svbi, 0, sizeof(*svbi));
+       memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
+       svbi->service_set = 0;
        /* we're done if raw VBI is active */
        if ((cx25840_read(client, 0x404) & 0x10) == 0)
                return 0;
similarity index 99%
rename from drivers/media/video/ks0127.c
rename to drivers/media/i2c/ks0127.c
index ee7ca2dcca2fd3cf8d38502b618b25be1b50d4b0..04a6efa37cc376eb2c49637b26a499da8665439b 100644 (file)
@@ -319,8 +319,17 @@ static u8 ks0127_read(struct v4l2_subdev *sd, u8 reg)
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        char val = 0;
        struct i2c_msg msgs[] = {
-               { client->addr, 0, sizeof(reg), &reg },
-               { client->addr, I2C_M_RD | I2C_M_NO_RD_ACK, sizeof(val), &val }
+               {
+                       .addr = client->addr,
+                       .len = sizeof(reg),
+                       .buf = &reg
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD | I2C_M_NO_RD_ACK,
+                       .len = sizeof(val),
+                       .buf = &val
+               }
        };
        int ret;
 
similarity index 96%
rename from drivers/media/video/m5mols/m5mols.h
rename to drivers/media/i2c/m5mols/m5mols.h
index bb589917b65b26b743744ed1c78234060238fb2d..4ab8b370e6650c9cf193ee3ee2220b13d65e028b 100644 (file)
 #include <media/v4l2-subdev.h>
 #include "m5mols_reg.h"
 
+
+/* An amount of data transmitted in addition to the value
+ * determined by CAPP_JPEG_SIZE_MAX register.
+ */
+#define M5MOLS_JPEG_TAGS_SIZE          0x20000
+#define M5MOLS_MAIN_JPEG_SIZE_MAX      (5 * SZ_1M)
+
 extern int m5mols_debug;
 
 enum m5mols_restype {
@@ -67,12 +74,14 @@ struct m5mols_exif {
 /**
  * struct m5mols_capture - Structure for the capture capability
  * @exif: EXIF information
+ * @buf_size: internal JPEG frame buffer size, in bytes
  * @main: size in bytes of the main image
  * @thumb: size in bytes of the thumb image, if it was accompanied
  * @total: total size in bytes of the produced image
  */
 struct m5mols_capture {
        struct m5mols_exif exif;
+       unsigned int buf_size;
        u32 main;
        u32 thumb;
        u32 total;
@@ -155,8 +164,6 @@ struct m5mols_version {
  * @pdata: platform data
  * @sd: v4l-subdev instance
  * @pad: media pad
- * @ffmt: current fmt according to resolution type
- * @res_type: current resolution type
  * @irq_waitq: waitqueue for the capture
  * @irq_done: set to 1 in the interrupt handler
  * @handle: control handler
@@ -174,6 +181,10 @@ struct m5mols_version {
  * @wdr: wide dynamic range control
  * @stabilization: image stabilization control
  * @jpeg_quality: JPEG compression quality control
+ * @set_power: optional power callback to the board code
+ * @lock: mutex protecting the structure fields below
+ * @ffmt: current fmt according to resolution type
+ * @res_type: current resolution type
  * @ver: information of the version
  * @cap: the capture mode attributes
  * @isp_ready: 1 when the ISP controller has completed booting
@@ -181,14 +192,11 @@ struct m5mols_version {
  * @ctrl_sync: 1 when the control handler state is restored in H/W
  * @resolution:        register value for current resolution
  * @mode: register value for current operation mode
- * @set_power: optional power callback to the board code
  */
 struct m5mols_info {
        const struct m5mols_platform_data *pdata;
        struct v4l2_subdev sd;
        struct media_pad pad;
-       struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
-       int res_type;
 
        wait_queue_head_t irq_waitq;
        atomic_t irq_done;
@@ -216,6 +224,13 @@ struct m5mols_info {
        struct v4l2_ctrl *stabilization;
        struct v4l2_ctrl *jpeg_quality;
 
+       int (*set_power)(struct device *dev, int on);
+
+       struct mutex lock;
+
+       struct v4l2_mbus_framefmt ffmt[M5MOLS_RESTYPE_MAX];
+       int res_type;
+
        struct m5mols_version ver;
        struct m5mols_capture cap;
 
@@ -225,8 +240,6 @@ struct m5mols_info {
 
        u8 resolution;
        u8 mode;
-
-       int (*set_power)(struct device *dev, int on);
 };
 
 #define is_available_af(__info)        (__info->ver.af)
@@ -323,12 +336,12 @@ static inline struct v4l2_subdev *to_sd(struct v4l2_ctrl *ctrl)
 static inline void m5mols_set_ctrl_mode(struct v4l2_ctrl *ctrl,
                                        unsigned int mode)
 {
-       ctrl->priv = (void *)mode;
+       ctrl->priv = (void *)(uintptr_t)mode;
 }
 
 static inline unsigned int m5mols_get_ctrl_mode(struct v4l2_ctrl *ctrl)
 {
-       return (unsigned int)ctrl->priv;
+       return (unsigned int)(uintptr_t)ctrl->priv;
 }
 
 #endif /* M5MOLS_H */
similarity index 96%
rename from drivers/media/video/m5mols/m5mols_capture.c
rename to drivers/media/i2c/m5mols/m5mols_capture.c
index cb243bd278ceecce60163b6eed41ce8cb2d5c019..ab34ccedf31ea7a1a72adfe9d3324103de92b7f7 100644 (file)
@@ -105,6 +105,7 @@ static int m5mols_capture_info(struct m5mols_info *info)
 
 int m5mols_start_capture(struct m5mols_info *info)
 {
+       unsigned int framesize = info->cap.buf_size - M5MOLS_JPEG_TAGS_SIZE;
        struct v4l2_subdev *sd = &info->sd;
        int ret;
 
@@ -120,6 +121,8 @@ int m5mols_start_capture(struct m5mols_info *info)
                ret = m5mols_write(sd, CAPP_YUVOUT_MAIN, REG_JPEG);
        if (!ret)
                ret = m5mols_write(sd, CAPP_MAIN_IMAGE_SIZE, info->resolution);
+       if (!ret)
+               ret = m5mols_write(sd, CAPP_JPEG_SIZE_MAX, framesize);
        if (!ret)
                ret = m5mols_set_mode(info, REG_CAPTURE);
        if (!ret)
similarity index 99%
rename from drivers/media/video/m5mols/m5mols_controls.c
rename to drivers/media/i2c/m5mols/m5mols_controls.c
index fdbc205a29698a1836b94d1fb9b6d9f8de0e798a..f34429e452abf4e01dfd71d38ceb690d3c5ab021 100644 (file)
@@ -463,8 +463,8 @@ static int m5mols_s_ctrl(struct v4l2_ctrl *ctrl)
                return 0;
        }
 
-       v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %#x\n",
-                __func__, ctrl->name, ctrl->val, (int)ctrl->priv);
+       v4l2_dbg(1, m5mols_debug, sd, "%s: %s, val: %d, priv: %p\n",
+                __func__, ctrl->name, ctrl->val, ctrl->priv);
 
        if (ctrl_mode && ctrl_mode != info->mode) {
                ret = m5mols_set_mode(info, ctrl_mode);
similarity index 91%
rename from drivers/media/video/m5mols/m5mols_core.c
rename to drivers/media/i2c/m5mols/m5mols_core.c
index ac7d28b6ddf25e44347cf1a931755c27e2bdd5ac..8131d651de9ef11ea5c10d8e4111e9c8e4468896 100644 (file)
@@ -551,13 +551,18 @@ static int m5mols_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
 {
        struct m5mols_info *info = to_m5mols(sd);
        struct v4l2_mbus_framefmt *format;
+       int ret = 0;
+
+       mutex_lock(&info->lock);
 
        format = __find_format(info, fh, fmt->which, info->res_type);
        if (!format)
-               return -EINVAL;
+               fmt->format = *format;
+       else
+               ret = -EINVAL;
 
-       fmt->format = *format;
-       return 0;
+       mutex_unlock(&info->lock);
+       return ret;
 }
 
 static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
@@ -578,6 +583,7 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        if (!sfmt)
                return 0;
 
+       mutex_lock(&info->lock);
 
        format->code = m5mols_default_ffmt[type].code;
        format->colorspace = V4L2_COLORSPACE_JPEG;
@@ -589,9 +595,55 @@ static int m5mols_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                info->res_type = type;
        }
 
+       mutex_unlock(&info->lock);
+       return ret;
+}
+
+static int m5mols_get_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       mutex_lock(&info->lock);
+       /*
+        * .get_frame_desc is only used for compressed formats,
+        * thus we always return the capture frame parameters here.
+        */
+       fd->entry[0].length = info->cap.buf_size;
+       fd->entry[0].pixelcode = info->ffmt[M5MOLS_RESTYPE_CAPTURE].code;
+       mutex_unlock(&info->lock);
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+
        return 0;
 }
 
+static int m5mols_set_frame_desc(struct v4l2_subdev *sd, unsigned int pad,
+                                struct v4l2_mbus_frame_desc *fd)
+{
+       struct m5mols_info *info = to_m5mols(sd);
+       struct v4l2_mbus_framefmt *mf = &info->ffmt[M5MOLS_RESTYPE_CAPTURE];
+
+       if (pad != 0 || fd == NULL)
+               return -EINVAL;
+
+       fd->entry[0].flags = V4L2_MBUS_FRAME_DESC_FL_LEN_MAX;
+       fd->num_entries = 1;
+       fd->entry[0].length = clamp_t(u32, fd->entry[0].length,
+                                     mf->width * mf->height,
+                                     M5MOLS_MAIN_JPEG_SIZE_MAX);
+       mutex_lock(&info->lock);
+       info->cap.buf_size = fd->entry[0].length;
+       mutex_unlock(&info->lock);
+
+       return 0;
+}
+
+
 static int m5mols_enum_mbus_code(struct v4l2_subdev *sd,
                                 struct v4l2_subdev_fh *fh,
                                 struct v4l2_subdev_mbus_code_enum *code)
@@ -608,6 +660,8 @@ static struct v4l2_subdev_pad_ops m5mols_pad_ops = {
        .enum_mbus_code = m5mols_enum_mbus_code,
        .get_fmt        = m5mols_get_fmt,
        .set_fmt        = m5mols_set_fmt,
+       .get_frame_desc = m5mols_get_frame_desc,
+       .set_frame_desc = m5mols_set_frame_desc,
 };
 
 /**
@@ -661,20 +715,25 @@ static int m5mols_start_monitor(struct m5mols_info *info)
 static int m5mols_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct m5mols_info *info = to_m5mols(sd);
-       u32 code = info->ffmt[info->res_type].code;
+       u32 code;
+       int ret;
 
-       if (enable) {
-               int ret = -EINVAL;
+       mutex_lock(&info->lock);
+       code = info->ffmt[info->res_type].code;
 
+       if (enable) {
                if (is_code(code, M5MOLS_RESTYPE_MONITOR))
                        ret = m5mols_start_monitor(info);
                if (is_code(code, M5MOLS_RESTYPE_CAPTURE))
                        ret = m5mols_start_capture(info);
-
-               return ret;
+               else
+                       ret = -EINVAL;
+       } else {
+               ret = m5mols_set_mode(info, REG_PARAMETER);
        }
 
-       return m5mols_set_mode(info, REG_PARAMETER);
+       mutex_unlock(&info->lock);
+       return ret;
 }
 
 static const struct v4l2_subdev_video_ops m5mols_video_ops = {
@@ -773,6 +832,20 @@ static int m5mols_fw_start(struct v4l2_subdev *sd)
        return ret;
 }
 
+/* Execute the lens soft-landing algorithm */
+static int m5mols_auto_focus_stop(struct m5mols_info *info)
+{
+       int ret;
+
+       ret = m5mols_write(&info->sd, AF_EXECUTE, REG_AF_STOP);
+       if (!ret)
+               ret = m5mols_write(&info->sd, AF_MODE, REG_AF_POWEROFF);
+       if (!ret)
+               ret = m5mols_busy_wait(&info->sd, SYSTEM_STATUS, REG_AF_IDLE,
+                                      0xff, -1);
+       return ret;
+}
+
 /**
  * m5mols_s_power - Main sensor power control function
  *
@@ -785,29 +858,26 @@ static int m5mols_s_power(struct v4l2_subdev *sd, int on)
        struct m5mols_info *info = to_m5mols(sd);
        int ret;
 
+       mutex_lock(&info->lock);
+
        if (on) {
                ret = m5mols_sensor_power(info, true);
                if (!ret)
                        ret = m5mols_fw_start(sd);
-               return ret;
-       }
+       } else {
+               if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
+                       ret = m5mols_set_mode(info, REG_MONITOR);
+                       if (!ret)
+                               ret = m5mols_auto_focus_stop(info);
+                       if (ret < 0)
+                               v4l2_warn(sd, "Soft landing lens failed\n");
+               }
+               ret = m5mols_sensor_power(info, false);
 
-       if (is_manufacturer(info, REG_SAMSUNG_TECHWIN)) {
-               ret = m5mols_set_mode(info, REG_MONITOR);
-               if (!ret)
-                       ret = m5mols_write(sd, AF_EXECUTE, REG_AF_STOP);
-               if (!ret)
-                       ret = m5mols_write(sd, AF_MODE, REG_AF_POWEROFF);
-               if (!ret)
-                       ret = m5mols_busy_wait(sd, SYSTEM_STATUS, REG_AF_IDLE,
-                                              0xff, -1);
-               if (ret < 0)
-                       v4l2_warn(sd, "Soft landing lens failed\n");
+               info->ctrl_sync = 0;
        }
 
-       ret = m5mols_sensor_power(info, false);
-       info->ctrl_sync = 0;
-
+       mutex_unlock(&info->lock);
        return ret;
 }
 
@@ -822,13 +892,6 @@ static int m5mols_log_status(struct v4l2_subdev *sd)
 
 static const struct v4l2_subdev_core_ops m5mols_core_ops = {
        .s_power        = m5mols_s_power,
-       .g_ctrl         = v4l2_subdev_g_ctrl,
-       .s_ctrl         = v4l2_subdev_s_ctrl,
-       .queryctrl      = v4l2_subdev_queryctrl,
-       .querymenu      = v4l2_subdev_querymenu,
-       .g_ext_ctrls    = v4l2_subdev_g_ext_ctrls,
-       .try_ext_ctrls  = v4l2_subdev_try_ext_ctrls,
-       .s_ext_ctrls    = v4l2_subdev_s_ext_ctrls,
        .log_status     = m5mols_log_status,
 };
 
@@ -919,6 +982,8 @@ static int __devinit m5mols_probe(struct i2c_client *client,
        sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
 
        init_waitqueue_head(&info->irq_waitq);
+       mutex_init(&info->lock);
+
        ret = request_irq(client->irq, m5mols_irq_handler,
                          IRQF_TRIGGER_RISING, MODULE_NAME, sd);
        if (ret) {
@@ -931,15 +996,17 @@ static int __devinit m5mols_probe(struct i2c_client *client,
 
        ret = m5mols_sensor_power(info, true);
        if (ret)
-               goto out_me;
+               goto out_irq;
 
        ret = m5mols_fw_start(sd);
        if (!ret)
                ret = m5mols_init_controls(sd);
 
-       m5mols_sensor_power(info, false);
+       ret = m5mols_sensor_power(info, false);
        if (!ret)
                return 0;
+out_irq:
+       free_irq(client->irq, sd);
 out_me:
        media_entity_cleanup(&sd->entity);
 out_reg:
similarity index 99%
rename from drivers/media/video/m5mols/m5mols_reg.h
rename to drivers/media/i2c/m5mols/m5mols_reg.h
index 14d4be72aeff67b09c9dafc98416490b1acc3412..58d8027508dfe338a7b4497b2fe77793cdf3312e 100644 (file)
 #define REG_JPEG               0x10
 
 #define CAPP_MAIN_IMAGE_SIZE   I2C_REG(CAT_CAPT_PARM, 0x01, 1)
+#define CAPP_JPEG_SIZE_MAX     I2C_REG(CAT_CAPT_PARM, 0x0f, 4)
 #define CAPP_JPEG_RATIO                I2C_REG(CAT_CAPT_PARM, 0x17, 1)
 
 #define CAPP_MCC_MODE          I2C_REG(CAT_CAPT_PARM, 0x1d, 1)
similarity index 98%
rename from drivers/media/video/msp3400-driver.c
rename to drivers/media/i2c/msp3400-driver.c
index aeb22be7dcbd80a11c545cafcc0dfe5e2da62fdd..766305f69a2899264d3819e8ebbda7e165d488af 100644 (file)
@@ -119,12 +119,31 @@ int msp_reset(struct i2c_client *client)
        static u8 write[3]     = { I2C_MSP_DSP + 1, 0x00, 0x1e };
        u8 read[2];
        struct i2c_msg reset[2] = {
-               { client->addr, I2C_M_IGNORE_NAK, 3, reset_off },
-               { client->addr, I2C_M_IGNORE_NAK, 3, reset_on  },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_IGNORE_NAK,
+                       .len = 3,
+                       .buf = reset_off
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_IGNORE_NAK,
+                       .len = 3,
+                       .buf = reset_on
+               },
        };
        struct i2c_msg test[2] = {
-               { client->addr, 0,        3, write },
-               { client->addr, I2C_M_RD, 2, read  },
+               {
+                       .addr = client->addr,
+                       .len = 3,
+                       .buf = write
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 2,
+                       .buf = read
+               },
        };
 
        v4l_dbg(3, msp_debug, client, "msp_reset\n");
@@ -143,8 +162,17 @@ static int msp_read(struct i2c_client *client, int dev, int addr)
        u8 write[3];
        u8 read[2];
        struct i2c_msg msgs[2] = {
-               { client->addr, 0,        3, write },
-               { client->addr, I2C_M_RD, 2, read  }
+               {
+                       .addr = client->addr,
+                       .len = 3,
+                       .buf = write
+               },
+               {
+                       .addr = client->addr,
+                       .flags = I2C_M_RD,
+                       .len = 2,
+                       .buf = read
+               }
        };
 
        write[0] = dev + 1;
similarity index 99%
rename from drivers/media/video/mt9m032.c
rename to drivers/media/i2c/mt9m032.c
index 445359c961136cd1595e59138c3e3a3b24ee90e2..f80c1d7ec88454def6d81bfaba52f98d0d83bbca 100644 (file)
@@ -781,7 +781,7 @@ static int mt9m032_probe(struct i2c_client *client,
        ret = mt9m032_write(client, MT9M032_RESET, 1);  /* reset on */
        if (ret < 0)
                goto error_entity;
-       mt9m032_write(client, MT9M032_RESET, 0);        /* reset off */
+       ret = mt9m032_write(client, MT9M032_RESET, 0);  /* reset off */
        if (ret < 0)
                goto error_entity;
 
similarity index 97%
rename from drivers/media/video/mt9p031.c
rename to drivers/media/i2c/mt9p031.c
index 3be537ef22d2f4138067ca9d09d48ffe65fb7cda..e32833262d32a6323c75f74e47dc89c9663d3ff4 100644 (file)
@@ -55,9 +55,9 @@
 #define                MT9P031_HORIZONTAL_BLANK_MIN            0
 #define                MT9P031_HORIZONTAL_BLANK_MAX            4095
 #define MT9P031_VERTICAL_BLANK                         0x06
-#define                MT9P031_VERTICAL_BLANK_MIN              0
-#define                MT9P031_VERTICAL_BLANK_MAX              4095
-#define                MT9P031_VERTICAL_BLANK_DEF              25
+#define                MT9P031_VERTICAL_BLANK_MIN              1
+#define                MT9P031_VERTICAL_BLANK_MAX              4096
+#define                MT9P031_VERTICAL_BLANK_DEF              26
 #define MT9P031_OUTPUT_CONTROL                         0x07
 #define                MT9P031_OUTPUT_CONTROL_CEN              2
 #define                MT9P031_OUTPUT_CONTROL_SYN              1
@@ -368,13 +368,13 @@ static int mt9p031_set_params(struct mt9p031 *mt9p031)
        /* Blanking - use minimum value for horizontal blanking and default
         * value for vertical blanking.
         */
-       hblank = 346 * ybin + 64 + (80 >> max_t(unsigned int, xbin, 3));
+       hblank = 346 * ybin + 64 + (80 >> min_t(unsigned int, xbin, 3));
        vblank = MT9P031_VERTICAL_BLANK_DEF;
 
-       ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank);
+       ret = mt9p031_write(client, MT9P031_HORIZONTAL_BLANK, hblank - 1);
        if (ret < 0)
                return ret;
-       ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank);
+       ret = mt9p031_write(client, MT9P031_VERTICAL_BLANK, vblank - 1);
        if (ret < 0)
                return ret;
 
@@ -574,7 +574,6 @@ static int mt9p031_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLC_AUTO              (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLC_TARGET_LEVEL      (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLC_ANALOG_OFFSET     (V4L2_CID_USER_BASE | 0x1004)
@@ -739,18 +738,6 @@ static const char * const mt9p031_test_pattern_menu[] = {
 
 static const struct v4l2_ctrl_config mt9p031_ctrls[] = {
        {
-               .ops            = &mt9p031_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_MENU,
-               .name           = "Test Pattern",
-               .min            = 0,
-               .max            = ARRAY_SIZE(mt9p031_test_pattern_menu) - 1,
-               .step           = 0,
-               .def            = 0,
-               .flags          = 0,
-               .menu_skip_mask = 0,
-               .qmenu          = mt9p031_test_pattern_menu,
-       }, {
                .ops            = &mt9p031_ctrl_ops,
                .id             = V4L2_CID_BLC_AUTO,
                .type           = V4L2_CTRL_TYPE_BOOLEAN,
@@ -950,7 +937,7 @@ static int mt9p031_probe(struct i2c_client *client,
        mt9p031->model = did->driver_data;
        mt9p031->reset = -1;
 
-       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 5);
+       v4l2_ctrl_handler_init(&mt9p031->ctrls, ARRAY_SIZE(mt9p031_ctrls) + 6);
 
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9P031_SHUTTER_WIDTH_MIN,
@@ -966,6 +953,10 @@ static int mt9p031_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9p031->ctrls, &mt9p031_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->target_freq,
                          pdata->target_freq, 1, pdata->target_freq);
+       v4l2_ctrl_new_std_menu_items(&mt9p031->ctrls, &mt9p031_ctrl_ops,
+                         V4L2_CID_TEST_PATTERN,
+                         ARRAY_SIZE(mt9p031_test_pattern_menu) - 1, 0,
+                         0, mt9p031_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9p031_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9p031->ctrls, &mt9p031_ctrls[i], NULL);
similarity index 97%
rename from drivers/media/video/mt9t001.c
rename to drivers/media/i2c/mt9t001.c
index 6d343adf891d1a5497b4cb4a4ecebaaf9328d1d0..2e189d8b71bb218725b76d894172420d30bdfe6a 100644 (file)
@@ -371,7 +371,7 @@ static int mt9t001_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 #define V4L2_CID_BLACK_LEVEL_AUTO      (V4L2_CID_USER_BASE | 0x1002)
 #define V4L2_CID_BLACK_LEVEL_OFFSET    (V4L2_CID_USER_BASE | 0x1003)
 #define V4L2_CID_BLACK_LEVEL_CALIBRATE (V4L2_CID_USER_BASE | 0x1004)
@@ -487,12 +487,11 @@ static int mt9t001_s_ctrl(struct v4l2_ctrl *ctrl)
                                     ctrl->val >> 16);
 
        case V4L2_CID_TEST_PATTERN:
-               ret = mt9t001_set_output_control(mt9t001,
+               return mt9t001_set_output_control(mt9t001,
                        ctrl->val ? 0 : MT9T001_OUTPUT_CONTROL_TEST_DATA,
                        ctrl->val ? MT9T001_OUTPUT_CONTROL_TEST_DATA : 0);
-               if (ret < 0)
-                       return ret;
 
+       case V4L2_CID_TEST_PATTERN_COLOR:
                return mt9t001_write(client, MT9T001_TEST_DATA, ctrl->val << 2);
 
        case V4L2_CID_BLACK_LEVEL_AUTO:
@@ -533,12 +532,17 @@ static struct v4l2_ctrl_ops mt9t001_ctrl_ops = {
        .s_ctrl = mt9t001_s_ctrl,
 };
 
+static const char * const mt9t001_test_pattern_menu[] = {
+       "Disabled",
+       "Enabled",
+};
+
 static const struct v4l2_ctrl_config mt9t001_ctrls[] = {
        {
                .ops            = &mt9t001_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
+               .id             = V4L2_CID_TEST_PATTERN_COLOR,
                .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
+               .name           = "Test Pattern Color",
                .min            = 0,
                .max            = 1023,
                .step           = 1,
@@ -741,7 +745,7 @@ static int mt9t001_probe(struct i2c_client *client,
                return -ENOMEM;
 
        v4l2_ctrl_handler_init(&mt9t001->ctrls, ARRAY_SIZE(mt9t001_ctrls) +
-                                               ARRAY_SIZE(mt9t001_gains) + 3);
+                                               ARRAY_SIZE(mt9t001_gains) + 4);
 
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_EXPOSURE, MT9T001_SHUTTER_WIDTH_MIN,
@@ -752,6 +756,10 @@ static int mt9t001_probe(struct i2c_client *client,
        v4l2_ctrl_new_std(&mt9t001->ctrls, &mt9t001_ctrl_ops,
                          V4L2_CID_PIXEL_RATE, pdata->ext_clk, pdata->ext_clk,
                          1, pdata->ext_clk);
+       v4l2_ctrl_new_std_menu_items(&mt9t001->ctrls, &mt9t001_ctrl_ops,
+                       V4L2_CID_TEST_PATTERN,
+                       ARRAY_SIZE(mt9t001_test_pattern_menu) - 1, 0,
+                       0, mt9t001_test_pattern_menu);
 
        for (i = 0; i < ARRAY_SIZE(mt9t001_ctrls); ++i)
                v4l2_ctrl_new_custom(&mt9t001->ctrls, &mt9t001_ctrls[i], NULL);
similarity index 84%
rename from drivers/media/video/mt9v032.c
rename to drivers/media/i2c/mt9v032.c
index 4ba4884c016eccfec828ecbc67134f6949c5e634..3f356cb282567e882361b7958146090d9092cb43 100644 (file)
@@ -29,6 +29,8 @@
 #define MT9V032_PIXEL_ARRAY_HEIGHT                     492
 #define MT9V032_PIXEL_ARRAY_WIDTH                      782
 
+#define MT9V032_SYSCLK_FREQ_DEF                                26600000
+
 #define MT9V032_CHIP_VERSION                           0x00
 #define                MT9V032_CHIP_ID_REV1                    0x1311
 #define                MT9V032_CHIP_ID_REV3                    0x1313
 #define                MT9V032_WINDOW_WIDTH_MAX                752
 #define MT9V032_HORIZONTAL_BLANKING                    0x05
 #define                MT9V032_HORIZONTAL_BLANKING_MIN         43
+#define                MT9V032_HORIZONTAL_BLANKING_DEF         94
 #define                MT9V032_HORIZONTAL_BLANKING_MAX         1023
 #define MT9V032_VERTICAL_BLANKING                      0x06
 #define                MT9V032_VERTICAL_BLANKING_MIN           4
+#define                MT9V032_VERTICAL_BLANKING_DEF           45
 #define                MT9V032_VERTICAL_BLANKING_MAX           3000
 #define MT9V032_CHIP_CONTROL                           0x07
 #define                MT9V032_CHIP_CONTROL_MASTER_MODE        (1 << 3)
@@ -123,13 +127,24 @@ struct mt9v032 {
        struct v4l2_rect crop;
 
        struct v4l2_ctrl_handler ctrls;
+       struct {
+               struct v4l2_ctrl *link_freq;
+               struct v4l2_ctrl *pixel_rate;
+       };
 
        struct mutex power_lock;
        int power_count;
 
        struct mt9v032_platform_data *pdata;
+
+       u32 sysclk;
        u16 chip_control;
        u16 aec_agc;
+       u16 hblank;
+       struct {
+               struct v4l2_ctrl *test_pattern;
+               struct v4l2_ctrl *test_pattern_color;
+       };
 };
 
 static struct mt9v032 *to_mt9v032(struct v4l2_subdev *sd)
@@ -187,13 +202,25 @@ mt9v032_update_aec_agc(struct mt9v032 *mt9v032, u16 which, int enable)
        return 0;
 }
 
+static int
+mt9v032_update_hblank(struct mt9v032 *mt9v032)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+       struct v4l2_rect *crop = &mt9v032->crop;
+
+       return mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
+                            max_t(s32, mt9v032->hblank, 660 - crop->width));
+}
+
+#define EXT_CLK                25000000
+
 static int mt9v032_power_on(struct mt9v032 *mt9v032)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
        int ret;
 
        if (mt9v032->pdata->set_clock) {
-               mt9v032->pdata->set_clock(&mt9v032->subdev, 25000000);
+               mt9v032->pdata->set_clock(&mt9v032->subdev, mt9v032->sysclk);
                udelay(1);
        }
 
@@ -319,8 +346,7 @@ static int mt9v032_s_stream(struct v4l2_subdev *subdev, int enable)
        if (ret < 0)
                return ret;
 
-       ret = mt9v032_write(client, MT9V032_HORIZONTAL_BLANKING,
-                           max(43, 660 - crop->width));
+       ret = mt9v032_update_hblank(mt9v032);
        if (ret < 0)
                return ret;
 
@@ -365,6 +391,18 @@ static int mt9v032_get_format(struct v4l2_subdev *subdev,
        return 0;
 }
 
+static void mt9v032_configure_pixel_rate(struct mt9v032 *mt9v032,
+                                        unsigned int hratio)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9v032->subdev);
+       int ret;
+
+       ret = v4l2_ctrl_s_ctrl_int64(mt9v032->pixel_rate,
+                                    mt9v032->sysclk / hratio);
+       if (ret < 0)
+               dev_warn(&client->dev, "failed to set pixel rate (%d)\n", ret);
+}
+
 static int mt9v032_set_format(struct v4l2_subdev *subdev,
                              struct v4l2_subdev_fh *fh,
                              struct v4l2_subdev_format *format)
@@ -395,6 +433,8 @@ static int mt9v032_set_format(struct v4l2_subdev *subdev,
                                            format->which);
        __format->width = __crop->width / hratio;
        __format->height = __crop->height / vratio;
+       if (format->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+               mt9v032_configure_pixel_rate(mt9v032, hratio);
 
        format->format = *__format;
 
@@ -450,6 +490,8 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
                                                    crop->which);
                __format->width = rect.width;
                __format->height = rect.height;
+               if (crop->which == V4L2_SUBDEV_FORMAT_ACTIVE)
+                       mt9v032_configure_pixel_rate(mt9v032, 1);
        }
 
        *__crop = rect;
@@ -462,13 +504,14 @@ static int mt9v032_set_crop(struct v4l2_subdev *subdev,
  * V4L2 subdev control operations
  */
 
-#define V4L2_CID_TEST_PATTERN          (V4L2_CID_USER_BASE | 0x1001)
+#define V4L2_CID_TEST_PATTERN_COLOR    (V4L2_CID_USER_BASE | 0x1001)
 
 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);
+       u32 freq;
        u16 data;
 
        switch (ctrl->id) {
@@ -487,8 +530,26 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                return mt9v032_write(client, 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);
+
+       case V4L2_CID_PIXEL_RATE:
+       case V4L2_CID_LINK_FREQ:
+               if (mt9v032->link_freq == NULL)
+                       break;
+
+               freq = mt9v032->pdata->link_freqs[mt9v032->link_freq->val];
+               mt9v032->pixel_rate->val64 = freq;
+               mt9v032->sysclk = freq;
+               break;
+
        case V4L2_CID_TEST_PATTERN:
-               switch (ctrl->val) {
+               switch (mt9v032->test_pattern->val) {
                case 0:
                        data = 0;
                        break;
@@ -505,13 +566,13 @@ static int mt9v032_s_ctrl(struct v4l2_ctrl *ctrl)
                             | MT9V032_TEST_PATTERN_ENABLE;
                        break;
                default:
-                       data = (ctrl->val << MT9V032_TEST_PATTERN_DATA_SHIFT)
+                       data = (mt9v032->test_pattern_color->val <<
+                               MT9V032_TEST_PATTERN_DATA_SHIFT)
                             | MT9V032_TEST_PATTERN_USE_DATA
                             | MT9V032_TEST_PATTERN_ENABLE
                             | MT9V032_TEST_PATTERN_FLIP;
                        break;
                }
-
                return mt9v032_write(client, MT9V032_TEST_PATTERN, data);
        }
 
@@ -522,18 +583,24 @@ static struct v4l2_ctrl_ops mt9v032_ctrl_ops = {
        .s_ctrl = mt9v032_s_ctrl,
 };
 
-static const struct v4l2_ctrl_config mt9v032_ctrls[] = {
-       {
-               .ops            = &mt9v032_ctrl_ops,
-               .id             = V4L2_CID_TEST_PATTERN,
-               .type           = V4L2_CTRL_TYPE_INTEGER,
-               .name           = "Test pattern",
-               .min            = 0,
-               .max            = 1023,
-               .step           = 1,
-               .def            = 0,
-               .flags          = 0,
-       }
+static const char * const mt9v032_test_pattern_menu[] = {
+       "Disabled",
+       "Gray Vertical Shade",
+       "Gray Horizontal Shade",
+       "Gray Diagonal Shade",
+       "Plain",
+};
+
+static const struct v4l2_ctrl_config mt9v032_test_pattern_color = {
+       .ops            = &mt9v032_ctrl_ops,
+       .id             = V4L2_CID_TEST_PATTERN_COLOR,
+       .type           = V4L2_CTRL_TYPE_INTEGER,
+       .name           = "Test Pattern Color",
+       .min            = 0,
+       .max            = 1023,
+       .step           = 1,
+       .def            = 0,
+       .flags          = 0,
 };
 
 /* -----------------------------------------------------------------------------
@@ -598,6 +665,8 @@ static int mt9v032_registered(struct v4l2_subdev *subdev)
        dev_info(&client->dev, "MT9V032 detected at address 0x%02x\n",
                        client->addr);
 
+       mt9v032_configure_pixel_rate(mt9v032, 1);
+
        return ret;
 }
 
@@ -663,6 +732,7 @@ static const struct v4l2_subdev_internal_ops mt9v032_subdev_internal_ops = {
 static int mt9v032_probe(struct i2c_client *client,
                const struct i2c_device_id *did)
 {
+       struct mt9v032_platform_data *pdata = client->dev.platform_data;
        struct mt9v032 *mt9v032;
        unsigned int i;
        int ret;
@@ -679,9 +749,9 @@ static int mt9v032_probe(struct i2c_client *client,
                return -ENOMEM;
 
        mutex_init(&mt9v032->power_lock);
-       mt9v032->pdata = client->dev.platform_data;
+       mt9v032->pdata = pdata;
 
-       v4l2_ctrl_handler_init(&mt9v032->ctrls, ARRAY_SIZE(mt9v032_ctrls) + 4);
+       v4l2_ctrl_handler_init(&mt9v032->ctrls, 10);
 
        v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
                          V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -695,9 +765,43 @@ static int mt9v032_probe(struct i2c_client *client,
                          V4L2_CID_EXPOSURE, MT9V032_TOTAL_SHUTTER_WIDTH_MIN,
                          MT9V032_TOTAL_SHUTTER_WIDTH_MAX, 1,
                          MT9V032_TOTAL_SHUTTER_WIDTH_DEF);
+       v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+                         V4L2_CID_HBLANK, MT9V032_HORIZONTAL_BLANKING_MIN,
+                         MT9V032_HORIZONTAL_BLANKING_MAX, 1,
+                         MT9V032_HORIZONTAL_BLANKING_DEF);
+       v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+                         V4L2_CID_VBLANK, MT9V032_VERTICAL_BLANKING_MIN,
+                         MT9V032_VERTICAL_BLANKING_MAX, 1,
+                         MT9V032_VERTICAL_BLANKING_DEF);
+       mt9v032->test_pattern = v4l2_ctrl_new_std_menu_items(&mt9v032->ctrls,
+                               &mt9v032_ctrl_ops, V4L2_CID_TEST_PATTERN,
+                               ARRAY_SIZE(mt9v032_test_pattern_menu) - 1, 0, 0,
+                               mt9v032_test_pattern_menu);
+       mt9v032->test_pattern_color = v4l2_ctrl_new_custom(&mt9v032->ctrls,
+                                     &mt9v032_test_pattern_color, NULL);
+
+       v4l2_ctrl_cluster(2, &mt9v032->test_pattern);
+
+       mt9v032->pixel_rate =
+               v4l2_ctrl_new_std(&mt9v032->ctrls, &mt9v032_ctrl_ops,
+                                 V4L2_CID_PIXEL_RATE, 0, 0, 1, 0);
+
+       if (pdata && pdata->link_freqs) {
+               unsigned int def = 0;
+
+               for (i = 0; pdata->link_freqs[i]; ++i) {
+                       if (pdata->link_freqs[i] == pdata->link_def_freq)
+                               def = i;
+               }
+
+               mt9v032->link_freq =
+                       v4l2_ctrl_new_int_menu(&mt9v032->ctrls,
+                                              &mt9v032_ctrl_ops,
+                                              V4L2_CID_LINK_FREQ, i - 1, def,
+                                              pdata->link_freqs);
+               v4l2_ctrl_cluster(2, &mt9v032->link_freq);
+       }
 
-       for (i = 0; i < ARRAY_SIZE(mt9v032_ctrls); ++i)
-               v4l2_ctrl_new_custom(&mt9v032->ctrls, &mt9v032_ctrls[i], NULL);
 
        mt9v032->subdev.ctrl_handler = &mt9v032->ctrls;
 
@@ -717,6 +821,8 @@ static int mt9v032_probe(struct i2c_client *client,
        mt9v032->format.colorspace = V4L2_COLORSPACE_SRGB;
 
        mt9v032->aec_agc = MT9V032_AEC_ENABLE | MT9V032_AGC_ENABLE;
+       mt9v032->hblank = MT9V032_HORIZONTAL_BLANKING_DEF;
+       mt9v032->sysclk = MT9V032_SYSCLK_FREQ_DEF;
 
        v4l2_i2c_subdev_init(&mt9v032->subdev, client, &mt9v032_subdev_ops);
        mt9v032->subdev.internal_ops = &mt9v032_subdev_internal_ops;
diff --git a/drivers/media/i2c/s5k4ecgx.c b/drivers/media/i2c/s5k4ecgx.c
new file mode 100644 (file)
index 0000000..49c1b3a
--- /dev/null
@@ -0,0 +1,1036 @@
+/*
+ * Driver for Samsung S5K4ECGX 1/4" 5Mp CMOS Image Sensor SoC
+ * with an Embedded Image Signal Processor.
+ *
+ * Copyright (C) 2012, Linaro, Sangwook Lee <sangwook.lee@linaro.org>
+ * Copyright (C) 2012, Insignal Co,. Ltd, Homin Lee <suapapa@insignal.co.kr>
+ *
+ * Based on s5k6aa and noon010pc30 driver
+ * Copyright (C) 2011, Samsung Electronics Co., 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 <linux/clk.h>
+#include <linux/crc32.h>
+#include <linux/ctype.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/gpio.h>
+#include <linux/i2c.h>
+#include <linux/module.h>
+#include <linux/regulator/consumer.h>
+#include <linux/slab.h>
+#include <asm/unaligned.h>
+
+#include <media/media-entity.h>
+#include <media/s5k4ecgx.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mediabus.h>
+#include <media/v4l2-subdev.h>
+
+static int debug;
+module_param(debug, int, 0644);
+
+#define S5K4ECGX_DRIVER_NAME           "s5k4ecgx"
+#define S5K4ECGX_FIRMWARE              "s5k4ecgx.bin"
+
+/* Firmware revision information */
+#define REG_FW_REVISION                        0x700001a6
+#define REG_FW_VERSION                 0x700001a4
+#define S5K4ECGX_REVISION_1_1          0x11
+#define S5K4ECGX_FW_VERSION            0x4ec0
+
+/* General purpose parameters */
+#define REG_USER_BRIGHTNESS            0x7000022c
+#define REG_USER_CONTRAST              0x7000022e
+#define REG_USER_SATURATION            0x70000230
+
+#define REG_G_ENABLE_PREV              0x7000023e
+#define REG_G_ENABLE_PREV_CHG          0x70000240
+#define REG_G_NEW_CFG_SYNC             0x7000024a
+#define REG_G_PREV_IN_WIDTH            0x70000250
+#define REG_G_PREV_IN_HEIGHT           0x70000252
+#define REG_G_PREV_IN_XOFFS            0x70000254
+#define REG_G_PREV_IN_YOFFS            0x70000256
+#define REG_G_CAP_IN_WIDTH             0x70000258
+#define REG_G_CAP_IN_HEIGHT            0x7000025a
+#define REG_G_CAP_IN_XOFFS             0x7000025c
+#define REG_G_CAP_IN_YOFFS             0x7000025e
+#define REG_G_INPUTS_CHANGE_REQ                0x70000262
+#define REG_G_ACTIVE_PREV_CFG          0x70000266
+#define REG_G_PREV_CFG_CHG             0x70000268
+#define REG_G_PREV_OPEN_AFTER_CH       0x7000026a
+
+/* Preview context register sets. n = 0...4. */
+#define PREG(n, x)                     ((n) * 0x30 + (x))
+#define REG_P_OUT_WIDTH(n)             PREG(n, 0x700002a6)
+#define REG_P_OUT_HEIGHT(n)            PREG(n, 0x700002a8)
+#define REG_P_FMT(n)                   PREG(n, 0x700002aa)
+#define REG_P_PVI_MASK(n)              PREG(n, 0x700002b4)
+#define REG_P_FR_TIME_TYPE(n)          PREG(n, 0x700002be)
+#define  FR_TIME_DYNAMIC               0
+#define  FR_TIME_FIXED                 1
+#define  FR_TIME_FIXED_ACCURATE                2
+#define REG_P_FR_TIME_Q_TYPE(n)                PREG(n, 0x700002c0)
+#define  FR_TIME_Q_DYNAMIC             0
+#define  FR_TIME_Q_BEST_FRRATE         1
+#define  FR_TIME_Q_BEST_QUALITY                2
+
+/* Frame period in 0.1 ms units */
+#define REG_P_MAX_FR_TIME(n)           PREG(n, 0x700002c2)
+#define REG_P_MIN_FR_TIME(n)           PREG(n, 0x700002c4)
+#define  US_TO_FR_TIME(__t)            ((__t) / 100)
+#define REG_P_PREV_MIRROR(n)           PREG(n, 0x700002d0)
+#define REG_P_CAP_MIRROR(n)            PREG(n, 0x700002d2)
+
+#define REG_G_PREVZOOM_IN_WIDTH                0x70000494
+#define REG_G_PREVZOOM_IN_HEIGHT       0x70000496
+#define REG_G_PREVZOOM_IN_XOFFS                0x70000498
+#define REG_G_PREVZOOM_IN_YOFFS                0x7000049a
+#define REG_G_CAPZOOM_IN_WIDTH         0x7000049c
+#define REG_G_CAPZOOM_IN_HEIGHT                0x7000049e
+#define REG_G_CAPZOOM_IN_XOFFS         0x700004a0
+#define REG_G_CAPZOOM_IN_YOFFS         0x700004a2
+
+/* n = 0...4 */
+#define REG_USER_SHARPNESS(n)          (0x70000a28 + (n) * 0xb6)
+
+/* Reduce sharpness range for user space API */
+#define SHARPNESS_DIV                  8208
+#define TOK_TERM                       0xffffffff
+
+/*
+ * FIXME: This is copied from s5k6aa, because of no information
+ * in the S5K4ECGX datasheet.
+ * H/W register Interface (0xd0000000 - 0xd0000fff)
+ */
+#define AHB_MSB_ADDR_PTR               0xfcfc
+#define GEN_REG_OFFSH                  0xd000
+#define REG_CMDWR_ADDRH                        0x0028
+#define REG_CMDWR_ADDRL                        0x002a
+#define REG_CMDRD_ADDRH                        0x002c
+#define REG_CMDRD_ADDRL                        0x002e
+#define REG_CMDBUF0_ADDR               0x0f12
+
+struct s5k4ecgx_frmsize {
+       struct v4l2_frmsize_discrete size;
+       /* Fixed sensor matrix crop rectangle */
+       struct v4l2_rect input_window;
+};
+
+struct regval_list {
+       u32 addr;
+       u16 val;
+};
+
+/*
+ * TODO: currently only preview is supported and snapshot (capture)
+ * is not implemented yet
+ */
+static const struct s5k4ecgx_frmsize s5k4ecgx_prev_sizes[] = {
+       {
+               .size = { 176, 144 },
+               .input_window = { 0x00, 0x00, 0x928, 0x780 },
+       }, {
+               .size = { 352, 288 },
+               .input_window = { 0x00, 0x00, 0x928, 0x780 },
+       }, {
+               .size = { 640, 480 },
+               .input_window = { 0x00, 0x00, 0xa00, 0x780 },
+       }, {
+               .size = { 720, 480 },
+               .input_window = { 0x00, 0x00, 0xa00, 0x6a8 },
+       }
+};
+
+#define S5K4ECGX_NUM_PREV ARRAY_SIZE(s5k4ecgx_prev_sizes)
+
+struct s5k4ecgx_pixfmt {
+       enum v4l2_mbus_pixelcode code;
+       u32 colorspace;
+       /* REG_TC_PCFG_Format register value */
+       u16 reg_p_format;
+};
+
+/* By default value, output from sensor will be YUV422 0-255 */
+static const struct s5k4ecgx_pixfmt s5k4ecgx_formats[] = {
+       { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_COLORSPACE_JPEG, 5 },
+};
+
+static const char * const s5k4ecgx_supply_names[] = {
+       /*
+        * Usually 2.8V is used for analog power (vdda)
+        * and digital IO (vddio, vdddcore)
+        */
+       "vdda",
+       "vddio",
+       "vddcore",
+       "vddreg", /* The internal s5k4ecgx regulator's supply (1.8V) */
+};
+
+#define S5K4ECGX_NUM_SUPPLIES ARRAY_SIZE(s5k4ecgx_supply_names)
+
+enum s5k4ecgx_gpio_id {
+       STBY,
+       RST,
+       GPIO_NUM,
+};
+
+struct s5k4ecgx {
+       struct v4l2_subdev sd;
+       struct media_pad pad;
+       struct v4l2_ctrl_handler handler;
+
+       struct s5k4ecgx_platform_data *pdata;
+       const struct s5k4ecgx_pixfmt *curr_pixfmt;
+       const struct s5k4ecgx_frmsize *curr_frmsize;
+       struct mutex lock;
+       u8 streaming;
+       u8 set_params;
+
+       struct regulator_bulk_data supplies[S5K4ECGX_NUM_SUPPLIES];
+       struct s5k4ecgx_gpio gpio[GPIO_NUM];
+};
+
+static inline struct s5k4ecgx *to_s5k4ecgx(struct v4l2_subdev *sd)
+{
+       return container_of(sd, struct s5k4ecgx, sd);
+}
+
+static int s5k4ecgx_i2c_read(struct i2c_client *client, u16 addr, u16 *val)
+{
+       u8 wbuf[2] = { addr >> 8, addr & 0xff };
+       struct i2c_msg msg[2];
+       u8 rbuf[2];
+       int ret;
+
+       msg[0].addr = client->addr;
+       msg[0].flags = 0;
+       msg[0].len = 2;
+       msg[0].buf = wbuf;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].len = 2;
+       msg[1].buf = rbuf;
+
+       ret = i2c_transfer(client->adapter, msg, 2);
+       *val = be16_to_cpu(*((u16 *)rbuf));
+
+       v4l2_dbg(4, debug, client, "i2c_read: 0x%04X : 0x%04x\n", addr, *val);
+
+       return ret == 2 ? 0 : ret;
+}
+
+static int s5k4ecgx_i2c_write(struct i2c_client *client, u16 addr, u16 val)
+{
+       u8 buf[4] = { addr >> 8, addr & 0xff, val >> 8, val & 0xff };
+
+       int ret = i2c_master_send(client, buf, 4);
+       v4l2_dbg(4, debug, client, "i2c_write: 0x%04x : 0x%04x\n", addr, val);
+
+       return ret == 4 ? 0 : ret;
+}
+
+static int s5k4ecgx_write(struct i2c_client *client, u32 addr, u16 val)
+{
+       u16 high = addr >> 16, low = addr & 0xffff;
+       int ret;
+
+       v4l2_dbg(3, debug, client, "write: 0x%08x : 0x%04x\n", addr, val);
+
+       ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRH, high);
+       if (!ret)
+               ret = s5k4ecgx_i2c_write(client, REG_CMDWR_ADDRL, low);
+       if (!ret)
+               ret = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val);
+
+       return ret;
+}
+
+static int s5k4ecgx_read(struct i2c_client *client, u32 addr, u16 *val)
+{
+       u16 high = addr >> 16, low =  addr & 0xffff;
+       int ret;
+
+       ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRH, high);
+       if (!ret)
+               ret = s5k4ecgx_i2c_write(client, REG_CMDRD_ADDRL, low);
+       if (!ret)
+               ret = s5k4ecgx_i2c_read(client, REG_CMDBUF0_ADDR, val);
+       if (!ret)
+               dev_err(&client->dev, "Failed to execute read command\n");
+
+       return ret;
+}
+
+static int s5k4ecgx_read_fw_ver(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       u16 hw_rev, fw_ver = 0;
+       int ret;
+
+       ret = s5k4ecgx_read(client, REG_FW_VERSION, &fw_ver);
+       if (ret < 0 || fw_ver != S5K4ECGX_FW_VERSION) {
+               v4l2_err(sd, "FW version check failed!\n");
+               return -ENODEV;
+       }
+
+       ret = s5k4ecgx_read(client, REG_FW_REVISION, &hw_rev);
+       if (ret < 0)
+               return ret;
+
+       v4l2_info(sd, "chip found FW ver: 0x%x, HW rev: 0x%x\n",
+                                               fw_ver, hw_rev);
+       return 0;
+}
+
+static int s5k4ecgx_set_ahb_address(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       int ret;
+
+       /* Set APB peripherals start address */
+       ret = s5k4ecgx_i2c_write(client, AHB_MSB_ADDR_PTR, GEN_REG_OFFSH);
+       if (ret < 0)
+               return ret;
+       /*
+        * FIXME: This is copied from s5k6aa, because of no information
+        * in s5k4ecgx's datasheet.
+        * sw_reset is activated to put device into idle status
+        */
+       ret = s5k4ecgx_i2c_write(client, 0x0010, 0x0001);
+       if (ret < 0)
+               return ret;
+
+       ret = s5k4ecgx_i2c_write(client, 0x1030, 0x0000);
+       if (ret < 0)
+               return ret;
+       /* Halt ARM CPU */
+       return s5k4ecgx_i2c_write(client, 0x0014, 0x0001);
+}
+
+#define FW_CRC_SIZE    4
+/* Register address, value are 4, 2 bytes */
+#define FW_RECORD_SIZE 6
+/*
+ * The firmware has following format:
+ * < total number of records (4 bytes + 2 bytes padding) N >,
+ * < record 0 >, ..., < record N - 1 >, < CRC32-CCITT (4-bytes) >,
+ * where "record" is a 4-byte register address followed by 2-byte
+ * register value (little endian).
+ * The firmware generator can be found in following git repository:
+ * git://git.linaro.org/people/sangwook/fimc-v4l2-app.git
+ */
+static int s5k4ecgx_load_firmware(struct v4l2_subdev *sd)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       const struct firmware *fw;
+       const u8 *ptr;
+       int err, i, regs_num;
+       u32 addr, crc, crc_file, addr_inc = 0;
+       u16 val;
+
+       err = request_firmware(&fw, S5K4ECGX_FIRMWARE, sd->v4l2_dev->dev);
+       if (err) {
+               v4l2_err(sd, "Failed to read firmware %s\n", S5K4ECGX_FIRMWARE);
+               return err;
+       }
+       regs_num = le32_to_cpu(get_unaligned_le32(fw->data));
+
+       v4l2_dbg(3, debug, sd, "FW: %s size %d register sets %d\n",
+                S5K4ECGX_FIRMWARE, fw->size, regs_num);
+
+       regs_num++; /* Add header */
+       if (fw->size != regs_num * FW_RECORD_SIZE + FW_CRC_SIZE) {
+               err = -EINVAL;
+               goto fw_out;
+       }
+       crc_file = le32_to_cpu(get_unaligned_le32(fw->data +
+                                                 regs_num * FW_RECORD_SIZE));
+       crc = crc32_le(~0, fw->data, regs_num * FW_RECORD_SIZE);
+       if (crc != crc_file) {
+               v4l2_err(sd, "FW: invalid crc (%#x:%#x)\n", crc, crc_file);
+               err = -EINVAL;
+               goto fw_out;
+       }
+       ptr = fw->data + FW_RECORD_SIZE;
+       for (i = 1; i < regs_num; i++) {
+               addr = le32_to_cpu(get_unaligned_le32(ptr));
+               ptr += sizeof(u32);
+               val = le16_to_cpu(get_unaligned_le16(ptr));
+               ptr += sizeof(u16);
+               if (addr - addr_inc != 2)
+                       err = s5k4ecgx_write(client, addr, val);
+               else
+                       err = s5k4ecgx_i2c_write(client, REG_CMDBUF0_ADDR, val);
+               if (err)
+                       break;
+               addr_inc = addr;
+       }
+fw_out:
+       release_firmware(fw);
+       return err;
+}
+
+/* Set preview and capture input window */
+static int s5k4ecgx_set_input_window(struct i2c_client *c,
+                                    const struct v4l2_rect *r)
+{
+       int ret;
+
+       ret = s5k4ecgx_write(c, REG_G_PREV_IN_WIDTH, r->width);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREV_IN_HEIGHT, r->height);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREV_IN_XOFFS, r->left);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREV_IN_YOFFS, r->top);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAP_IN_WIDTH, r->width);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAP_IN_HEIGHT, r->height);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAP_IN_XOFFS, r->left);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAP_IN_YOFFS, r->top);
+
+       return ret;
+}
+
+/* Set preview and capture zoom input window */
+static int s5k4ecgx_set_zoom_window(struct i2c_client *c,
+                                   const struct v4l2_rect *r)
+{
+       int ret;
+
+       ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_WIDTH, r->width);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_HEIGHT, r->height);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_XOFFS, r->left);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_PREVZOOM_IN_YOFFS, r->top);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_WIDTH, r->width);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_HEIGHT, r->height);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_XOFFS, r->left);
+       if (!ret)
+               ret = s5k4ecgx_write(c, REG_G_CAPZOOM_IN_YOFFS, r->top);
+
+       return ret;
+}
+
+static int s5k4ecgx_set_output_framefmt(struct s5k4ecgx *priv)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
+       int ret;
+
+       ret = s5k4ecgx_write(client, REG_P_OUT_WIDTH(0),
+                            priv->curr_frmsize->size.width);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_OUT_HEIGHT(0),
+                                    priv->curr_frmsize->size.height);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_FMT(0),
+                                    priv->curr_pixfmt->reg_p_format);
+       return ret;
+}
+
+static int s5k4ecgx_init_sensor(struct v4l2_subdev *sd)
+{
+       int ret;
+
+       ret = s5k4ecgx_set_ahb_address(sd);
+
+       /* The delay is from manufacturer's settings */
+       msleep(100);
+
+       if (!ret)
+               ret = s5k4ecgx_load_firmware(sd);
+       if (ret)
+               v4l2_err(sd, "Failed to write initial settings\n");
+
+       return ret;
+}
+
+static int s5k4ecgx_gpio_set_value(struct s5k4ecgx *priv, int id, u32 val)
+{
+       if (!gpio_is_valid(priv->gpio[id].gpio))
+               return 0;
+       gpio_set_value(priv->gpio[id].gpio, val);
+
+       return 1;
+}
+
+static int __s5k4ecgx_power_on(struct s5k4ecgx *priv)
+{
+       int ret;
+
+       ret = regulator_bulk_enable(S5K4ECGX_NUM_SUPPLIES, priv->supplies);
+       if (ret)
+               return ret;
+       usleep_range(30, 50);
+
+       /* The polarity of STBY is controlled by TSP */
+       if (s5k4ecgx_gpio_set_value(priv, STBY, priv->gpio[STBY].level))
+               usleep_range(30, 50);
+
+       if (s5k4ecgx_gpio_set_value(priv, RST, priv->gpio[RST].level))
+               usleep_range(30, 50);
+
+       return 0;
+}
+
+static int __s5k4ecgx_power_off(struct s5k4ecgx *priv)
+{
+       if (s5k4ecgx_gpio_set_value(priv, RST, !priv->gpio[RST].level))
+               usleep_range(30, 50);
+
+       if (s5k4ecgx_gpio_set_value(priv, STBY, !priv->gpio[STBY].level))
+               usleep_range(30, 50);
+
+       priv->streaming = 0;
+
+       return regulator_bulk_disable(S5K4ECGX_NUM_SUPPLIES, priv->supplies);
+}
+
+/* Find nearest matching image pixel size. */
+static int s5k4ecgx_try_frame_size(struct v4l2_mbus_framefmt *mf,
+                                 const struct s5k4ecgx_frmsize **size)
+{
+       unsigned int min_err = ~0;
+       int i = ARRAY_SIZE(s5k4ecgx_prev_sizes);
+       const struct s5k4ecgx_frmsize *fsize = &s5k4ecgx_prev_sizes[0],
+               *match = NULL;
+
+       while (i--) {
+               int err = abs(fsize->size.width - mf->width)
+                               + abs(fsize->size.height - mf->height);
+               if (err < min_err) {
+                       min_err = err;
+                       match = fsize;
+               }
+               fsize++;
+       }
+       if (match) {
+               mf->width  = match->size.width;
+               mf->height = match->size.height;
+               if (size)
+                       *size = match;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int s5k4ecgx_enum_mbus_code(struct v4l2_subdev *sd,
+                                  struct v4l2_subdev_fh *fh,
+                                  struct v4l2_subdev_mbus_code_enum *code)
+{
+       if (code->index >= ARRAY_SIZE(s5k4ecgx_formats))
+               return -EINVAL;
+       code->code = s5k4ecgx_formats[code->index].code;
+
+       return 0;
+}
+
+static int s5k4ecgx_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                          struct v4l2_subdev_format *fmt)
+{
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+       struct v4l2_mbus_framefmt *mf;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               if (fh) {
+                       mf = v4l2_subdev_get_try_format(fh, 0);
+                       fmt->format = *mf;
+               }
+               return 0;
+       }
+
+       mf = &fmt->format;
+
+       mutex_lock(&priv->lock);
+       mf->width = priv->curr_frmsize->size.width;
+       mf->height = priv->curr_frmsize->size.height;
+       mf->code = priv->curr_pixfmt->code;
+       mf->colorspace = priv->curr_pixfmt->colorspace;
+       mf->field = V4L2_FIELD_NONE;
+       mutex_unlock(&priv->lock);
+
+       return 0;
+}
+
+static const struct s5k4ecgx_pixfmt *s5k4ecgx_try_fmt(struct v4l2_subdev *sd,
+                                           struct v4l2_mbus_framefmt *mf)
+{
+       int i = ARRAY_SIZE(s5k4ecgx_formats);
+
+       while (--i)
+               if (mf->code == s5k4ecgx_formats[i].code)
+                       break;
+       mf->code = s5k4ecgx_formats[i].code;
+
+       return &s5k4ecgx_formats[i];
+}
+
+static int s5k4ecgx_set_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
+                           struct v4l2_subdev_format *fmt)
+{
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+       const struct s5k4ecgx_frmsize *fsize = NULL;
+       const struct s5k4ecgx_pixfmt *pf;
+       struct v4l2_mbus_framefmt *mf;
+       int ret = 0;
+
+       pf = s5k4ecgx_try_fmt(sd, &fmt->format);
+       s5k4ecgx_try_frame_size(&fmt->format, &fsize);
+       fmt->format.colorspace = V4L2_COLORSPACE_JPEG;
+
+       if (fmt->which == V4L2_SUBDEV_FORMAT_TRY) {
+               if (fh) {
+                       mf = v4l2_subdev_get_try_format(fh, 0);
+                       *mf = fmt->format;
+               }
+               return 0;
+       }
+
+       mutex_lock(&priv->lock);
+       if (!priv->streaming) {
+               priv->curr_frmsize = fsize;
+               priv->curr_pixfmt = pf;
+               priv->set_params = 1;
+       } else {
+               ret = -EBUSY;
+       }
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+static const struct v4l2_subdev_pad_ops s5k4ecgx_pad_ops = {
+       .enum_mbus_code = s5k4ecgx_enum_mbus_code,
+       .get_fmt        = s5k4ecgx_get_fmt,
+       .set_fmt        = s5k4ecgx_set_fmt,
+};
+
+/*
+ * V4L2 subdev controls
+ */
+static int s5k4ecgx_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct v4l2_subdev *sd = &container_of(ctrl->handler, struct s5k4ecgx,
+                                               handler)->sd;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+       unsigned int i;
+       int err = 0;
+
+       v4l2_dbg(1, debug, sd, "ctrl: 0x%x, value: %d\n", ctrl->id, ctrl->val);
+
+       mutex_lock(&priv->lock);
+       switch (ctrl->id) {
+       case V4L2_CID_CONTRAST:
+               err = s5k4ecgx_write(client, REG_USER_CONTRAST, ctrl->val);
+               break;
+
+       case V4L2_CID_SATURATION:
+               err = s5k4ecgx_write(client, REG_USER_SATURATION, ctrl->val);
+               break;
+
+       case V4L2_CID_SHARPNESS:
+               /* TODO: Revisit, is this setting for all presets ? */
+               for (i = 0; i < 4 && !err; i++)
+                       err = s5k4ecgx_write(client, REG_USER_SHARPNESS(i),
+                                            ctrl->val * SHARPNESS_DIV);
+               break;
+
+       case V4L2_CID_BRIGHTNESS:
+               err = s5k4ecgx_write(client, REG_USER_BRIGHTNESS, ctrl->val);
+               break;
+       }
+       mutex_unlock(&priv->lock);
+       if (err < 0)
+               v4l2_err(sd, "Failed to write s_ctrl err %d\n", err);
+
+       return err;
+}
+
+static const struct v4l2_ctrl_ops s5k4ecgx_ctrl_ops = {
+       .s_ctrl = s5k4ecgx_s_ctrl,
+};
+
+/*
+ * Reading s5k4ecgx version information
+ */
+static int s5k4ecgx_registered(struct v4l2_subdev *sd)
+{
+       int ret;
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+
+       mutex_lock(&priv->lock);
+       ret = __s5k4ecgx_power_on(priv);
+       if (!ret) {
+               ret = s5k4ecgx_read_fw_ver(sd);
+               __s5k4ecgx_power_off(priv);
+       }
+       mutex_unlock(&priv->lock);
+
+       return ret;
+}
+
+/*
+ * V4L2 subdev internal operations
+ */
+static int s5k4ecgx_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
+{
+       struct v4l2_mbus_framefmt *mf = v4l2_subdev_get_try_format(fh, 0);
+
+       mf->width = s5k4ecgx_prev_sizes[0].size.width;
+       mf->height = s5k4ecgx_prev_sizes[0].size.height;
+       mf->code = s5k4ecgx_formats[0].code;
+       mf->colorspace = V4L2_COLORSPACE_JPEG;
+       mf->field = V4L2_FIELD_NONE;
+
+       return 0;
+}
+
+static const struct v4l2_subdev_internal_ops s5k4ecgx_subdev_internal_ops = {
+       .registered = s5k4ecgx_registered,
+       .open = s5k4ecgx_open,
+};
+
+static int s5k4ecgx_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+       int ret;
+
+       v4l2_dbg(1, debug, sd, "Switching %s\n", on ? "on" : "off");
+
+       if (on) {
+               ret = __s5k4ecgx_power_on(priv);
+               if (ret < 0)
+                       return ret;
+               /* Time to stabilize sensor */
+               msleep(100);
+               ret = s5k4ecgx_init_sensor(sd);
+               if (ret < 0)
+                       __s5k4ecgx_power_off(priv);
+               else
+                       priv->set_params = 1;
+       } else {
+               ret = __s5k4ecgx_power_off(priv);
+       }
+
+       return ret;
+}
+
+static int s5k4ecgx_log_status(struct v4l2_subdev *sd)
+{
+       v4l2_ctrl_handler_log_status(sd->ctrl_handler, sd->name);
+
+       return 0;
+}
+
+static const struct v4l2_subdev_core_ops s5k4ecgx_core_ops = {
+       .s_power        = s5k4ecgx_s_power,
+       .log_status     = s5k4ecgx_log_status,
+};
+
+static int __s5k4ecgx_s_params(struct s5k4ecgx *priv)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
+       const struct v4l2_rect *crop_rect = &priv->curr_frmsize->input_window;
+       int ret;
+
+       ret = s5k4ecgx_set_input_window(client, crop_rect);
+       if (!ret)
+               ret = s5k4ecgx_set_zoom_window(client, crop_rect);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_G_INPUTS_CHANGE_REQ, 1);
+       if (!ret)
+               ret = s5k4ecgx_write(client, 0x70000a1e, 0x28);
+       if (!ret)
+               ret = s5k4ecgx_write(client, 0x70000ad4, 0x3c);
+       if (!ret)
+               ret = s5k4ecgx_set_output_framefmt(priv);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_PVI_MASK(0), 0x52);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_FR_TIME_TYPE(0),
+                                    FR_TIME_DYNAMIC);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_FR_TIME_Q_TYPE(0),
+                                    FR_TIME_Q_BEST_FRRATE);
+       if (!ret)
+               ret = s5k4ecgx_write(client,  REG_P_MIN_FR_TIME(0),
+                                    US_TO_FR_TIME(33300));
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_MAX_FR_TIME(0),
+                                    US_TO_FR_TIME(66600));
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_PREV_MIRROR(0), 0);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_P_CAP_MIRROR(0), 0);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_G_ACTIVE_PREV_CFG, 0);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_G_PREV_OPEN_AFTER_CH, 1);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_G_NEW_CFG_SYNC, 1);
+       if (!ret)
+               ret = s5k4ecgx_write(client, REG_G_PREV_CFG_CHG, 1);
+
+       return ret;
+}
+
+static int __s5k4ecgx_s_stream(struct s5k4ecgx *priv, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->sd);
+       int ret;
+
+       if (on && priv->set_params) {
+               ret = __s5k4ecgx_s_params(priv);
+               if (ret < 0)
+                       return ret;
+               priv->set_params = 0;
+       }
+       /*
+        * This enables/disables preview stream only. Capture requests
+        * are not supported yet.
+        */
+       ret = s5k4ecgx_write(client, REG_G_ENABLE_PREV, on);
+       if (ret < 0)
+               return ret;
+       return s5k4ecgx_write(client, REG_G_ENABLE_PREV_CHG, 1);
+}
+
+static int s5k4ecgx_s_stream(struct v4l2_subdev *sd, int on)
+{
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+       int ret = 0;
+
+       v4l2_dbg(1, debug, sd, "Turn streaming %s\n", on ? "on" : "off");
+
+       mutex_lock(&priv->lock);
+
+       if (priv->streaming == !on) {
+               ret = __s5k4ecgx_s_stream(priv, on);
+               if (!ret)
+                       priv->streaming = on & 1;
+       }
+
+       mutex_unlock(&priv->lock);
+       return ret;
+}
+
+static const struct v4l2_subdev_video_ops s5k4ecgx_video_ops = {
+       .s_stream = s5k4ecgx_s_stream,
+};
+
+static const struct v4l2_subdev_ops s5k4ecgx_ops = {
+       .core = &s5k4ecgx_core_ops,
+       .pad = &s5k4ecgx_pad_ops,
+       .video = &s5k4ecgx_video_ops,
+};
+
+/*
+ * GPIO setup
+ */
+static int s5k4ecgx_config_gpio(int nr, int val, const char *name)
+{
+       unsigned long flags = val ? GPIOF_OUT_INIT_HIGH : GPIOF_OUT_INIT_LOW;
+       int ret;
+
+       if (!gpio_is_valid(nr))
+               return 0;
+       ret = gpio_request_one(nr, flags, name);
+       if (!ret)
+               gpio_export(nr, 0);
+
+       return ret;
+}
+
+static void s5k4ecgx_free_gpios(struct s5k4ecgx *priv)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(priv->gpio); i++) {
+               if (!gpio_is_valid(priv->gpio[i].gpio))
+                       continue;
+               gpio_free(priv->gpio[i].gpio);
+               priv->gpio[i].gpio = -EINVAL;
+       }
+}
+
+static int s5k4ecgx_config_gpios(struct s5k4ecgx *priv,
+                                 const struct s5k4ecgx_platform_data *pdata)
+{
+       const struct s5k4ecgx_gpio *gpio = &pdata->gpio_stby;
+       int ret;
+
+       priv->gpio[STBY].gpio = -EINVAL;
+       priv->gpio[RST].gpio  = -EINVAL;
+
+       ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_STBY");
+
+       if (ret) {
+               s5k4ecgx_free_gpios(priv);
+               return ret;
+       }
+       priv->gpio[STBY] = *gpio;
+       if (gpio_is_valid(gpio->gpio))
+               gpio_set_value(gpio->gpio, 0);
+
+       gpio = &pdata->gpio_reset;
+
+       ret = s5k4ecgx_config_gpio(gpio->gpio, gpio->level, "S5K4ECGX_RST");
+       if (ret) {
+               s5k4ecgx_free_gpios(priv);
+               return ret;
+       }
+       priv->gpio[RST] = *gpio;
+       if (gpio_is_valid(gpio->gpio))
+               gpio_set_value(gpio->gpio, 0);
+
+       return 0;
+}
+
+static int s5k4ecgx_init_v4l2_ctrls(struct s5k4ecgx *priv)
+{
+       const struct v4l2_ctrl_ops *ops = &s5k4ecgx_ctrl_ops;
+       struct v4l2_ctrl_handler *hdl = &priv->handler;
+       int ret;
+
+       ret = v4l2_ctrl_handler_init(hdl, 4);
+       if (ret)
+               return ret;
+
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_BRIGHTNESS, -208, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_CONTRAST, -127, 127, 1, 0);
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SATURATION, -127, 127, 1, 0);
+
+       /* Sharpness default is 24612, and then (24612/SHARPNESS_DIV) = 2 */
+       v4l2_ctrl_new_std(hdl, ops, V4L2_CID_SHARPNESS, -32704/SHARPNESS_DIV,
+                         24612/SHARPNESS_DIV, 1, 2);
+       if (hdl->error) {
+               ret = hdl->error;
+               v4l2_ctrl_handler_free(hdl);
+               return ret;
+       }
+       priv->sd.ctrl_handler = hdl;
+
+       return 0;
+};
+
+static int s5k4ecgx_probe(struct i2c_client *client,
+                         const struct i2c_device_id *id)
+{
+       struct s5k4ecgx_platform_data *pdata = client->dev.platform_data;
+       struct v4l2_subdev *sd;
+       struct s5k4ecgx *priv;
+       int ret, i;
+
+       if (pdata == NULL) {
+               dev_err(&client->dev, "platform data is missing!\n");
+               return -EINVAL;
+       }
+
+       priv = devm_kzalloc(&client->dev, sizeof(struct s5k4ecgx), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       mutex_init(&priv->lock);
+       priv->streaming = 0;
+
+       sd = &priv->sd;
+       /* Registering subdev */
+       v4l2_i2c_subdev_init(sd, client, &s5k4ecgx_ops);
+       strlcpy(sd->name, S5K4ECGX_DRIVER_NAME, sizeof(sd->name));
+
+       sd->internal_ops = &s5k4ecgx_subdev_internal_ops;
+       /* Support v4l2 sub-device user space API */
+       sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+
+       priv->pad.flags = MEDIA_PAD_FL_SOURCE;
+       sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
+       ret = media_entity_init(&sd->entity, 1, &priv->pad, 0);
+       if (ret)
+               return ret;
+
+       ret = s5k4ecgx_config_gpios(priv, pdata);
+       if (ret) {
+               dev_err(&client->dev, "Failed to set gpios\n");
+               goto out_err1;
+       }
+       for (i = 0; i < S5K4ECGX_NUM_SUPPLIES; i++)
+               priv->supplies[i].supply = s5k4ecgx_supply_names[i];
+
+       ret = devm_regulator_bulk_get(&client->dev, S5K4ECGX_NUM_SUPPLIES,
+                                priv->supplies);
+       if (ret) {
+               dev_err(&client->dev, "Failed to get regulators\n");
+               goto out_err2;
+       }
+       ret = s5k4ecgx_init_v4l2_ctrls(priv);
+       if (ret)
+               goto out_err2;
+
+       priv->curr_pixfmt = &s5k4ecgx_formats[0];
+       priv->curr_frmsize = &s5k4ecgx_prev_sizes[0];
+
+       return 0;
+
+out_err2:
+       s5k4ecgx_free_gpios(priv);
+out_err1:
+       media_entity_cleanup(&priv->sd.entity);
+
+       return ret;
+}
+
+static int s5k4ecgx_remove(struct i2c_client *client)
+{
+       struct v4l2_subdev *sd = i2c_get_clientdata(client);
+       struct s5k4ecgx *priv = to_s5k4ecgx(sd);
+
+       mutex_destroy(&priv->lock);
+       s5k4ecgx_free_gpios(priv);
+       v4l2_device_unregister_subdev(sd);
+       v4l2_ctrl_handler_free(&priv->handler);
+       media_entity_cleanup(&sd->entity);
+
+       return 0;
+}
+
+static const struct i2c_device_id s5k4ecgx_id[] = {
+       { S5K4ECGX_DRIVER_NAME, 0 },
+       {}
+};
+MODULE_DEVICE_TABLE(i2c, s5k4ecgx_id);
+
+static struct i2c_driver v4l2_i2c_driver = {
+       .driver = {
+               .owner  = THIS_MODULE,
+               .name = S5K4ECGX_DRIVER_NAME,
+       },
+       .probe = s5k4ecgx_probe,
+       .remove = s5k4ecgx_remove,
+       .id_table = s5k4ecgx_id,
+};
+
+module_i2c_driver(v4l2_i2c_driver);
+
+MODULE_DESCRIPTION("Samsung S5K4ECGX 5MP SOC camera");
+MODULE_AUTHOR("Sangwook Lee <sangwook.lee@linaro.org>");
+MODULE_AUTHOR("Seok-Young Jang <quartz.jang@samsung.com>");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(S5K4ECGX_FIRMWARE);
similarity index 99%
rename from drivers/media/video/s5k6aa.c
rename to drivers/media/i2c/s5k6aa.c
index 6625e46a4638d5a0e916d3ff91fdbeb6dd8355fc..57cd4fa0193d4e0b554ead5d22be85d415007903 100644 (file)
@@ -1061,10 +1061,9 @@ __s5k6aa_get_crop_rect(struct s5k6aa *s5k6aa, struct v4l2_subdev_fh *fh,
 {
        if (which == V4L2_SUBDEV_FORMAT_ACTIVE)
                return &s5k6aa->ccd_rect;
-       if (which == V4L2_SUBDEV_FORMAT_TRY)
-               return v4l2_subdev_get_try_crop(fh, 0);
 
-       return NULL;
+       WARN_ON(which != V4L2_SUBDEV_FORMAT_TRY);
+       return v4l2_subdev_get_try_crop(fh, 0);
 }
 
 static void s5k6aa_try_format(struct s5k6aa *s5k6aa,
@@ -1169,12 +1168,10 @@ static int s5k6aa_get_crop(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        struct v4l2_rect *rect;
 
        memset(crop->reserved, 0, sizeof(crop->reserved));
-       mutex_lock(&s5k6aa->lock);
 
+       mutex_lock(&s5k6aa->lock);
        rect = __s5k6aa_get_crop_rect(s5k6aa, fh, crop->which);
-       if (rect)
-               crop->rect = *rect;
-
+       crop->rect = *rect;
        mutex_unlock(&s5k6aa->lock);
 
        v4l2_dbg(1, debug, sd, "Current crop rectangle: (%d,%d)/%dx%d\n",
@@ -1436,7 +1433,7 @@ static int s5k6aa_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
        return 0;
 }
 
-int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
+static int s5k6aa_check_fw_revision(struct s5k6aa *s5k6aa)
 {
        struct i2c_client *client = v4l2_get_subdevdata(&s5k6aa->sd);
        u16 api_ver = 0, fw_rev = 0;
@@ -1568,7 +1565,7 @@ static int s5k6aa_probe(struct i2c_client *client,
                return -EINVAL;
        }
 
-       s5k6aa = kzalloc(sizeof(*s5k6aa), GFP_KERNEL);
+       s5k6aa = devm_kzalloc(&client->dev, sizeof(*s5k6aa), GFP_KERNEL);
        if (!s5k6aa)
                return -ENOMEM;
 
@@ -1592,7 +1589,7 @@ static int s5k6aa_probe(struct i2c_client *client,
        sd->entity.type = MEDIA_ENT_T_V4L2_SUBDEV_SENSOR;
        ret = media_entity_init(&sd->entity, 1, &s5k6aa->pad, 0);
        if (ret)
-               goto out_err1;
+               return ret;
 
        ret = s5k6aa_configure_gpios(s5k6aa, pdata);
        if (ret)
@@ -1627,8 +1624,6 @@ out_err3:
        s5k6aa_free_gpios(s5k6aa);
 out_err2:
        media_entity_cleanup(&s5k6aa->sd.entity);
-out_err1:
-       kfree(s5k6aa);
        return ret;
 }
 
@@ -1642,7 +1637,6 @@ static int s5k6aa_remove(struct i2c_client *client)
        media_entity_cleanup(&sd->entity);
        regulator_bulk_free(S5K6AA_NUM_SUPPLIES, s5k6aa->supplies);
        s5k6aa_free_gpios(s5k6aa);
-       kfree(s5k6aa);
 
        return 0;
 }
similarity index 99%
rename from drivers/media/video/saa7115.c
rename to drivers/media/i2c/saa7115.c
index 2107336cd8369cd055e5d43362349fc936d4518e..6b6788cd08f6d6862020d0ab8d6b76e40fbb1402 100644 (file)
@@ -1066,7 +1066,8 @@ static int saa711x_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
        };
        int i;
 
-       memset(sliced, 0, sizeof(*sliced));
+       memset(sliced->service_lines, 0, sizeof(sliced->service_lines));
+       sliced->service_set = 0;
        /* done if using raw VBI */
        if (saa711x_read(sd, R_80_GLOBAL_CNTL_1) & 0x10)
                return 0;
similarity index 99%
rename from drivers/media/video/saa7127.c
rename to drivers/media/i2c/saa7127.c
index 39c90b08eea8c4715b9a0b525a6ed5f8dfda23ca..b745f68fbc92d9c1c142a5a712f61180c928dd28 100644 (file)
@@ -364,10 +364,7 @@ static int saa7127_set_vps(struct v4l2_subdev *sd, const struct v4l2_sliced_vbi_
        state->vps_data[2] = data->data[9];
        state->vps_data[3] = data->data[10];
        state->vps_data[4] = data->data[11];
-       v4l2_dbg(1, debug, sd, "Set VPS data %02x %02x %02x %02x %02x\n",
-               state->vps_data[0], state->vps_data[1],
-               state->vps_data[2], state->vps_data[3],
-               state->vps_data[4]);
+       v4l2_dbg(1, debug, sd, "Set VPS data %*ph\n", 5, state->vps_data);
        saa7127_write(sd, 0x55, state->vps_data[0]);
        saa7127_write(sd, 0x56, state->vps_data[1]);
        saa7127_write(sd, 0x57, state->vps_data[2]);
@@ -628,7 +625,7 @@ static int saa7127_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
 {
        struct saa7127_state *state = to_state(sd);
 
-       memset(fmt, 0, sizeof(*fmt));
+       memset(fmt->service_lines, 0, sizeof(fmt->service_lines));
        if (state->vps_enable)
                fmt->service_lines[0][16] = V4L2_SLICED_VPS;
        if (state->wss_enable)
similarity index 99%
rename from drivers/media/video/smiapp-pll.c
rename to drivers/media/i2c/smiapp-pll.c
index a2e41a21dc65908f93a448f8b4eb68b4186424af..a577614bd84f53113470c085e4e1cd221d761a14 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp-pll.c
+ * drivers/media/i2c/smiapp-pll.c
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 98%
rename from drivers/media/video/smiapp-pll.h
rename to drivers/media/i2c/smiapp-pll.h
index 9eab63f23afb1a31c33448dfc25059d55e9d3eba..cb2d2db5d02def416e10e3d638df33079655500f 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp-pll.h
+ * drivers/media/i2c/smiapp-pll.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 78%
rename from drivers/media/video/smiapp/Makefile
rename to drivers/media/i2c/smiapp/Makefile
index 36b0cfa2c541e6b7fcb5a344d2d22fee6266ccb1..f45a003cbe7e3dbbedfc5d87882389c8d666650a 100644 (file)
@@ -2,4 +2,4 @@ smiapp-objs                     += smiapp-core.o smiapp-regs.o \
                                   smiapp-quirk.o smiapp-limits.o
 obj-$(CONFIG_VIDEO_SMIAPP)     += smiapp.o
 
-ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/i2c
similarity index 98%
rename from drivers/media/video/smiapp/smiapp-core.c
rename to drivers/media/i2c/smiapp/smiapp-core.c
index bfd47c10613433fa50990ea6b13f6a00b09db5fd..e08e588ad24b5f90808279629bf9c80a2c22aecc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-core.c
+ * drivers/media/i2c/smiapp/smiapp-core.c
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
@@ -777,7 +777,11 @@ static int smiapp_get_mbus_formats(struct smiapp_sensor *sensor)
                        dev_dbg(&client->dev, "jolly good! %d\n", j);
 
                        sensor->default_mbus_frame_fmts |= 1 << j;
-                       if (!sensor->csi_format) {
+                       if (!sensor->csi_format
+                           || f->width > sensor->csi_format->width
+                           || (f->width == sensor->csi_format->width
+                               && f->compressed
+                               > sensor->csi_format->compressed)) {
                                sensor->csi_format = f;
                                sensor->internal_csi_format = f;
                        }
@@ -2207,6 +2211,21 @@ smiapp_sysfs_nvm_read(struct device *dev, struct device_attribute *attr,
 }
 static DEVICE_ATTR(nvm, S_IRUGO, smiapp_sysfs_nvm_read, NULL);
 
+static ssize_t
+smiapp_sysfs_ident_read(struct device *dev, struct device_attribute *attr,
+                       char *buf)
+{
+       struct v4l2_subdev *subdev = i2c_get_clientdata(to_i2c_client(dev));
+       struct smiapp_sensor *sensor = to_smiapp_sensor(subdev);
+       struct smiapp_module_info *minfo = &sensor->minfo;
+
+       return snprintf(buf, PAGE_SIZE, "%2.2x%4.4x%2.2x\n",
+                       minfo->manufacturer_id, minfo->model_id,
+                       minfo->revision_number_major) + 1;
+}
+
+static DEVICE_ATTR(ident, S_IRUGO, smiapp_sysfs_ident_read, NULL);
+
 /* -----------------------------------------------------------------------------
  * V4L2 subdev core operations
  */
@@ -2355,20 +2374,19 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
        unsigned int i;
        int rval;
 
-       sensor->vana = regulator_get(&client->dev, "VANA");
+       sensor->vana = devm_regulator_get(&client->dev, "VANA");
        if (IS_ERR(sensor->vana)) {
                dev_err(&client->dev, "could not get regulator for vana\n");
                return -ENODEV;
        }
 
        if (!sensor->platform_data->set_xclk) {
-               sensor->ext_clk = clk_get(&client->dev,
-                                         sensor->platform_data->ext_clk_name);
+               sensor->ext_clk = devm_clk_get(&client->dev,
+                                       sensor->platform_data->ext_clk_name);
                if (IS_ERR(sensor->ext_clk)) {
                        dev_err(&client->dev, "could not get clock %s\n",
                                sensor->platform_data->ext_clk_name);
-                       rval = -ENODEV;
-                       goto out_clk_get;
+                       return -ENODEV;
                }
 
                rval = clk_set_rate(sensor->ext_clk,
@@ -2378,8 +2396,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
                                "unable to set clock %s freq to %u\n",
                                sensor->platform_data->ext_clk_name,
                                sensor->platform_data->ext_clk);
-                       rval = -ENODEV;
-                       goto out_clk_set_rate;
+                       return -ENODEV;
                }
        }
 
@@ -2389,8 +2406,7 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
                        dev_err(&client->dev,
                                "unable to acquire reset gpio %d\n",
                                sensor->platform_data->xshutdown);
-                       rval = -ENODEV;
-                       goto out_clk_set_rate;
+                       return -ENODEV;
                }
        }
 
@@ -2466,22 +2482,27 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
        sensor->binning_horizontal = 1;
        sensor->binning_vertical = 1;
 
+       if (device_create_file(&client->dev, &dev_attr_ident) != 0) {
+               dev_err(&client->dev, "sysfs ident entry creation failed\n");
+               rval = -ENOENT;
+               goto out_power_off;
+       }
        /* SMIA++ NVM initialization - it will be read from the sensor
         * when it is first requested by userspace.
         */
        if (sensor->minfo.smiapp_version && sensor->platform_data->nvm_size) {
-               sensor->nvm = kzalloc(sensor->platform_data->nvm_size,
-                                     GFP_KERNEL);
+               sensor->nvm = devm_kzalloc(&client->dev,
+                               sensor->platform_data->nvm_size, GFP_KERNEL);
                if (sensor->nvm == NULL) {
                        dev_err(&client->dev, "nvm buf allocation failed\n");
                        rval = -ENOMEM;
-                       goto out_power_off;
+                       goto out_ident_release;
                }
 
                if (device_create_file(&client->dev, &dev_attr_nvm) != 0) {
                        dev_err(&client->dev, "sysfs nvm entry failed\n");
                        rval = -EBUSY;
-                       goto out_power_off;
+                       goto out_ident_release;
                }
        }
 
@@ -2636,22 +2657,16 @@ static int smiapp_registered(struct v4l2_subdev *subdev)
 out_nvm_release:
        device_remove_file(&client->dev, &dev_attr_nvm);
 
+out_ident_release:
+       device_remove_file(&client->dev, &dev_attr_ident);
+
 out_power_off:
-       kfree(sensor->nvm);
-       sensor->nvm = NULL;
        smiapp_power_off(sensor);
 
 out_smiapp_power_on:
        if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
                gpio_free(sensor->platform_data->xshutdown);
 
-out_clk_set_rate:
-       clk_put(sensor->ext_clk);
-       sensor->ext_clk = NULL;
-
-out_clk_get:
-       regulator_put(sensor->vana);
-       sensor->vana = NULL;
        return rval;
 }
 
@@ -2801,12 +2816,11 @@ static int smiapp_probe(struct i2c_client *client,
                        const struct i2c_device_id *devid)
 {
        struct smiapp_sensor *sensor;
-       int rval;
 
        if (client->dev.platform_data == NULL)
                return -ENODEV;
 
-       sensor = kzalloc(sizeof(*sensor), GFP_KERNEL);
+       sensor = devm_kzalloc(&client->dev, sizeof(*sensor), GFP_KERNEL);
        if (sensor == NULL)
                return -ENOMEM;
 
@@ -2821,12 +2835,8 @@ static int smiapp_probe(struct i2c_client *client,
        sensor->src->sensor = sensor;
 
        sensor->src->pads[0].flags = MEDIA_PAD_FL_SOURCE;
-       rval = media_entity_init(&sensor->src->sd.entity, 2,
+       return media_entity_init(&sensor->src->sd.entity, 2,
                                 sensor->src->pads, 0);
-       if (rval < 0)
-               kfree(sensor);
-
-       return rval;
 }
 
 static int __exit smiapp_remove(struct i2c_client *client)
@@ -2845,10 +2855,9 @@ static int __exit smiapp_remove(struct i2c_client *client)
                sensor->power_count = 0;
        }
 
-       if (sensor->nvm) {
+       device_remove_file(&client->dev, &dev_attr_ident);
+       if (sensor->nvm)
                device_remove_file(&client->dev, &dev_attr_nvm);
-               kfree(sensor->nvm);
-       }
 
        for (i = 0; i < sensor->ssds_used; i++) {
                media_entity_cleanup(&sensor->ssds[i].sd.entity);
@@ -2857,12 +2866,6 @@ static int __exit smiapp_remove(struct i2c_client *client)
        smiapp_free_controls(sensor);
        if (sensor->platform_data->xshutdown != SMIAPP_NO_XSHUTDOWN)
                gpio_free(sensor->platform_data->xshutdown);
-       if (sensor->ext_clk)
-               clk_put(sensor->ext_clk);
-       if (sensor->vana)
-               regulator_put(sensor->vana);
-
-       kfree(sensor);
 
        return 0;
 }
similarity index 99%
rename from drivers/media/video/smiapp/smiapp-limits.c
rename to drivers/media/i2c/smiapp/smiapp-limits.c
index 0800e095724e2d4058ba5754880c066a35cda0d8..fb2f81ad8c3b39f56d7507e740f5cd9dc9fd4da2 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-limits.c
+ * drivers/media/i2c/smiapp/smiapp-limits.c
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 99%
rename from drivers/media/video/smiapp/smiapp-limits.h
rename to drivers/media/i2c/smiapp/smiapp-limits.h
index 7f4836bb78db97754c0de9b5a2bde3da5f68a694..9ae765e23ea53b20ca3176ce1070205821a4b1f0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-limits.h
+ * drivers/media/i2c/smiapp/smiapp-limits.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 94%
rename from drivers/media/video/smiapp/smiapp-quirk.c
rename to drivers/media/i2c/smiapp/smiapp-quirk.c
index 55e87950dcea5ca23d9c482f3f3c93a3ffaf3ed9..725cf62836c632f4bbf2c536b97f6d0384497cf4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-quirk.c
+ * drivers/media/i2c/smiapp/smiapp-quirk.c
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
@@ -61,26 +61,6 @@ void smiapp_replace_limit(struct smiapp_sensor *sensor,
        sensor->limits[limit] = val;
 }
 
-int smiapp_replace_limit_at(struct smiapp_sensor *sensor,
-                           u32 reg, u32 val)
-{
-       struct i2c_client *client = v4l2_get_subdevdata(&sensor->src->sd);
-       int i;
-
-       for (i = 0; smiapp_reg_limits[i].addr; i++) {
-               if ((smiapp_reg_limits[i].addr & 0xffff) != reg)
-                       continue;
-
-               smiapp_replace_limit(sensor, i, val);
-
-               return 0;
-       }
-
-       dev_dbg(&client->dev, "quirk: bad register 0x%4.4x\n", reg);
-
-       return -EINVAL;
-}
-
 bool smiapp_quirk_reg(struct smiapp_sensor *sensor,
                      u32 reg, u32 *val)
 {
similarity index 98%
rename from drivers/media/video/smiapp/smiapp-quirk.h
rename to drivers/media/i2c/smiapp/smiapp-quirk.h
index f4dcaabaefe7066f99cd8d10ed22c5f4bfb62625..86fd3e8bfb0fe0e3e78a116ad93100b6c4ff0013 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-quirk.h
+ * drivers/media/i2c/smiapp/smiapp-quirk.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 99%
rename from drivers/media/video/smiapp/smiapp-reg-defs.h
rename to drivers/media/i2c/smiapp/smiapp-reg-defs.h
index a089eb8161e1e3c16f9c5df53602afe6ad8b632f..defa7c5adebf0e07fbd51d4f5d4963baf87d52e0 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-reg-defs.h
+ * drivers/media/i2c/smiapp/smiapp-reg-defs.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 98%
rename from drivers/media/video/smiapp/smiapp-reg.h
rename to drivers/media/i2c/smiapp/smiapp-reg.h
index d0167aa17534b84d2f94d7455de2dfd336115e62..54568ca2fe6d987c79c477c4262988ff6dcfbf4d 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-reg.h
+ * drivers/media/i2c/smiapp/smiapp-reg.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 99%
rename from drivers/media/video/smiapp/smiapp-regs.c
rename to drivers/media/i2c/smiapp/smiapp-regs.c
index b1812b17a4075150365a5ff7c6c1cd6b8512b69a..70e0d8db01301d56388ab452c318db728151e35b 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp-regs.c
+ * drivers/media/i2c/smiapp/smiapp-regs.c
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
similarity index 99%
rename from drivers/media/video/smiapp/smiapp.h
rename to drivers/media/i2c/smiapp/smiapp.h
index 587f7f11238d7125f96abc989fa24aed183b099b..4182a695ab53913e540cf230f2a5abdb0b810a38 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/smiapp/smiapp.h
+ * drivers/media/i2c/smiapp/smiapp.h
  *
  * Generic driver for SMIA/SMIA++ compliant camera modules
  *
diff --git a/drivers/media/i2c/soc_camera/Kconfig b/drivers/media/i2c/soc_camera/Kconfig
new file mode 100644 (file)
index 0000000..6dff2b7
--- /dev/null
@@ -0,0 +1,89 @@
+comment "soc_camera sensor drivers"
+
+config SOC_CAMERA_IMX074
+       tristate "imx074 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports IMX074 cameras from Sony
+
+config SOC_CAMERA_MT9M001
+       tristate "mt9m001 support"
+       depends on SOC_CAMERA && I2C
+       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
+       help
+         This driver supports MT9M001 cameras from Micron, monochrome
+         and colour models.
+
+config SOC_CAMERA_MT9M111
+       tristate "mt9m111, mt9m112 and mt9m131 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports MT9M111, MT9M112 and MT9M131 cameras from
+         Micron/Aptina
+
+config SOC_CAMERA_MT9T031
+       tristate "mt9t031 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports MT9T031 cameras from Micron.
+
+config SOC_CAMERA_MT9T112
+       tristate "mt9t112 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This driver supports MT9T112 cameras from Aptina.
+
+config SOC_CAMERA_MT9V022
+       tristate "mt9v022 and mt9v024 support"
+       depends on SOC_CAMERA && I2C
+       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
+       help
+         This driver supports MT9V022 cameras from Micron
+
+config SOC_CAMERA_OV2640
+       tristate "ov2640 camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a ov2640 camera driver
+
+config SOC_CAMERA_OV5642
+       tristate "ov5642 camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a V4L2 camera driver for the OmniVision OV5642 sensor
+
+config SOC_CAMERA_OV6650
+       tristate "ov6650 sensor support"
+       depends on SOC_CAMERA && I2C
+       ---help---
+         This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor
+
+config SOC_CAMERA_OV772X
+       tristate "ov772x camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a ov772x camera driver
+
+config SOC_CAMERA_OV9640
+       tristate "ov9640 camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a ov9640 camera driver
+
+config SOC_CAMERA_OV9740
+       tristate "ov9740 camera support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a ov9740 camera driver
+
+config SOC_CAMERA_RJ54N1
+       tristate "rj54n1cb0c support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a rj54n1cb0c video driver
+
+config SOC_CAMERA_TW9910
+       tristate "tw9910 support"
+       depends on SOC_CAMERA && I2C
+       help
+         This is a tw9910 video driver
diff --git a/drivers/media/i2c/soc_camera/Makefile b/drivers/media/i2c/soc_camera/Makefile
new file mode 100644 (file)
index 0000000..d0421fe
--- /dev/null
@@ -0,0 +1,14 @@
+obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
+obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
+obj-$(CONFIG_SOC_CAMERA_MT9M111)       += mt9m111.o
+obj-$(CONFIG_SOC_CAMERA_MT9T031)       += mt9t031.o
+obj-$(CONFIG_SOC_CAMERA_MT9T112)       += mt9t112.o
+obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
+obj-$(CONFIG_SOC_CAMERA_OV2640)                += ov2640.o
+obj-$(CONFIG_SOC_CAMERA_OV5642)                += ov5642.o
+obj-$(CONFIG_SOC_CAMERA_OV6650)                += ov6650.o
+obj-$(CONFIG_SOC_CAMERA_OV772X)                += ov772x.o
+obj-$(CONFIG_SOC_CAMERA_OV9640)                += ov9640.o
+obj-$(CONFIG_SOC_CAMERA_OV9740)                += ov9740.o
+obj-$(CONFIG_SOC_CAMERA_RJ54N1)                += rj54n1cb0c.o
+obj-$(CONFIG_SOC_CAMERA_TW9910)                += tw9910.o
similarity index 95%
rename from drivers/media/video/imx074.c
rename to drivers/media/i2c/soc_camera/imx074.c
index 351e9bafe8fe815daa8a5f6f6479adac65cb7581..f8534eec9de94a58f1de1497b6b4460239a92845 100644 (file)
@@ -268,6 +268,14 @@ static int imx074_g_chip_ident(struct v4l2_subdev *sd,
        return 0;
 }
 
+static int imx074_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int imx074_g_mbus_config(struct v4l2_subdev *sd,
                                struct v4l2_mbus_config *cfg)
 {
@@ -292,6 +300,7 @@ static struct v4l2_subdev_video_ops imx074_subdev_video_ops = {
 
 static struct v4l2_subdev_core_ops imx074_subdev_core_ops = {
        .g_chip_ident   = imx074_g_chip_ident,
+       .s_power        = imx074_s_power,
 };
 
 static struct v4l2_subdev_ops imx074_subdev_ops = {
@@ -301,26 +310,33 @@ static struct v4l2_subdev_ops imx074_subdev_ops = {
 
 static int imx074_video_probe(struct i2c_client *client)
 {
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
        int ret;
        u16 id;
 
+       ret = imx074_s_power(subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /* Read sensor Model ID */
        ret = reg_read(client, 0);
        if (ret < 0)
-               return ret;
+               goto done;
 
        id = ret << 8;
 
        ret = reg_read(client, 1);
        if (ret < 0)
-               return ret;
+               goto done;
 
        id |= ret;
 
        dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
 
-       if (id != 0x74)
-               return -ENODEV;
+       if (id != 0x74) {
+               ret = -ENODEV;
+               goto done;
+       }
 
        /* PLL Setting EXTCLK=24MHz, 22.5times */
        reg_write(client, PLL_MULTIPLIER, 0x2D);
@@ -402,7 +418,11 @@ static int imx074_video_probe(struct i2c_client *client)
 
        reg_write(client, GROUPED_PARAMETER_HOLD, 0x00);        /* off */
 
-       return 0;
+       ret = 0;
+
+done:
+       imx074_s_power(subdev, 0);
+       return ret;
 }
 
 static int imx074_probe(struct i2c_client *client,
similarity index 97%
rename from drivers/media/video/mt9m001.c
rename to drivers/media/i2c/soc_camera/mt9m001.c
index 00583f5fd26bbc26c6dcd9861ff4fcf774118597..19f8a07764f97cf3b5e56b3c083c463b31cb99ed 100644 (file)
@@ -171,7 +171,7 @@ static int mt9m001_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9m001_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9m001_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9m001 *mt9m001 = to_mt9m001(client);
@@ -377,6 +377,14 @@ static int mt9m001_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int mt9m001_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int mt9m001_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct mt9m001 *mt9m001 = container_of(ctrl->handler,
@@ -482,6 +490,10 @@ static int mt9m001_video_probe(struct soc_camera_link *icl,
        unsigned long flags;
        int ret;
 
+       ret = mt9m001_s_power(&mt9m001->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /* Enable the chip */
        data = reg_write(client, MT9M001_CHIP_ENABLE, 1);
        dev_dbg(&client->dev, "write: %d\n", data);
@@ -503,7 +515,8 @@ static int mt9m001_video_probe(struct soc_camera_link *icl,
        default:
                dev_err(&client->dev,
                        "No MT9M001 chip detected, register read %x\n", data);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        mt9m001->num_fmts = 0;
@@ -532,11 +545,17 @@ static int mt9m001_video_probe(struct soc_camera_link *icl,
                 data == 0x8431 ? "C12STM" : "C12ST");
 
        ret = mt9m001_init(client);
-       if (ret < 0)
+       if (ret < 0) {
                dev_err(&client->dev, "Failed to initialise the camera\n");
+               goto done;
+       }
 
        /* mt9m001_init() has reset the chip, returning registers to defaults */
-       return v4l2_ctrl_handler_setup(&mt9m001->hdl);
+       ret = v4l2_ctrl_handler_setup(&mt9m001->hdl);
+
+done:
+       mt9m001_s_power(&mt9m001->subdev, 0);
+       return ret;
 }
 
 static void mt9m001_video_remove(struct soc_camera_link *icl)
@@ -566,6 +585,7 @@ static struct v4l2_subdev_core_ops mt9m001_subdev_core_ops = {
        .g_register     = mt9m001_g_register,
        .s_register     = mt9m001_s_register,
 #endif
+       .s_power        = mt9m001_s_power,
 };
 
 static int mt9m001_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
similarity index 95%
rename from drivers/media/video/mt9m111.c
rename to drivers/media/i2c/soc_camera/mt9m111.c
index 863d722dda06ebf25440c0f2fbb491c7eb3d2ce9..62fd94af599be4010e72ccde0bf6fa61f7794a5f 100644 (file)
@@ -383,7 +383,7 @@ static int mt9m111_reset(struct mt9m111 *mt9m111)
        return ret;
 }
 
-static int mt9m111_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9m111_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct v4l2_rect rect = a->c;
        struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
@@ -796,45 +796,37 @@ static int mt9m111_init(struct mt9m111 *mt9m111)
        return ret;
 }
 
-/*
- * Interface active, can use i2c. If it fails, it can indeed mean, that
- * this wasn't our capture interface, so, we wait for the right one
- */
-static int mt9m111_video_probe(struct i2c_client *client)
+static int mt9m111_power_on(struct mt9m111 *mt9m111)
 {
-       struct mt9m111 *mt9m111 = to_mt9m111(client);
-       s32 data;
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
-       data = reg_read(CHIP_VERSION);
+       ret = soc_camera_power_on(&client->dev, icl);
+       if (ret < 0)
+               return ret;
 
-       switch (data) {
-       case 0x143a: /* MT9M111 or MT9M131 */
-               mt9m111->model = V4L2_IDENT_MT9M111;
-               dev_info(&client->dev,
-                       "Detected a MT9M111/MT9M131 chip ID %x\n", data);
-               break;
-       case 0x148c: /* MT9M112 */
-               mt9m111->model = V4L2_IDENT_MT9M112;
-               dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
-               break;
-       default:
-               dev_err(&client->dev,
-                       "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
-                       data);
-               return -ENODEV;
+       ret = mt9m111_resume(mt9m111);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failed to resume the sensor: %d\n", ret);
+               soc_camera_power_off(&client->dev, icl);
        }
 
-       ret = mt9m111_init(mt9m111);
-       if (ret)
-               return ret;
-       return v4l2_ctrl_handler_setup(&mt9m111->hdl);
+       return ret;
+}
+
+static void mt9m111_power_off(struct mt9m111 *mt9m111)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&mt9m111->subdev);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       mt9m111_suspend(mt9m111);
+       soc_camera_power_off(&client->dev, icl);
 }
 
 static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
 {
        struct mt9m111 *mt9m111 = container_of(sd, struct mt9m111, subdev);
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
        int ret = 0;
 
        mutex_lock(&mt9m111->power_lock);
@@ -844,23 +836,18 @@ static int mt9m111_s_power(struct v4l2_subdev *sd, int on)
         * update the power state.
         */
        if (mt9m111->power_count == !on) {
-               if (on) {
-                       ret = mt9m111_resume(mt9m111);
-                       if (ret) {
-                               dev_err(&client->dev,
-                                       "Failed to resume the sensor: %d\n", ret);
-                               goto out;
-                       }
-               } else {
-                       mt9m111_suspend(mt9m111);
-               }
+               if (on)
+                       ret = mt9m111_power_on(mt9m111);
+               else
+                       mt9m111_power_off(mt9m111);
        }
 
-       /* Update the power count. */
-       mt9m111->power_count += on ? 1 : -1;
-       WARN_ON(mt9m111->power_count < 0);
+       if (!ret) {
+               /* Update the power count. */
+               mt9m111->power_count += on ? 1 : -1;
+               WARN_ON(mt9m111->power_count < 0);
+       }
 
-out:
        mutex_unlock(&mt9m111->power_lock);
        return ret;
 }
@@ -919,6 +906,51 @@ static struct v4l2_subdev_ops mt9m111_subdev_ops = {
        .video  = &mt9m111_subdev_video_ops,
 };
 
+/*
+ * Interface active, can use i2c. If it fails, it can indeed mean, that
+ * this wasn't our capture interface, so, we wait for the right one
+ */
+static int mt9m111_video_probe(struct i2c_client *client)
+{
+       struct mt9m111 *mt9m111 = to_mt9m111(client);
+       s32 data;
+       int ret;
+
+       ret = mt9m111_s_power(&mt9m111->subdev, 1);
+       if (ret < 0)
+               return ret;
+
+       data = reg_read(CHIP_VERSION);
+
+       switch (data) {
+       case 0x143a: /* MT9M111 or MT9M131 */
+               mt9m111->model = V4L2_IDENT_MT9M111;
+               dev_info(&client->dev,
+                       "Detected a MT9M111/MT9M131 chip ID %x\n", data);
+               break;
+       case 0x148c: /* MT9M112 */
+               mt9m111->model = V4L2_IDENT_MT9M112;
+               dev_info(&client->dev, "Detected a MT9M112 chip ID %x\n", data);
+               break;
+       default:
+               dev_err(&client->dev,
+                       "No MT9M111/MT9M112/MT9M131 chip detected register read %x\n",
+                       data);
+               ret = -ENODEV;
+               goto done;
+       }
+
+       ret = mt9m111_init(mt9m111);
+       if (ret)
+               goto done;
+
+       ret = v4l2_ctrl_handler_setup(&mt9m111->hdl);
+
+done:
+       mt9m111_s_power(&mt9m111->subdev, 0);
+       return ret;
+}
+
 static int mt9m111_probe(struct i2c_client *client,
                         const struct i2c_device_id *did)
 {
similarity index 97%
rename from drivers/media/video/mt9t031.c
rename to drivers/media/i2c/soc_camera/mt9t031.c
index 1415074138a5409b69a9236d7416f501442d521f..40800b10a0808240f889628026c64e17630de98c 100644 (file)
@@ -161,14 +161,6 @@ static int mt9t031_idle(struct i2c_client *client)
        return ret >= 0 ? 0 : -EIO;
 }
 
-static int mt9t031_disable(struct i2c_client *client)
-{
-       /* Disable the chip */
-       reg_clear(client, MT9T031_OUTPUT_CONTROL, 2);
-
-       return 0;
-}
-
 static int mt9t031_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -302,7 +294,7 @@ static int mt9t031_set_params(struct i2c_client *client,
        return ret < 0 ? ret : 0;
 }
 
-static int mt9t031_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9t031_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct v4l2_rect rect = a->c;
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -616,12 +608,19 @@ static struct device_type mt9t031_dev_type = {
 static int mt9t031_s_power(struct v4l2_subdev *sd, int on)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct video_device *vdev = soc_camera_i2c_to_vdev(client);
+       int ret;
 
-       if (on)
+       if (on) {
+               ret = soc_camera_power_on(&client->dev, icl);
+               if (ret < 0)
+                       return ret;
                vdev->dev.type = &mt9t031_dev_type;
-       else
+       } else {
                vdev->dev.type = NULL;
+               soc_camera_power_off(&client->dev, icl);
+       }
 
        return 0;
 }
@@ -636,9 +635,15 @@ static int mt9t031_video_probe(struct i2c_client *client)
        s32 data;
        int ret;
 
-       /* Enable the chip */
-       data = reg_write(client, MT9T031_CHIP_ENABLE, 1);
-       dev_dbg(&client->dev, "write: %d\n", data);
+       ret = mt9t031_s_power(&mt9t031->subdev, 1);
+       if (ret < 0)
+               return ret;
+
+       ret = mt9t031_idle(client);
+       if (ret < 0) {
+               dev_err(&client->dev, "Failed to initialise the camera\n");
+               goto done;
+       }
 
        /* Read out the chip version register */
        data = reg_read(client, MT9T031_CHIP_VERSION);
@@ -650,16 +655,16 @@ static int mt9t031_video_probe(struct i2c_client *client)
        default:
                dev_err(&client->dev,
                        "No MT9T031 chip detected, register read %x\n", data);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev, "Detected a MT9T031 chip ID %x\n", data);
 
-       ret = mt9t031_idle(client);
-       if (ret < 0)
-               dev_err(&client->dev, "Failed to initialise the camera\n");
-       else
-               v4l2_ctrl_handler_setup(&mt9t031->hdl);
+       ret = v4l2_ctrl_handler_setup(&mt9t031->hdl);
+
+done:
+       mt9t031_s_power(&mt9t031->subdev, 0);
 
        return ret;
 }
@@ -810,12 +815,7 @@ static int mt9t031_probe(struct i2c_client *client,
        mt9t031->xskip = 1;
        mt9t031->yskip = 1;
 
-       mt9t031_idle(client);
-
        ret = mt9t031_video_probe(client);
-
-       mt9t031_disable(client);
-
        if (ret) {
                v4l2_ctrl_handler_free(&mt9t031->hdl);
                kfree(mt9t031);
similarity index 98%
rename from drivers/media/video/mt9t112.c
rename to drivers/media/i2c/soc_camera/mt9t112.c
index e1ae46a7ee96e81f9a4da20bf7c5dc2267c0585b..de7cd836b0a2c8e4fc95cdf821a49b52b103a774 100644 (file)
@@ -776,12 +776,21 @@ static int mt9t112_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int mt9t112_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static struct v4l2_subdev_core_ops mt9t112_subdev_core_ops = {
        .g_chip_ident   = mt9t112_g_chip_ident,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .g_register     = mt9t112_g_register,
        .s_register     = mt9t112_s_register,
 #endif
+       .s_power        = mt9t112_s_power,
 };
 
 
@@ -898,11 +907,11 @@ static int mt9t112_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        return 0;
 }
 
-static int mt9t112_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9t112_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9t112_priv *priv = to_mt9t112(client);
-       struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &a->c;
 
        return mt9t112_set_params(priv, rect, priv->format->code);
 }
@@ -1032,6 +1041,11 @@ static int mt9t112_camera_probe(struct i2c_client *client)
        struct mt9t112_priv *priv = to_mt9t112(client);
        const char          *devname;
        int                  chipid;
+       int                  ret;
+
+       ret = mt9t112_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
 
        /*
         * check and show chip ID
@@ -1049,12 +1063,15 @@ static int mt9t112_camera_probe(struct i2c_client *client)
                break;
        default:
                dev_err(&client->dev, "Product ID error %04x\n", chipid);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev, "%s chip ID %04x\n", devname, chipid);
 
-       return 0;
+done:
+       mt9t112_s_power(&priv->subdev, 0);
+       return ret;
 }
 
 static int mt9t112_probe(struct i2c_client *client,
similarity index 93%
rename from drivers/media/video/mt9v022.c
rename to drivers/media/i2c/soc_camera/mt9v022.c
index 72479247522a8fe923235a88b342145ed0d39cf3..13057b966ee9abe10b7d4e29331ec80ba52fa20a 100644 (file)
@@ -57,6 +57,10 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_AEC_AGC_ENABLE         0xAF
 #define MT9V022_MAX_TOTAL_SHUTTER_WIDTH        0xBD
 
+/* mt9v024 partial list register addresses changes with respect to mt9v022 */
+#define MT9V024_PIXCLK_FV_LV           0x72
+#define MT9V024_MAX_TOTAL_SHUTTER_WIDTH        0xAD
+
 /* Progressive scan, master, defaults */
 #define MT9V022_CHIP_CONTROL_DEFAULT   0x188
 
@@ -67,6 +71,8 @@ MODULE_PARM_DESC(sensor_type, "Sensor type: \"colour\" or \"monochrome\"");
 #define MT9V022_COLUMN_SKIP            1
 #define MT9V022_ROW_SKIP               4
 
+#define is_mt9v024(id) (id == 0x1324)
+
 /* MT9V022 has only one fixed colorspace per pixelcode */
 struct mt9v022_datafmt {
        enum v4l2_mbus_pixelcode        code;
@@ -101,6 +107,22 @@ static const struct mt9v022_datafmt mt9v022_monochrome_fmts[] = {
        {V4L2_MBUS_FMT_Y8_1X8, V4L2_COLORSPACE_JPEG},
 };
 
+/* only registers with different addresses on different mt9v02x sensors */
+struct mt9v02x_register {
+       u8      max_total_shutter_width;
+       u8      pixclk_fv_lv;
+};
+
+static const struct mt9v02x_register mt9v022_register = {
+       .max_total_shutter_width        = MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+       .pixclk_fv_lv                   = MT9V022_PIXCLK_FV_LV,
+};
+
+static const struct mt9v02x_register mt9v024_register = {
+       .max_total_shutter_width        = MT9V024_MAX_TOTAL_SHUTTER_WIDTH,
+       .pixclk_fv_lv                   = MT9V024_PIXCLK_FV_LV,
+};
+
 struct mt9v022 {
        struct v4l2_subdev subdev;
        struct v4l2_ctrl_handler hdl;
@@ -117,6 +139,7 @@ struct mt9v022 {
        struct v4l2_rect rect;  /* Sensor window */
        const struct mt9v022_datafmt *fmt;
        const struct mt9v022_datafmt *fmts;
+       const struct mt9v02x_register *reg;
        int num_fmts;
        int model;      /* V4L2_IDENT_MT9V022* codes from v4l2-chip-ident.h */
        u16 chip_control;
@@ -185,7 +208,7 @@ static int mt9v022_init(struct i2c_client *client)
        if (!ret)
                ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH, 480);
        if (!ret)
-               ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH, 480);
+               ret = reg_write(client, mt9v022->reg->max_total_shutter_width, 480);
        if (!ret)
                /* default - auto */
                ret = reg_clear(client, MT9V022_BLACK_LEVEL_CALIB_CTRL, 1);
@@ -214,7 +237,7 @@ static int mt9v022_s_stream(struct v4l2_subdev *sd, int enable)
        return 0;
 }
 
-static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int mt9v022_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct mt9v022 *mt9v022 = to_mt9v022(client);
@@ -238,7 +261,7 @@ static int mt9v022_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        ret = reg_read(client, MT9V022_AEC_AGC_ENABLE);
        if (ret >= 0) {
                if (ret & 1) /* Autoexposure */
-                       ret = reg_write(client, MT9V022_MAX_TOTAL_SHUTTER_WIDTH,
+                       ret = reg_write(client, mt9v022->reg->max_total_shutter_width,
                                        rect.height + mt9v022->y_skip_top + 43);
                else
                        ret = reg_write(client, MT9V022_TOTAL_SHUTTER_WIDTH,
@@ -445,6 +468,14 @@ static int mt9v022_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int mt9v022_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int mt9v022_g_volatile_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct mt9v022 *mt9v022 = container_of(ctrl->handler,
@@ -570,17 +601,24 @@ static int mt9v022_video_probe(struct i2c_client *client)
        int ret;
        unsigned long flags;
 
+       ret = mt9v022_s_power(&mt9v022->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /* Read out the chip version register */
        data = reg_read(client, MT9V022_CHIP_VERSION);
 
-       /* must be 0x1311 or 0x1313 */
-       if (data != 0x1311 && data != 0x1313) {
+       /* must be 0x1311, 0x1313 or 0x1324 */
+       if (data != 0x1311 && data != 0x1313 && data != 0x1324) {
                ret = -ENODEV;
                dev_info(&client->dev, "No MT9V022 found, ID register 0x%x\n",
                         data);
                goto ei2c;
        }
 
+       mt9v022->reg = is_mt9v024(data) ? &mt9v024_register :
+                       &mt9v022_register;
+
        /* Soft reset */
        ret = reg_write(client, MT9V022_RESET, 1);
        if (ret < 0)
@@ -640,6 +678,7 @@ static int mt9v022_video_probe(struct i2c_client *client)
                dev_err(&client->dev, "Failed to initialise the camera\n");
 
 ei2c:
+       mt9v022_s_power(&mt9v022->subdev, 0);
        return ret;
 }
 
@@ -664,6 +703,7 @@ static struct v4l2_subdev_core_ops mt9v022_subdev_core_ops = {
        .g_register     = mt9v022_g_register,
        .s_register     = mt9v022_s_register,
 #endif
+       .s_power        = mt9v022_s_power,
 };
 
 static int mt9v022_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
@@ -728,7 +768,7 @@ static int mt9v022_s_mbus_config(struct v4l2_subdev *sd,
        if (!(flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH))
                pixclk |= 0x2;
 
-       ret = reg_write(client, MT9V022_PIXCLK_FV_LV, pixclk);
+       ret = reg_write(client, mt9v022->reg->pixclk_fv_lv, pixclk);
        if (ret < 0)
                return ret;
 
similarity index 98%
rename from drivers/media/video/ov2640.c
rename to drivers/media/i2c/soc_camera/ov2640.c
index 7c44d1fe3c87a8224823e2357c297abfa5b43968..78ac5744cb5dd55ffda31edf6e7ead3e74fb1e0c 100644 (file)
@@ -742,6 +742,14 @@ static int ov2640_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int ov2640_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 /* Select the nearest higher resolution for capture */
 static const struct ov2640_win_size *ov2640_select_win(u32 *width, u32 *height)
 {
@@ -947,6 +955,10 @@ static int ov2640_video_probe(struct i2c_client *client)
        const char *devname;
        int ret;
 
+       ret = ov2640_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /*
         * check and show product ID and manufacturer ID
         */
@@ -965,16 +977,17 @@ static int ov2640_video_probe(struct i2c_client *client)
                dev_err(&client->dev,
                        "Product ID error %x:%x\n", pid, ver);
                ret = -ENODEV;
-               goto err;
+               goto done;
        }
 
        dev_info(&client->dev,
                 "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
                 devname, pid, ver, midh, midl);
 
-       return v4l2_ctrl_handler_setup(&priv->hdl);
+       ret = v4l2_ctrl_handler_setup(&priv->hdl);
 
-err:
+done:
+       ov2640_s_power(&priv->subdev, 0);
        return ret;
 }
 
@@ -988,6 +1001,7 @@ static struct v4l2_subdev_core_ops ov2640_subdev_core_ops = {
        .g_register     = ov2640_g_register,
        .s_register     = ov2640_s_register,
 #endif
+       .s_power        = ov2640_s_power,
 };
 
 static int ov2640_g_mbus_config(struct v4l2_subdev *sd,
similarity index 96%
rename from drivers/media/video/ov5642.c
rename to drivers/media/i2c/soc_camera/ov5642.c
index 0bc93313d37ad1036da74be56a655dd9bbe880ae..8577e0cfb7fed34c70440f1df25a7c4fbfda1c53 100644 (file)
@@ -865,24 +865,24 @@ static int ov5642_g_chip_ident(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov5642_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int ov5642_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov5642 *priv = to_ov5642(client);
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_rect rect = a->c;
        int ret;
 
-       v4l_bound_align_image(&rect->width, 48, OV5642_MAX_WIDTH, 1,
-                             &rect->height, 32, OV5642_MAX_HEIGHT, 1, 0);
+       v4l_bound_align_image(&rect.width, 48, OV5642_MAX_WIDTH, 1,
+                             &rect.height, 32, OV5642_MAX_HEIGHT, 1, 0);
 
-       priv->crop_rect.width   = rect->width;
-       priv->crop_rect.height  = rect->height;
-       priv->total_width       = rect->width + BLANKING_EXTRA_WIDTH;
-       priv->total_height      = max_t(int, rect->height +
+       priv->crop_rect.width   = rect.width;
+       priv->crop_rect.height  = rect.height;
+       priv->total_width       = rect.width + BLANKING_EXTRA_WIDTH;
+       priv->total_height      = max_t(int, rect.height +
                                                        BLANKING_EXTRA_HEIGHT,
                                                        BLANKING_MIN_HEIGHT);
-       priv->crop_rect.width           = rect->width;
-       priv->crop_rect.height          = rect->height;
+       priv->crop_rect.width           = rect.width;
+       priv->crop_rect.height          = rect.height;
 
        ret = ov5642_write_array(client, ov5642_default_regs_init);
        if (!ret)
@@ -933,13 +933,17 @@ static int ov5642_g_mbus_config(struct v4l2_subdev *sd,
 
 static int ov5642_s_power(struct v4l2_subdev *sd, int on)
 {
-       struct i2c_client *client;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        int ret;
 
        if (!on)
-               return 0;
+               return soc_camera_power_off(&client->dev, icl);
+
+       ret = soc_camera_power_on(&client->dev, icl);
+       if (ret < 0)
+               return ret;
 
-       client = v4l2_get_subdevdata(sd);
        ret = ov5642_write_array(client, ov5642_default_regs_init);
        if (!ret)
                ret = ov5642_set_resolution(sd);
@@ -976,29 +980,40 @@ static struct v4l2_subdev_ops ov5642_subdev_ops = {
 
 static int ov5642_video_probe(struct i2c_client *client)
 {
+       struct v4l2_subdev *subdev = i2c_get_clientdata(client);
        int ret;
        u8 id_high, id_low;
        u16 id;
 
+       ret = ov5642_s_power(subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /* Read sensor Model ID */
        ret = reg_read(client, REG_CHIP_ID_HIGH, &id_high);
        if (ret < 0)
-               return ret;
+               goto done;
 
        id = id_high << 8;
 
        ret = reg_read(client, REG_CHIP_ID_LOW, &id_low);
        if (ret < 0)
-               return ret;
+               goto done;
 
        id |= id_low;
 
        dev_info(&client->dev, "Chip ID 0x%04x detected\n", id);
 
-       if (id != 0x5642)
-               return -ENODEV;
+       if (id != 0x5642) {
+               ret = -ENODEV;
+               goto done;
+       }
 
-       return 0;
+       ret = 0;
+
+done:
+       ov5642_s_power(subdev, 0);
+       return ret;
 }
 
 static int ov5642_probe(struct i2c_client *client,
similarity index 95%
rename from drivers/media/video/ov6650.c
rename to drivers/media/i2c/soc_camera/ov6650.c
index 3e028b1970dd4124412b6b844f07bf0d61222637..e87feb0881e391023e8a0143188207e234bdab2d 100644 (file)
@@ -432,6 +432,14 @@ static int ov6650_set_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int ov6650_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -443,42 +451,42 @@ static int ov6650_g_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
        return 0;
 }
 
-static int ov6650_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int ov6650_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct ov6650 *priv = to_ov6650(client);
-       struct v4l2_rect *rect = &a->c;
+       struct v4l2_rect rect = a->c;
        int ret;
 
        if (a->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
 
-       rect->left   = ALIGN(rect->left,   2);
-       rect->width  = ALIGN(rect->width,  2);
-       rect->top    = ALIGN(rect->top,    2);
-       rect->height = ALIGN(rect->height, 2);
-       soc_camera_limit_side(&rect->left, &rect->width,
+       rect.left   = ALIGN(rect.left,   2);
+       rect.width  = ALIGN(rect.width,  2);
+       rect.top    = ALIGN(rect.top,    2);
+       rect.height = ALIGN(rect.height, 2);
+       soc_camera_limit_side(&rect.left, &rect.width,
                        DEF_HSTRT << 1, 2, W_CIF);
-       soc_camera_limit_side(&rect->top, &rect->height,
+       soc_camera_limit_side(&rect.top, &rect.height,
                        DEF_VSTRT << 1, 2, H_CIF);
 
-       ret = ov6650_reg_write(client, REG_HSTRT, rect->left >> 1);
+       ret = ov6650_reg_write(client, REG_HSTRT, rect.left >> 1);
        if (!ret) {
-               priv->rect.left = rect->left;
+               priv->rect.left = rect.left;
                ret = ov6650_reg_write(client, REG_HSTOP,
-                               (rect->left + rect->width) >> 1);
+                               (rect.left + rect.width) >> 1);
        }
        if (!ret) {
-               priv->rect.width = rect->width;
-               ret = ov6650_reg_write(client, REG_VSTRT, rect->top >> 1);
+               priv->rect.width = rect.width;
+               ret = ov6650_reg_write(client, REG_VSTRT, rect.top >> 1);
        }
        if (!ret) {
-               priv->rect.top = rect->top;
+               priv->rect.top = rect.top;
                ret = ov6650_reg_write(client, REG_VSTOP,
-                               (rect->top + rect->height) >> 1);
+                               (rect.top + rect.height) >> 1);
        }
        if (!ret)
-               priv->rect.height = rect->height;
+               priv->rect.height = rect.height;
 
        return ret;
 }
@@ -821,8 +829,13 @@ static int ov6650_prog_dflt(struct i2c_client *client)
 
 static int ov6650_video_probe(struct i2c_client *client)
 {
+       struct ov6650 *priv = to_ov6650(client);
        u8              pidh, pidl, midh, midl;
-       int             ret = 0;
+       int             ret;
+
+       ret = ov6650_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
 
        /*
         * check and show product ID and manufacturer ID
@@ -836,12 +849,13 @@ static int ov6650_video_probe(struct i2c_client *client)
                ret = ov6650_reg_read(client, REG_MIDL, &midl);
 
        if (ret)
-               return ret;
+               goto done;
 
        if ((pidh != OV6650_PIDH) || (pidl != OV6650_PIDL)) {
                dev_err(&client->dev, "Product ID error 0x%02x:0x%02x\n",
                                pidh, pidl);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev,
@@ -851,7 +865,11 @@ static int ov6650_video_probe(struct i2c_client *client)
        ret = ov6650_reset(client);
        if (!ret)
                ret = ov6650_prog_dflt(client);
+       if (!ret)
+               ret = v4l2_ctrl_handler_setup(&priv->hdl);
 
+done:
+       ov6650_s_power(&priv->subdev, 0);
        return ret;
 }
 
@@ -866,6 +884,7 @@ static struct v4l2_subdev_core_ops ov6650_core_ops = {
        .g_register             = ov6650_get_register,
        .s_register             = ov6650_set_register,
 #endif
+       .s_power                = ov6650_s_power,
 };
 
 /* Request bus settings on camera side */
@@ -1010,9 +1029,6 @@ static int ov6650_probe(struct i2c_client *client,
        priv->colorspace  = V4L2_COLORSPACE_JPEG;
 
        ret = ov6650_video_probe(client);
-       if (!ret)
-               ret = v4l2_ctrl_handler_setup(&priv->hdl);
-
        if (ret) {
                v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
similarity index 81%
rename from drivers/media/video/ov772x.c
rename to drivers/media/i2c/soc_camera/ov772x.c
index 6d79b89b860340dddaf2ae0c1f64f3d121ee1f2d..e4a10751894dc477c3de6010323882ed7020f2c4 100644 (file)
@@ -16,6 +16,7 @@
  */
 
 #include <linux/init.h>
+#include <linux/kernel.h>
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/slab.h>
 #define SLCT_VGA        0x00   /*   0 : VGA */
 #define SLCT_QVGA       0x40   /*   1 : QVGA */
 #define ITU656_ON_OFF   0x20   /* ITU656 protocol ON/OFF selection */
+#define SENSOR_RAW     0x10    /* Sensor RAW */
                                /* RGB output format control */
 #define FMT_MASK        0x0c   /*      Mask of color format */
 #define FMT_GBR422      0x00   /*      00 : GBR 4:2:2 */
 #define SGLF_ON_OFF     0x02   /* Single frame ON/OFF selection */
 #define SGLF_TRIG       0x01   /* Single frame transfer trigger */
 
+/* HREF */
+#define HREF_VSTART_SHIFT      6       /* VSTART LSB */
+#define HREF_HSTART_SHIFT      4       /* HSTART 2 LSBs */
+#define HREF_VSIZE_SHIFT       2       /* VSIZE LSB */
+#define HREF_HSIZE_SHIFT       0       /* HSIZE 2 LSBs */
+
 /* EXHCH */
-#define VSIZE_LSB       0x04   /* Vertical data output size LSB */
+#define EXHCH_VSIZE_SHIFT      2       /* VOUTSIZE LSB */
+#define EXHCH_HSIZE_SHIFT      0       /* HOUTSIZE 2 LSBs */
 
 /* DSP_CTRL1 */
 #define FIFO_ON         0x80   /* FIFO enable/disable selection */
 #define CBAR_ON         0x20   /*   ON */
 #define CBAR_OFF        0x00   /*   OFF */
 
-/* HSTART */
-#define HST_VGA         0x23
-#define HST_QVGA        0x3F
-
-/* HSIZE */
-#define HSZ_VGA         0xA0
-#define HSZ_QVGA        0x50
-
-/* VSTART */
-#define VST_VGA         0x07
-#define VST_QVGA        0x03
-
-/* VSIZE */
-#define VSZ_VGA         0xF0
-#define VSZ_QVGA        0x78
-
-/* HOUTSIZE */
-#define HOSZ_VGA        0xA0
-#define HOSZ_QVGA       0x50
-
-/* VOUTSIZE */
-#define VOSZ_VGA        0xF0
-#define VOSZ_QVGA       0x78
+/* DSP_CTRL4 */
+#define DSP_OFMT_YUV   0x00
+#define DSP_OFMT_RGB   0x00
+#define DSP_OFMT_RAW8  0x02
+#define DSP_OFMT_RAW10 0x03
 
 /* DSPAUTO (DSP Auto Function ON/OFF Control) */
 #define AWB_ACTRL       0x80 /* AWB auto threshold control */
 #define SCAL0_ACTRL     0x08 /* Auto scaling factor control */
 #define SCAL1_2_ACTRL   0x04 /* Auto scaling factor control */
 
+#define VGA_WIDTH              640
+#define VGA_HEIGHT             480
+#define QVGA_WIDTH             320
+#define QVGA_HEIGHT            240
+#define OV772X_MAX_WIDTH       VGA_WIDTH
+#define OV772X_MAX_HEIGHT      VGA_HEIGHT
+
 /*
  * ID
  */
 /*
  * struct
  */
-struct regval_list {
-       unsigned char reg_num;
-       unsigned char value;
-};
 
 struct ov772x_color_format {
        enum v4l2_mbus_pixelcode code;
        enum v4l2_colorspace colorspace;
        u8 dsp3;
+       u8 dsp4;
        u8 com3;
        u8 com7;
 };
 
 struct ov772x_win_size {
        char                     *name;
-       __u32                     width;
-       __u32                     height;
        unsigned char             com7_bit;
-       const struct regval_list *regs;
+       struct v4l2_rect          rect;
 };
 
 struct ov772x_priv {
@@ -413,31 +406,6 @@ struct ov772x_priv {
        unsigned short                    band_filter;
 };
 
-#define ENDMARKER { 0xff, 0xff }
-
-/*
- * register setting for window size
- */
-static const struct regval_list ov772x_qvga_regs[] = {
-       { HSTART,   HST_QVGA },
-       { HSIZE,    HSZ_QVGA },
-       { VSTART,   VST_QVGA },
-       { VSIZE,    VSZ_QVGA  },
-       { HOUTSIZE, HOSZ_QVGA },
-       { VOUTSIZE, VOSZ_QVGA },
-       ENDMARKER,
-};
-
-static const struct regval_list ov772x_vga_regs[] = {
-       { HSTART,   HST_VGA },
-       { HSIZE,    HSZ_VGA },
-       { VSTART,   VST_VGA },
-       { VSIZE,    VSZ_VGA },
-       { HOUTSIZE, HOSZ_VGA },
-       { VOUTSIZE, VOSZ_VGA },
-       ENDMARKER,
-};
-
 /*
  * supported color format list
  */
@@ -446,6 +414,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_YUYV8_2X8,
                .colorspace     = V4L2_COLORSPACE_JPEG,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = SWAP_YUV,
                .com7           = OFMT_YUV,
        },
@@ -453,6 +422,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_YVYU8_2X8,
                .colorspace     = V4L2_COLORSPACE_JPEG,
                .dsp3           = UV_ON,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = SWAP_YUV,
                .com7           = OFMT_YUV,
        },
@@ -460,6 +430,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_UYVY8_2X8,
                .colorspace     = V4L2_COLORSPACE_JPEG,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = 0x0,
                .com7           = OFMT_YUV,
        },
@@ -467,6 +438,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_RGB555_2X8_PADHI_LE,
                .colorspace     = V4L2_COLORSPACE_SRGB,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = SWAP_RGB,
                .com7           = FMT_RGB555 | OFMT_RGB,
        },
@@ -474,6 +446,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_RGB555_2X8_PADHI_BE,
                .colorspace     = V4L2_COLORSPACE_SRGB,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = 0x0,
                .com7           = FMT_RGB555 | OFMT_RGB,
        },
@@ -481,6 +454,7 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_RGB565_2X8_LE,
                .colorspace     = V4L2_COLORSPACE_SRGB,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = SWAP_RGB,
                .com7           = FMT_RGB565 | OFMT_RGB,
        },
@@ -488,82 +462,94 @@ static const struct ov772x_color_format ov772x_cfmts[] = {
                .code           = V4L2_MBUS_FMT_RGB565_2X8_BE,
                .colorspace     = V4L2_COLORSPACE_SRGB,
                .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_YUV,
                .com3           = 0x0,
                .com7           = FMT_RGB565 | OFMT_RGB,
        },
+       {
+               /* Setting DSP4 to DSP_OFMT_RAW8 still gives 10-bit output,
+                * regardless of the COM7 value. We can thus only support 10-bit
+                * Bayer until someone figures it out.
+                */
+               .code           = V4L2_MBUS_FMT_SBGGR10_1X10,
+               .colorspace     = V4L2_COLORSPACE_SRGB,
+               .dsp3           = 0x0,
+               .dsp4           = DSP_OFMT_RAW10,
+               .com3           = 0x0,
+               .com7           = SENSOR_RAW | OFMT_BRAW,
+       },
 };
 
 
 /*
  * window size list
  */
-#define VGA_WIDTH   640
-#define VGA_HEIGHT  480
-#define QVGA_WIDTH  320
-#define QVGA_HEIGHT 240
-#define MAX_WIDTH   VGA_WIDTH
-#define MAX_HEIGHT  VGA_HEIGHT
-
-static const struct ov772x_win_size ov772x_win_vga = {
-       .name     = "VGA",
-       .width    = VGA_WIDTH,
-       .height   = VGA_HEIGHT,
-       .com7_bit = SLCT_VGA,
-       .regs     = ov772x_vga_regs,
-};
 
-static const struct ov772x_win_size ov772x_win_qvga = {
-       .name     = "QVGA",
-       .width    = QVGA_WIDTH,
-       .height   = QVGA_HEIGHT,
-       .com7_bit = SLCT_QVGA,
-       .regs     = ov772x_qvga_regs,
+static const struct ov772x_win_size ov772x_win_sizes[] = {
+       {
+               .name     = "VGA",
+               .com7_bit = SLCT_VGA,
+               .rect = {
+                       .left = 140,
+                       .top = 14,
+                       .width = VGA_WIDTH,
+                       .height = VGA_HEIGHT,
+               },
+       }, {
+               .name     = "QVGA",
+               .com7_bit = SLCT_QVGA,
+               .rect = {
+                       .left = 252,
+                       .top = 6,
+                       .width = QVGA_WIDTH,
+                       .height = QVGA_HEIGHT,
+               },
+       },
 };
 
 /*
  * general function
  */
 
-static struct ov772x_priv *to_ov772x(const struct i2c_client *client)
+static struct ov772x_priv *to_ov772x(struct v4l2_subdev *sd)
 {
-       return container_of(i2c_get_clientdata(client), struct ov772x_priv,
-                           subdev);
+       return container_of(sd, struct ov772x_priv, subdev);
 }
 
-static int ov772x_write_array(struct i2c_client        *client,
-                             const struct regval_list *vals)
+static inline int ov772x_read(struct i2c_client *client, u8 addr)
 {
-       while (vals->reg_num != 0xff) {
-               int ret = i2c_smbus_write_byte_data(client,
-                                                   vals->reg_num,
-                                                   vals->value);
-               if (ret < 0)
-                       return ret;
-               vals++;
-       }
-       return 0;
+       return i2c_smbus_read_byte_data(client, addr);
+}
+
+static inline int ov772x_write(struct i2c_client *client, u8 addr, u8 value)
+{
+       return i2c_smbus_write_byte_data(client, addr, value);
 }
 
-static int ov772x_mask_set(struct i2c_client *client,
-                                         u8  command,
-                                         u8  mask,
-                                         u8  set)
+static int ov772x_mask_set(struct i2c_client *client, u8  command, u8  mask,
+                          u8  set)
 {
-       s32 val = i2c_smbus_read_byte_data(client, command);
+       s32 val = ov772x_read(client, command);
        if (val < 0)
                return val;
 
        val &= ~mask;
        val |= set & mask;
 
-       return i2c_smbus_write_byte_data(client, command, val);
+       return ov772x_write(client, command, val);
 }
 
 static int ov772x_reset(struct i2c_client *client)
 {
-       int ret = i2c_smbus_write_byte_data(client, COM7, SCCB_RESET);
+       int ret;
+
+       ret = ov772x_write(client, COM7, SCCB_RESET);
+       if (ret < 0)
+               return ret;
+
        msleep(1);
-       return ret;
+
+       return ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
 }
 
 /*
@@ -573,18 +559,13 @@ static int ov772x_reset(struct i2c_client *client)
 static int ov772x_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
+       struct ov772x_priv *priv = to_ov772x(sd);
 
        if (!enable) {
                ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, SOFT_SLEEP_MODE);
                return 0;
        }
 
-       if (!priv->win || !priv->cfmt) {
-               dev_err(&client->dev, "norm or win select error\n");
-               return -EPERM;
-       }
-
        ov772x_mask_set(client, COM2, SOFT_SLEEP_MODE, 0);
 
        dev_dbg(&client->dev, "format %d, win %s\n",
@@ -642,7 +623,7 @@ static int ov772x_s_ctrl(struct v4l2_ctrl *ctrl)
 static int ov772x_g_chip_ident(struct v4l2_subdev *sd,
                               struct v4l2_dbg_chip_ident *id)
 {
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
+       struct ov772x_priv *priv = to_ov772x(sd);
 
        id->ident    = priv->model;
        id->revision = 0;
@@ -661,7 +642,7 @@ static int ov772x_g_register(struct v4l2_subdev *sd,
        if (reg->reg > 0xff)
                return -EINVAL;
 
-       ret = i2c_smbus_read_byte_data(client, reg->reg);
+       ret = ov772x_read(client, reg->reg);
        if (ret < 0)
                return ret;
 
@@ -679,54 +660,63 @@ static int ov772x_s_register(struct v4l2_subdev *sd,
            reg->val > 0xff)
                return -EINVAL;
 
-       return i2c_smbus_write_byte_data(client, reg->reg, reg->val);
+       return ov772x_write(client, reg->reg, reg->val);
 }
 #endif
 
-static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
+static int ov772x_s_power(struct v4l2_subdev *sd, int on)
 {
-       __u32 diff;
-       const struct ov772x_win_size *win;
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
 
-       /* default is QVGA */
-       diff = abs(width - ov772x_win_qvga.width) +
-               abs(height - ov772x_win_qvga.height);
-       win = &ov772x_win_qvga;
+       return soc_camera_set_power(&client->dev, icl, on);
+}
 
-       /* VGA */
-       if (diff >
-           abs(width  - ov772x_win_vga.width) +
-           abs(height - ov772x_win_vga.height))
-               win = &ov772x_win_vga;
+static const struct ov772x_win_size *ov772x_select_win(u32 width, u32 height)
+{
+       const struct ov772x_win_size *win = &ov772x_win_sizes[0];
+       u32 best_diff = UINT_MAX;
+       unsigned int i;
+
+       for (i = 0; i < ARRAY_SIZE(ov772x_win_sizes); ++i) {
+               u32 diff = abs(width - ov772x_win_sizes[i].rect.width)
+                        + abs(height - ov772x_win_sizes[i].rect.height);
+               if (diff < best_diff) {
+                       best_diff = diff;
+                       win = &ov772x_win_sizes[i];
+               }
+       }
 
        return win;
 }
 
-static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
-                            enum v4l2_mbus_pixelcode code)
+static void ov772x_select_params(const struct v4l2_mbus_framefmt *mf,
+                                const struct ov772x_color_format **cfmt,
+                                const struct ov772x_win_size **win)
 {
-       struct ov772x_priv *priv = to_ov772x(client);
-       int ret = -EINVAL;
-       u8  val;
-       int i;
+       unsigned int i;
+
+       /* Select a format. */
+       *cfmt = &ov772x_cfmts[0];
 
-       /*
-        * select format
-        */
-       priv->cfmt = NULL;
        for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++) {
-               if (code == ov772x_cfmts[i].code) {
-                       priv->cfmt = ov772x_cfmts + i;
+               if (mf->code == ov772x_cfmts[i].code) {
+                       *cfmt = &ov772x_cfmts[i];
                        break;
                }
        }
-       if (!priv->cfmt)
-               goto ov772x_set_fmt_error;
 
-       /*
-        * select win
-        */
-       priv->win = ov772x_select_win(*width, *height);
+       /* Select a window size. */
+       *win = ov772x_select_win(mf->width, mf->height);
+}
+
+static int ov772x_set_params(struct ov772x_priv *priv,
+                            const struct ov772x_color_format *cfmt,
+                            const struct ov772x_win_size *win)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(&priv->subdev);
+       int ret;
+       u8  val;
 
        /*
         * reset hardware
@@ -780,17 +770,42 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
                        goto ov772x_set_fmt_error;
        }
 
-       /*
-        * set size format
-        */
-       ret = ov772x_write_array(client, priv->win->regs);
+       /* Format and window size */
+       ret = ov772x_write(client, HSTART, win->rect.left >> 2);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, HSIZE, win->rect.width >> 2);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, VSTART, win->rect.top >> 1);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, VSIZE, win->rect.height >> 1);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, HOUTSIZE, win->rect.width >> 2);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, VOUTSIZE, win->rect.height >> 1);
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, HREF,
+                          ((win->rect.top & 1) << HREF_VSTART_SHIFT) |
+                          ((win->rect.left & 3) << HREF_HSTART_SHIFT) |
+                          ((win->rect.height & 1) << HREF_VSIZE_SHIFT) |
+                          ((win->rect.width & 3) << HREF_HSIZE_SHIFT));
+       if (ret < 0)
+               goto ov772x_set_fmt_error;
+       ret = ov772x_write(client, EXHCH,
+                          ((win->rect.height & 1) << EXHCH_VSIZE_SHIFT) |
+                          ((win->rect.width & 3) << EXHCH_HSIZE_SHIFT));
        if (ret < 0)
                goto ov772x_set_fmt_error;
 
        /*
         * set DSP_CTRL3
         */
-       val = priv->cfmt->dsp3;
+       val = cfmt->dsp3;
        if (val) {
                ret = ov772x_mask_set(client,
                                      DSP_CTRL3, UV_MASK, val);
@@ -798,10 +813,17 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
                        goto ov772x_set_fmt_error;
        }
 
+       /* DSP_CTRL4: AEC reference point and DSP output format. */
+       if (cfmt->dsp4) {
+               ret = ov772x_write(client, DSP_CTRL4, cfmt->dsp4);
+               if (ret < 0)
+                       goto ov772x_set_fmt_error;
+       }
+
        /*
         * set COM3
         */
-       val = priv->cfmt->com3;
+       val = cfmt->com3;
        if (priv->info->flags & OV772X_FLAG_VFLIP)
                val |= VFLIP_IMG;
        if (priv->info->flags & OV772X_FLAG_HFLIP)
@@ -816,13 +838,8 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
        if (ret < 0)
                goto ov772x_set_fmt_error;
 
-       /*
-        * set COM7
-        */
-       val = priv->win->com7_bit | priv->cfmt->com7;
-       ret = ov772x_mask_set(client,
-                             COM7, SLCT_MASK | FMT_MASK | OFMT_MASK,
-                             val);
+       /* COM7: Sensor resolution and output format control. */
+       ret = ov772x_write(client, COM7, win->com7_bit | cfmt->com7);
        if (ret < 0)
                goto ov772x_set_fmt_error;
 
@@ -838,16 +855,11 @@ static int ov772x_set_params(struct i2c_client *client, u32 *width, u32 *height,
                        goto ov772x_set_fmt_error;
        }
 
-       *width = priv->win->width;
-       *height = priv->win->height;
-
        return ret;
 
 ov772x_set_fmt_error:
 
        ov772x_reset(client);
-       priv->win = NULL;
-       priv->cfmt = NULL;
 
        return ret;
 }
@@ -867,8 +879,8 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 {
        a->bounds.left                  = 0;
        a->bounds.top                   = 0;
-       a->bounds.width                 = VGA_WIDTH;
-       a->bounds.height                = VGA_HEIGHT;
+       a->bounds.width                 = OV772X_MAX_WIDTH;
+       a->bounds.height                = OV772X_MAX_HEIGHT;
        a->defrect                      = a->bounds;
        a->type                         = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        a->pixelaspect.numerator        = 1;
@@ -880,15 +892,10 @@ static int ov772x_cropcap(struct v4l2_subdev *sd, struct v4l2_cropcap *a)
 static int ov772x_g_fmt(struct v4l2_subdev *sd,
                        struct v4l2_mbus_framefmt *mf)
 {
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
-
-       if (!priv->win || !priv->cfmt) {
-               priv->cfmt = &ov772x_cfmts[0];
-               priv->win = ov772x_select_win(VGA_WIDTH, VGA_HEIGHT);
-       }
+       struct ov772x_priv *priv = to_ov772x(sd);
 
-       mf->width       = priv->win->width;
-       mf->height      = priv->win->height;
+       mf->width       = priv->win->rect.width;
+       mf->height      = priv->win->rect.height;
        mf->code        = priv->cfmt->code;
        mf->colorspace  = priv->cfmt->colorspace;
        mf->field       = V4L2_FIELD_NONE;
@@ -896,70 +903,64 @@ static int ov772x_g_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int ov772x_s_fmt(struct v4l2_subdev *sd,
-                       struct v4l2_mbus_framefmt *mf)
+static int ov772x_s_fmt(struct v4l2_subdev *sd, struct v4l2_mbus_framefmt *mf)
 {
-       struct i2c_client *client = v4l2_get_subdevdata(sd);
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
-       int ret = ov772x_set_params(client, &mf->width, &mf->height,
-                                   mf->code);
+       struct ov772x_priv *priv = to_ov772x(sd);
+       const struct ov772x_color_format *cfmt;
+       const struct ov772x_win_size *win;
+       int ret;
 
-       if (!ret)
-               mf->colorspace = priv->cfmt->colorspace;
+       ov772x_select_params(mf, &cfmt, &win);
 
-       return ret;
+       ret = ov772x_set_params(priv, cfmt, win);
+       if (ret < 0)
+               return ret;
+
+       priv->win = win;
+       priv->cfmt = cfmt;
+
+       mf->code = cfmt->code;
+       mf->width = win->rect.width;
+       mf->height = win->rect.height;
+       mf->field = V4L2_FIELD_NONE;
+       mf->colorspace = cfmt->colorspace;
+
+       return 0;
 }
 
 static int ov772x_try_fmt(struct v4l2_subdev *sd,
                          struct v4l2_mbus_framefmt *mf)
 {
-       struct ov772x_priv *priv = container_of(sd, struct ov772x_priv, subdev);
+       const struct ov772x_color_format *cfmt;
        const struct ov772x_win_size *win;
-       int i;
 
-       /*
-        * select suitable win
-        */
-       win = ov772x_select_win(mf->width, mf->height);
+       ov772x_select_params(mf, &cfmt, &win);
 
-       mf->width       = win->width;
-       mf->height      = win->height;
-       mf->field       = V4L2_FIELD_NONE;
-
-       for (i = 0; i < ARRAY_SIZE(ov772x_cfmts); i++)
-               if (mf->code == ov772x_cfmts[i].code)
-                       break;
-
-       if (i == ARRAY_SIZE(ov772x_cfmts)) {
-               /* Unsupported format requested. Propose either */
-               if (priv->cfmt) {
-                       /* the current one or */
-                       mf->colorspace = priv->cfmt->colorspace;
-                       mf->code = priv->cfmt->code;
-               } else {
-                       /* the default one */
-                       mf->colorspace = ov772x_cfmts[0].colorspace;
-                       mf->code = ov772x_cfmts[0].code;
-               }
-       } else {
-               /* Also return the colorspace */
-               mf->colorspace  = ov772x_cfmts[i].colorspace;
-       }
+       mf->code = cfmt->code;
+       mf->width = win->rect.width;
+       mf->height = win->rect.height;
+       mf->field = V4L2_FIELD_NONE;
+       mf->colorspace = cfmt->colorspace;
 
        return 0;
 }
 
-static int ov772x_video_probe(struct i2c_client *client)
+static int ov772x_video_probe(struct ov772x_priv *priv)
 {
-       struct ov772x_priv *priv = to_ov772x(client);
+       struct i2c_client  *client = v4l2_get_subdevdata(&priv->subdev);
        u8                  pid, ver;
        const char         *devname;
+       int                 ret;
+
+       ret = ov772x_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
 
        /*
         * check and show product ID and manufacturer ID
         */
-       pid = i2c_smbus_read_byte_data(client, PID);
-       ver = i2c_smbus_read_byte_data(client, VER);
+       pid = ov772x_read(client, PID);
+       ver = ov772x_read(client, VER);
 
        switch (VERSION(pid, ver)) {
        case OV7720:
@@ -973,7 +974,8 @@ static int ov772x_video_probe(struct i2c_client *client)
        default:
                dev_err(&client->dev,
                        "Product ID error %x:%x\n", pid, ver);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev,
@@ -981,9 +983,13 @@ static int ov772x_video_probe(struct i2c_client *client)
                 devname,
                 pid,
                 ver,
-                i2c_smbus_read_byte_data(client, MIDH),
-                i2c_smbus_read_byte_data(client, MIDL));
-       return v4l2_ctrl_handler_setup(&priv->hdl);
+                ov772x_read(client, MIDH),
+                ov772x_read(client, MIDL));
+       ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+       ov772x_s_power(&priv->subdev, 0);
+       return ret;
 }
 
 static const struct v4l2_ctrl_ops ov772x_ctrl_ops = {
@@ -996,6 +1002,7 @@ static struct v4l2_subdev_core_ops ov772x_subdev_core_ops = {
        .g_register     = ov772x_g_register,
        .s_register     = ov772x_s_register,
 #endif
+       .s_power        = ov772x_s_power,
 };
 
 static int ov772x_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
@@ -1079,24 +1086,28 @@ static int ov772x_probe(struct i2c_client *client,
                        V4L2_CID_BAND_STOP_FILTER, 0, 256, 1, 0);
        priv->subdev.ctrl_handler = &priv->hdl;
        if (priv->hdl.error) {
-               int err = priv->hdl.error;
-
-               kfree(priv);
-               return err;
+               ret = priv->hdl.error;
+               goto done;
        }
 
-       ret = ov772x_video_probe(client);
+       ret = ov772x_video_probe(priv);
+       if (ret < 0)
+               goto done;
+
+       priv->cfmt = &ov772x_cfmts[0];
+       priv->win = &ov772x_win_sizes[0];
+
+done:
        if (ret) {
                v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
        }
-
        return ret;
 }
 
 static int ov772x_remove(struct i2c_client *client)
 {
-       struct ov772x_priv *priv = to_ov772x(client);
+       struct ov772x_priv *priv = to_ov772x(i2c_get_clientdata(client));
 
        v4l2_device_unregister_subdev(&priv->subdev);
        v4l2_ctrl_handler_free(&priv->hdl);
similarity index 97%
rename from drivers/media/video/ov9640.c
rename to drivers/media/i2c/soc_camera/ov9640.c
index 9ed4ba4236c47e4adf9920e7a88f974b513f3fc0..b323684eaf77e445555c1ab90dfaacb154144491 100644 (file)
@@ -333,6 +333,14 @@ static int ov9640_set_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int ov9640_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 /* select nearest higher resolution for capture */
 static void ov9640_res_roundup(u32 *width, u32 *height)
 {
@@ -584,7 +592,11 @@ static int ov9640_video_probe(struct i2c_client *client)
        struct ov9640_priv *priv = to_ov9640_sensor(sd);
        u8              pid, ver, midh, midl;
        const char      *devname;
-       int             ret = 0;
+       int             ret;
+
+       ret = ov9640_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
 
        /*
         * check and show product ID and manufacturer ID
@@ -598,7 +610,7 @@ static int ov9640_video_probe(struct i2c_client *client)
        if (!ret)
                ret = ov9640_reg_read(client, OV9640_MIDL, &midl);
        if (ret)
-               return ret;
+               goto done;
 
        switch (VERSION(pid, ver)) {
        case OV9640_V2:
@@ -613,13 +625,18 @@ static int ov9640_video_probe(struct i2c_client *client)
                break;
        default:
                dev_err(&client->dev, "Product ID error %x:%x\n", pid, ver);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev, "%s Product ID %0x:%0x Manufacturer ID %x:%x\n",
                 devname, pid, ver, midh, midl);
 
-       return v4l2_ctrl_handler_setup(&priv->hdl);
+       ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+       ov9640_s_power(&priv->subdev, 0);
+       return ret;
 }
 
 static const struct v4l2_ctrl_ops ov9640_ctrl_ops = {
@@ -632,7 +649,7 @@ static struct v4l2_subdev_core_ops ov9640_core_ops = {
        .g_register             = ov9640_get_register,
        .s_register             = ov9640_set_register,
 #endif
-
+       .s_power                = ov9640_s_power,
 };
 
 /* Request bus settings on camera side */
similarity index 97%
rename from drivers/media/video/ov9740.c
rename to drivers/media/i2c/soc_camera/ov9740.c
index 3eb07c22516e6b9b46e8e2d3257f58f5532436f0..7a55889e397b3be3334cd9b7dd85e7045e6e17c8 100644 (file)
@@ -786,17 +786,27 @@ static int ov9740_g_chip_ident(struct v4l2_subdev *sd,
 
 static int ov9740_s_power(struct v4l2_subdev *sd, int on)
 {
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
        struct ov9740_priv *priv = to_ov9740(sd);
-
-       if (!priv->current_enable)
-               return 0;
+       int ret;
 
        if (on) {
-               ov9740_s_fmt(sd, &priv->current_mf);
-               ov9740_s_stream(sd, priv->current_enable);
+               ret = soc_camera_power_on(&client->dev, icl);
+               if (ret < 0)
+                       return ret;
+
+               if (priv->current_enable) {
+                       ov9740_s_fmt(sd, &priv->current_mf);
+                       ov9740_s_stream(sd, 1);
+               }
        } else {
-               ov9740_s_stream(sd, 0);
-               priv->current_enable = true;
+               if (priv->current_enable) {
+                       ov9740_s_stream(sd, 0);
+                       priv->current_enable = true;
+               }
+
+               soc_camera_power_off(&client->dev, icl);
        }
 
        return 0;
@@ -843,34 +853,38 @@ static int ov9740_video_probe(struct i2c_client *client)
        u8 modelhi, modello;
        int ret;
 
+       ret = ov9740_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /*
         * check and show product ID and manufacturer ID
         */
        ret = ov9740_reg_read(client, OV9740_MODEL_ID_HI, &modelhi);
        if (ret < 0)
-               goto err;
+               goto done;
 
        ret = ov9740_reg_read(client, OV9740_MODEL_ID_LO, &modello);
        if (ret < 0)
-               goto err;
+               goto done;
 
        priv->model = (modelhi << 8) | modello;
 
        ret = ov9740_reg_read(client, OV9740_REVISION_NUMBER, &priv->revision);
        if (ret < 0)
-               goto err;
+               goto done;
 
        ret = ov9740_reg_read(client, OV9740_MANUFACTURER_ID, &priv->manid);
        if (ret < 0)
-               goto err;
+               goto done;
 
        ret = ov9740_reg_read(client, OV9740_SMIA_VERSION, &priv->smiaver);
        if (ret < 0)
-               goto err;
+               goto done;
 
        if (priv->model != 0x9740) {
                ret = -ENODEV;
-               goto err;
+               goto done;
        }
 
        priv->ident = V4L2_IDENT_OV9740;
@@ -879,7 +893,10 @@ static int ov9740_video_probe(struct i2c_client *client)
                 "Manufacturer 0x%02x, SMIA Version 0x%02x\n",
                 priv->model, priv->revision, priv->manid, priv->smiaver);
 
-err:
+       ret = v4l2_ctrl_handler_setup(&priv->hdl);
+
+done:
+       ov9740_s_power(&priv->subdev, 0);
        return ret;
 }
 
@@ -963,8 +980,6 @@ static int ov9740_probe(struct i2c_client *client,
        }
 
        ret = ov9740_video_probe(client);
-       if (!ret)
-               ret = v4l2_ctrl_handler_setup(&priv->hdl);
        if (ret < 0) {
                v4l2_ctrl_handler_free(&priv->hdl);
                kfree(priv);
similarity index 98%
rename from drivers/media/video/rj54n1cb0c.c
rename to drivers/media/i2c/soc_camera/rj54n1cb0c.c
index f6419b22c258061bb6eeb10a8f3593ebab677d06..02f0400051d9255a72a52e702bd7eacebc63261b 100644 (file)
@@ -536,11 +536,11 @@ static int rj54n1_commit(struct i2c_client *client)
 static int rj54n1_sensor_scale(struct v4l2_subdev *sd, s32 *in_w, s32 *in_h,
                               s32 *out_w, s32 *out_h);
 
-static int rj54n1_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int rj54n1_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
        struct rj54n1 *rj54n1 = to_rj54n1(client);
-       struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &a->c;
        int dummy = 0, output_w, output_h,
                input_w = rect->width, input_h = rect->height;
        int ret;
@@ -1180,6 +1180,14 @@ static int rj54n1_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int rj54n1_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int rj54n1_s_ctrl(struct v4l2_ctrl *ctrl)
 {
        struct rj54n1 *rj54n1 = container_of(ctrl->handler, struct rj54n1, hdl);
@@ -1230,6 +1238,7 @@ static struct v4l2_subdev_core_ops rj54n1_subdev_core_ops = {
        .g_register     = rj54n1_g_register,
        .s_register     = rj54n1_s_register,
 #endif
+       .s_power        = rj54n1_s_power,
 };
 
 static int rj54n1_g_mbus_config(struct v4l2_subdev *sd,
@@ -1287,9 +1296,14 @@ static struct v4l2_subdev_ops rj54n1_subdev_ops = {
 static int rj54n1_video_probe(struct i2c_client *client,
                              struct rj54n1_pdata *priv)
 {
+       struct rj54n1 *rj54n1 = to_rj54n1(client);
        int data1, data2;
        int ret;
 
+       ret = rj54n1_s_power(&rj54n1->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /* Read out the chip version register */
        data1 = reg_read(client, RJ54N1_DEV_CODE);
        data2 = reg_read(client, RJ54N1_DEV_CODE2);
@@ -1298,18 +1312,21 @@ static int rj54n1_video_probe(struct i2c_client *client,
                ret = -ENODEV;
                dev_info(&client->dev, "No RJ54N1CB0C found, read 0x%x:0x%x\n",
                         data1, data2);
-               goto ei2c;
+               goto done;
        }
 
        /* Configure IOCTL polarity from the platform data: 0 or 1 << 7. */
        ret = reg_write(client, RJ54N1_IOC, priv->ioctl_high << 7);
        if (ret < 0)
-               goto ei2c;
+               goto done;
 
        dev_info(&client->dev, "Detected a RJ54N1CB0C chip ID 0x%x:0x%x\n",
                 data1, data2);
 
-ei2c:
+       ret = v4l2_ctrl_handler_setup(&rj54n1->hdl);
+
+done:
+       rj54n1_s_power(&rj54n1->subdev, 0);
        return ret;
 }
 
@@ -1373,9 +1390,9 @@ static int rj54n1_probe(struct i2c_client *client,
        if (ret < 0) {
                v4l2_ctrl_handler_free(&rj54n1->hdl);
                kfree(rj54n1);
-               return ret;
        }
-       return v4l2_ctrl_handler_setup(&rj54n1->hdl);
+
+       return ret;
 }
 
 static int rj54n1_remove(struct i2c_client *client)
similarity index 98%
rename from drivers/media/video/tw9910.c
rename to drivers/media/i2c/soc_camera/tw9910.c
index 9f53eacb66e3cd89a75f14ec08b0ced3ea752385..140716e71a158d69c23a82c670bd8387b2a632a8 100644 (file)
@@ -566,6 +566,14 @@ static int tw9910_s_register(struct v4l2_subdev *sd,
 }
 #endif
 
+static int tw9910_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
+       struct soc_camera_link *icl = soc_camera_i2c_to_link(client);
+
+       return soc_camera_set_power(&client->dev, icl, on);
+}
+
 static int tw9910_set_frame(struct v4l2_subdev *sd, u32 *width, u32 *height)
 {
        struct i2c_client *client = v4l2_get_subdevdata(sd);
@@ -772,6 +780,7 @@ static int tw9910_video_probe(struct i2c_client *client)
 {
        struct tw9910_priv *priv = to_tw9910(client);
        s32 id;
+       int ret;
 
        /*
         * tw9910 only use 8 or 16 bit bus width
@@ -782,6 +791,10 @@ static int tw9910_video_probe(struct i2c_client *client)
                return -ENODEV;
        }
 
+       ret = tw9910_s_power(&priv->subdev, 1);
+       if (ret < 0)
+               return ret;
+
        /*
         * check and show Product ID
         * So far only revisions 0 and 1 have been seen
@@ -795,7 +808,8 @@ static int tw9910_video_probe(struct i2c_client *client)
                dev_err(&client->dev,
                        "Product ID error %x:%x\n",
                        id, priv->revision);
-               return -ENODEV;
+               ret = -ENODEV;
+               goto done;
        }
 
        dev_info(&client->dev,
@@ -803,7 +817,9 @@ static int tw9910_video_probe(struct i2c_client *client)
 
        priv->norm = V4L2_STD_NTSC;
 
-       return 0;
+done:
+       tw9910_s_power(&priv->subdev, 0);
+       return ret;
 }
 
 static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
@@ -814,6 +830,7 @@ static struct v4l2_subdev_core_ops tw9910_subdev_core_ops = {
        .g_register     = tw9910_g_register,
        .s_register     = tw9910_s_register,
 #endif
+       .s_power        = tw9910_s_power,
 };
 
 static int tw9910_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
similarity index 99%
rename from drivers/media/video/tcm825x.c
rename to drivers/media/i2c/tcm825x.c
index 462caa44ae001c1a802fe8ca48f46052bcd59917..9252529fc5ddd69f7bd9aa8ff8e20072cb111aab 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/tcm825x.c
+ * drivers/media/i2c/tcm825x.c
  *
  * TCM825X camera sensor driver.
  *
similarity index 99%
rename from drivers/media/video/tcm825x.h
rename to drivers/media/i2c/tcm825x.h
index 5b7e69682368c6189a2965386ced056e7ba5ac48..8ebab953963f869b5f63ea4e8686def0e5e9f573 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/tcm825x.h
+ * drivers/media/i2c/tcm825x.h
  *
  * Register definitions for the TCM825X CameraChip.
  *
similarity index 99%
rename from drivers/media/video/tea6415c.c
rename to drivers/media/i2c/tea6415c.c
index d1d6ea1dd2739140cb7c456f9c14c13b70a87458..3d5b06a5c308c9db906b995bea7830093cdeb655 100644 (file)
@@ -81,7 +81,7 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd,
        case 13:
                byte = 0x28;
                break;
-       };
+       }
 
        switch (i) {
        case 5:
@@ -108,7 +108,7 @@ static int tea6415c_s_routing(struct v4l2_subdev *sd,
        case 11:
                byte |= 0x07;
                break;
-       };
+       }
 
        ret = i2c_smbus_write_byte(client, byte);
        if (ret) {
similarity index 54%
rename from drivers/media/video/ths7303.c
rename to drivers/media/i2c/ths7303.c
index e5c0eedebc58b5129bbaf0bedd3b97d81ada4a19..c31cc04fffd282a6194ff7cb1d90bfb3a4634a2a 100644 (file)
 #include <media/v4l2-subdev.h>
 #include <media/v4l2-chip-ident.h>
 
+#define THS7303_CHANNEL_1      1
+#define THS7303_CHANNEL_2      2
+#define THS7303_CHANNEL_3      3
+
+enum ths7303_filter_mode {
+       THS7303_FILTER_MODE_480I_576I,
+       THS7303_FILTER_MODE_480P_576P,
+       THS7303_FILTER_MODE_720P_1080I,
+       THS7303_FILTER_MODE_1080P,
+       THS7303_FILTER_MODE_DISABLE
+};
+
 MODULE_DESCRIPTION("TI THS7303 video amplifier driver");
 MODULE_AUTHOR("Chaithrika U S");
 MODULE_LICENSE("GPL");
@@ -37,35 +49,96 @@ module_param(debug, int, 0644);
 MODULE_PARM_DESC(debug, "Debug level 0-1");
 
 /* following function is used to set ths7303 */
-static int ths7303_setvalue(struct v4l2_subdev *sd, v4l2_std_id std)
+int ths7303_setval(struct v4l2_subdev *sd, enum ths7303_filter_mode mode)
 {
+       u8 input_bias_chroma = 3;
+       u8 input_bias_luma = 3;
+       int disable = 0;
        int err = 0;
-       u8 val;
-       struct i2c_client *client;
+       u8 val = 0;
+       u8 temp;
 
-       client = v4l2_get_subdevdata(sd);
+       struct i2c_client *client = v4l2_get_subdevdata(sd);
 
-       if (std & (V4L2_STD_ALL & ~V4L2_STD_SECAM)) {
-               val = 0x02;
-               v4l2_dbg(1, debug, sd, "setting value for SDTV format\n");
-       } else {
-               val = 0x00;
-               v4l2_dbg(1, debug, sd, "disabling all channels\n");
+       if (!client)
+               return -EINVAL;
+
+       switch (mode) {
+       case THS7303_FILTER_MODE_1080P:
+               val = (3 << 6);
+               val |= (3 << 3);
+               break;
+       case THS7303_FILTER_MODE_720P_1080I:
+               val = (2 << 6);
+               val |= (2 << 3);
+               break;
+       case THS7303_FILTER_MODE_480P_576P:
+               val = (1 << 6);
+               val |= (1 << 3);
+               break;
+       case THS7303_FILTER_MODE_480I_576I:
+               break;
+       case THS7303_FILTER_MODE_DISABLE:
+               pr_info("mode disabled\n");
+               /* disable all channels */
+               disable = 1;
+       default:
+               /* disable all channels */
+               disable = 1;
        }
+       /* Setup channel 2 - Luma - Green */
+       temp = val;
+       if (!disable)
+               val |= input_bias_luma;
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_2, val);
+       if (err)
+               goto out;
 
-       err |= i2c_smbus_write_byte_data(client, 0x01, val);
-       err |= i2c_smbus_write_byte_data(client, 0x02, val);
-       err |= i2c_smbus_write_byte_data(client, 0x03, val);
+       /* setup two chroma channels */
+       if (!disable)
+               temp |= input_bias_chroma;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_1, temp);
        if (err)
-               v4l2_err(sd, "write failed\n");
+               goto out;
 
+       err = i2c_smbus_write_byte_data(client, THS7303_CHANNEL_3, temp);
+       if (err)
+               goto out;
+       return err;
+out:
+       pr_info("write byte data failed\n");
        return err;
 }
 
 static int ths7303_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
 {
-       return ths7303_setvalue(sd, norm);
+       if (norm & (V4L2_STD_ALL & ~V4L2_STD_SECAM))
+               return ths7303_setval(sd, THS7303_FILTER_MODE_480I_576I);
+       else
+               return ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+}
+
+/* for setting filter for HD output */
+static int ths7303_s_dv_timings(struct v4l2_subdev *sd,
+                              struct v4l2_dv_timings *dv_timings)
+{
+       u32 height = dv_timings->bt.height;
+       int interlaced = dv_timings->bt.interlaced;
+       int res = 0;
+
+       if (height == 1080 && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_1080P);
+       else if ((height == 720 && !interlaced) ||
+                       (height == 1080 && interlaced))
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_720P_1080I);
+       else if ((height == 480 || height == 576) && !interlaced)
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_480P_576P);
+       else
+               /* disable all channels */
+               res = ths7303_setval(sd, THS7303_FILTER_MODE_DISABLE);
+
+       return res;
 }
 
 static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
@@ -78,6 +151,7 @@ static int ths7303_g_chip_ident(struct v4l2_subdev *sd,
 
 static const struct v4l2_subdev_video_ops ths7303_video_ops = {
        .s_std_output   = ths7303_s_std_output,
+       .s_dv_timings    = ths7303_s_dv_timings,
 };
 
 static const struct v4l2_subdev_core_ops ths7303_core_ops = {
@@ -107,7 +181,7 @@ static int ths7303_probe(struct i2c_client *client,
 
        v4l2_i2c_subdev_init(sd, client, &ths7303_ops);
 
-       return ths7303_setvalue(sd, std_id);
+       return ths7303_s_std_output(sd, std_id);
 }
 
 static int ths7303_remove(struct i2c_client *client)
similarity index 99%
rename from drivers/media/video/tvaudio.c
rename to drivers/media/i2c/tvaudio.c
index 321b3153df87abe1537bab907121d98012d25838..3b24d3fc186647751d94f0b1ba04a3dd23c4d8cf 100644 (file)
@@ -7,6 +7,10 @@
  *   Steve VanDeBogart (vandebo@uclink.berkeley.edu)
  *   Greg Alexander (galexand@acm.org)
  *
+ * For the TDA9875 part:
+ * Copyright (c) 2000 Guillaume Delvit based on Gerd Knorr source
+ * and Eric Sandeen
+ *
  * Copyright(c) 2005-2008 Mauro Carvalho Chehab
  *     - Some cleanups, code fixes, etc
  *     - Convert it to V4L2 API
@@ -217,8 +221,17 @@ static int chip_read2(struct CHIPSTATE *chip, int subaddr)
        unsigned char write[1];
        unsigned char read[1];
        struct i2c_msg msgs[2] = {
-               { c->addr, 0,        1, write },
-               { c->addr, I2C_M_RD, 1, read  }
+               {
+                       .addr = c->addr,
+                       .len = 1,
+                       .buf = write
+               },
+               {
+                       .addr = c->addr,
+                       .flags = I2C_M_RD,
+                       .len = 1,
+                       .buf = read
+               }
        };
 
        write[0] = subaddr;
similarity index 94%
rename from drivers/media/video/tvp514x.c
rename to drivers/media/i2c/tvp514x.c
index cd615c1d6011feaa31405336e13ce07dc0348a2f..d5e10215a28f46197d480aa51156cab605d7ef21 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/tvp514x.c
+ * drivers/media/i2c/tvp514x.c
  *
  * TI TVP5146/47 decoder driver
  *
@@ -519,6 +519,12 @@ static int tvp514x_querystd(struct v4l2_subdev *sd, v4l2_std_id *std_id)
 
        *std_id = V4L2_STD_UNKNOWN;
 
+       /* To query the standard the TVP514x must power on the ADCs. */
+       if (!decoder->streaming) {
+               tvp514x_s_stream(sd, 1);
+               msleep(LOCK_RETRY_DELAY);
+       }
+
        /* query the current standard */
        current_std = tvp514x_query_current_std(sd);
        if (current_std == STD_INVALID)
@@ -625,25 +631,12 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
        int err;
        enum tvp514x_input input_sel;
        enum tvp514x_output output_sel;
-       u8 sync_lock_status, lock_mask;
-       int try_count = LOCK_RETRY_COUNT;
 
        if ((input >= INPUT_INVALID) ||
                        (output >= OUTPUT_INVALID))
                /* Index out of bound */
                return -EINVAL;
 
-       /*
-        * For the sequence streamon -> streamoff and again s_input
-        * it fails to lock the signal, since streamoff puts TVP514x
-        * into power off state which leads to failure in sub-sequent s_input.
-        *
-        * So power up the TVP514x device here, since it is important to lock
-        * the signal at this stage.
-        */
-       if (!decoder->streaming)
-               tvp514x_s_stream(sd, 1);
-
        input_sel = input;
        output_sel = output;
 
@@ -660,64 +653,6 @@ static int tvp514x_s_routing(struct v4l2_subdev *sd,
 
        decoder->tvp514x_regs[REG_INPUT_SEL].val = input_sel;
        decoder->tvp514x_regs[REG_OUTPUT_FORMATTER1].val = output_sel;
-
-       /* Clear status */
-       msleep(LOCK_RETRY_DELAY);
-       err =
-           tvp514x_write_reg(sd, REG_CLEAR_LOST_LOCK, 0x01);
-       if (err)
-               return err;
-
-       switch (input_sel) {
-       case INPUT_CVBS_VI1A:
-       case INPUT_CVBS_VI1B:
-       case INPUT_CVBS_VI1C:
-       case INPUT_CVBS_VI2A:
-       case INPUT_CVBS_VI2B:
-       case INPUT_CVBS_VI2C:
-       case INPUT_CVBS_VI3A:
-       case INPUT_CVBS_VI3B:
-       case INPUT_CVBS_VI3C:
-       case INPUT_CVBS_VI4A:
-               lock_mask = STATUS_CLR_SUBCAR_LOCK_BIT |
-                       STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-
-       case INPUT_SVIDEO_VI2A_VI1A:
-       case INPUT_SVIDEO_VI2B_VI1B:
-       case INPUT_SVIDEO_VI2C_VI1C:
-       case INPUT_SVIDEO_VI2A_VI3A:
-       case INPUT_SVIDEO_VI2B_VI3B:
-       case INPUT_SVIDEO_VI2C_VI3C:
-       case INPUT_SVIDEO_VI4A_VI1A:
-       case INPUT_SVIDEO_VI4A_VI1B:
-       case INPUT_SVIDEO_VI4A_VI1C:
-       case INPUT_SVIDEO_VI4A_VI3A:
-       case INPUT_SVIDEO_VI4A_VI3B:
-       case INPUT_SVIDEO_VI4A_VI3C:
-               lock_mask = STATUS_HORZ_SYNC_LOCK_BIT |
-                       STATUS_VIRT_SYNC_LOCK_BIT;
-               break;
-       /* Need to add other interfaces*/
-       default:
-               return -EINVAL;
-       }
-
-       while (try_count-- > 0) {
-               /* Allow decoder to sync up with new input */
-               msleep(LOCK_RETRY_DELAY);
-
-               sync_lock_status = tvp514x_read_reg(sd,
-                               REG_STATUS1);
-               if (lock_mask == (sync_lock_status & lock_mask))
-                       /* Input detected */
-                       break;
-       }
-
-       if (try_count < 0)
-               return -EINVAL;
-
        decoder->input = input;
        decoder->output = output;
 
similarity index 99%
rename from drivers/media/video/tvp514x_regs.h
rename to drivers/media/i2c/tvp514x_regs.h
index 18f29ad0dfe2cfbe84db9c694ed1a95be87b316b..d23aa2fbb9b1e2f6f540ad7864298a28d4a3b3b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/tvp514x_regs.h
+ * drivers/media/i2c/tvp514x_regs.h
  *
  * Copyright (C) 2008 Texas Instruments Inc
  * Author: Vaibhav Hiremath <hvaibhav@ti.com>
similarity index 99%
rename from drivers/media/video/tvp5150.c
rename to drivers/media/i2c/tvp5150.c
index a751b6c146fdb523a6a8f3c00cdd9edf84f1f716..31104a9606529a1ad57040527e9e3cc53f8361f9 100644 (file)
@@ -865,7 +865,7 @@ static int tvp5150_mbus_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static int tvp5150_s_crop(struct v4l2_subdev *sd, struct v4l2_crop *a)
+static int tvp5150_s_crop(struct v4l2_subdev *sd, const struct v4l2_crop *a)
 {
        struct v4l2_rect rect = a->c;
        struct tvp5150 *decoder = to_tvp5150(sd);
@@ -1020,7 +1020,7 @@ static int tvp5150_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_f
 {
        int i, mask = 0;
 
-       memset(svbi, 0, sizeof(*svbi));
+       memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
 
        for (i = 0; i <= 23; i++) {
                svbi->service_lines[0][i] =
index 6f9eb94e85b387f78f144fd74c244e0e0859237a..d01fcb7e87c2558e1b2c48c504d7dda0efada8df 100644 (file)
@@ -59,7 +59,9 @@ static int media_device_get_info(struct media_device *dev,
        info.hw_revision = dev->hw_revision;
        info.driver_version = dev->driver_version;
 
-       return copy_to_user(__info, &info, sizeof(*__info));
+       if (copy_to_user(__info, &info, sizeof(*__info)))
+               return -EFAULT;
+       return 0;
 }
 
 static struct media_entity *find_entity(struct media_device *mdev, u32 id)
index f6b52d5494309cb0b3829916136d8352fc57adc1..023b2a1cbb9b73ba6829f387f28e85f9f3f72e91 100644 (file)
@@ -30,6 +30,8 @@
  * counting.
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/errno.h>
 #include <linux/init.h>
 #include <linux/module.h>
@@ -215,7 +217,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev)
        minor = find_next_zero_bit(media_devnode_nums, MEDIA_NUM_DEVICES, 0);
        if (minor == MEDIA_NUM_DEVICES) {
                mutex_unlock(&media_devnode_lock);
-               printk(KERN_ERR "could not get a free minor\n");
+               pr_err("could not get a free minor\n");
                return -ENFILE;
        }
 
@@ -230,7 +232,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev)
 
        ret = cdev_add(&mdev->cdev, MKDEV(MAJOR(media_dev_t), mdev->minor), 1);
        if (ret < 0) {
-               printk(KERN_ERR "%s: cdev_add failed\n", __func__);
+               pr_err("%s: cdev_add failed\n", __func__);
                goto error;
        }
 
@@ -243,7 +245,7 @@ int __must_check media_devnode_register(struct media_devnode *mdev)
        dev_set_name(&mdev->dev, "media%d", mdev->minor);
        ret = device_register(&mdev->dev);
        if (ret < 0) {
-               printk(KERN_ERR "%s: device_register failed\n", __func__);
+               pr_err("%s: device_register failed\n", __func__);
                goto error;
        }
 
@@ -287,18 +289,18 @@ static int __init media_devnode_init(void)
 {
        int ret;
 
-       printk(KERN_INFO "Linux media interface: v0.10\n");
+       pr_info("Linux media interface: v0.10\n");
        ret = alloc_chrdev_region(&media_dev_t, 0, MEDIA_NUM_DEVICES,
                                  MEDIA_NAME);
        if (ret < 0) {
-               printk(KERN_WARNING "media: unable to allocate major\n");
+               pr_warn("unable to allocate major\n");
                return ret;
        }
 
        ret = bus_register(&media_bus_type);
        if (ret < 0) {
                unregister_chrdev_region(media_dev_t, MEDIA_NUM_DEVICES);
-               printk(KERN_WARNING "media: bus_register failed\n");
+               pr_warn("bus_register failed\n");
                return -EIO;
        }
 
diff --git a/drivers/media/mmc/Kconfig b/drivers/media/mmc/Kconfig
new file mode 100644 (file)
index 0000000..8c30ada
--- /dev/null
@@ -0,0 +1,2 @@
+comment "Supported MMC/SDIO adapters"
+source "drivers/media/mmc/siano/Kconfig"
diff --git a/drivers/media/mmc/Makefile b/drivers/media/mmc/Makefile
new file mode 100644 (file)
index 0000000..31e297a
--- /dev/null
@@ -0,0 +1 @@
+obj-y += siano/
diff --git a/drivers/media/mmc/siano/Kconfig b/drivers/media/mmc/siano/Kconfig
new file mode 100644 (file)
index 0000000..fa62475
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config SMS_SDIO_DRV
+       tristate "Siano SMS1xxx based MDTV via SDIO interface"
+       depends on DVB_CORE && RC_CORE && HAS_DMA
+       depends on MMC
+       ---help---
+         Choose if you would like to have Siano's support for SDIO interface
diff --git a/drivers/media/mmc/siano/Makefile b/drivers/media/mmc/siano/Makefile
new file mode 100644 (file)
index 0000000..0e01f97
--- /dev/null
@@ -0,0 +1,6 @@
+obj-$(CONFIG_SMS_SDIO_DRV) += smssdio.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/common/siano
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/parport/Kconfig b/drivers/media/parport/Kconfig
new file mode 100644 (file)
index 0000000..ece13dc
--- /dev/null
@@ -0,0 +1,52 @@
+menuconfig MEDIA_PARPORT_SUPPORT
+       bool "ISA and parallel port devices"
+       depends on (ISA || PARPORT) && MEDIA_CAMERA_SUPPORT
+       help
+         Enables drivers for ISA and parallel port bus. If you
+         need media drivers using those legacy buses, say Y.
+
+if MEDIA_PARPORT_SUPPORT
+config VIDEO_BWQCAM
+       tristate "Quickcam BW Video For Linux"
+       depends on PARPORT && VIDEO_V4L2
+       help
+         Say Y have if you the black and white version of the QuickCam
+         camera. See the next option for the color version.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bw-qcam.
+
+config VIDEO_CQCAM
+       tristate "QuickCam Colour Video For Linux"
+       depends on PARPORT && VIDEO_V4L2
+       help
+         This is the video4linux driver for the colour version of the
+         Connectix QuickCam.  If you have one of these cameras, say Y here,
+         otherwise say N.  This driver does not work with the original
+         monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
+         as a module (c-qcam).
+         Read <file:Documentation/video4linux/CQcam.txt> for more information.
+
+config VIDEO_PMS
+       tristate "Mediavision Pro Movie Studio Video For Linux"
+       depends on ISA && VIDEO_V4L2
+       help
+         Say Y if you have the ISA Mediavision Pro Movie Studio
+         capture card.
+
+         To compile this driver as a module, choose M here: the
+         module will be called pms.
+
+config VIDEO_W9966
+       tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
+       depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
+       help
+         Video4linux driver for Winbond's w9966 based Webcams.
+         Currently tested with the LifeView FlyCam Supra.
+         If you have one of these cameras, say Y here
+         otherwise say N.
+         This driver is also available as a module (w9966).
+
+         Check out <file:Documentation/video4linux/w9966.txt> for more
+         information.
+endif
diff --git a/drivers/media/parport/Makefile b/drivers/media/parport/Makefile
new file mode 100644 (file)
index 0000000..4eea06d
--- /dev/null
@@ -0,0 +1,4 @@
+obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
+obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
+obj-$(CONFIG_VIDEO_W9966) += w9966.o
+obj-$(CONFIG_VIDEO_PMS) += pms.o
diff --git a/drivers/media/pci/Kconfig b/drivers/media/pci/Kconfig
new file mode 100644 (file)
index 0000000..d4e2ed3
--- /dev/null
@@ -0,0 +1,47 @@
+menuconfig MEDIA_PCI_SUPPORT
+       bool "Media PCI Adapters"
+       depends on PCI && MEDIA_SUPPORT
+       help
+         Enable media drivers for PCI/PCIe bus.
+         If you have such devices, say Y.
+
+if MEDIA_PCI_SUPPORT
+
+if MEDIA_CAMERA_SUPPORT
+       comment "Media capture support"
+source "drivers/media/pci/meye/Kconfig"
+source "drivers/media/pci/sta2x11/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT
+       comment "Media capture/analog TV support"
+source "drivers/media/pci/ivtv/Kconfig"
+source "drivers/media/pci/zoran/Kconfig"
+source "drivers/media/pci/saa7146/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT
+       comment "Media capture/analog/hybrid TV support"
+source "drivers/media/pci/cx18/Kconfig"
+source "drivers/media/pci/cx23885/Kconfig"
+source "drivers/media/pci/cx25821/Kconfig"
+source "drivers/media/pci/cx88/Kconfig"
+source "drivers/media/pci/bt8xx/Kconfig"
+source "drivers/media/pci/saa7134/Kconfig"
+source "drivers/media/pci/saa7164/Kconfig"
+
+endif
+
+if MEDIA_DIGITAL_TV_SUPPORT
+       comment "Media digital TV PCI Adapters"
+source "drivers/media/pci/ttpci/Kconfig"
+source "drivers/media/pci/b2c2/Kconfig"
+source "drivers/media/pci/pluto2/Kconfig"
+source "drivers/media/pci/dm1105/Kconfig"
+source "drivers/media/pci/pt1/Kconfig"
+source "drivers/media/pci/mantis/Kconfig"
+source "drivers/media/pci/ngene/Kconfig"
+source "drivers/media/pci/ddbridge/Kconfig"
+endif
+
+endif #MEDIA_PCI_SUPPORT
diff --git a/drivers/media/pci/Makefile b/drivers/media/pci/Makefile
new file mode 100644 (file)
index 0000000..35cc578
--- /dev/null
@@ -0,0 +1,26 @@
+#
+# Makefile for the kernel multimedia device drivers.
+#
+
+obj-y        +=        ttpci/          \
+               b2c2/           \
+               pluto2/         \
+               dm1105/         \
+               pt1/            \
+               mantis/         \
+               ngene/          \
+               ddbridge/       \
+               b2c2/           \
+               saa7146/
+
+obj-$(CONFIG_VIDEO_IVTV) += ivtv/
+obj-$(CONFIG_VIDEO_ZORAN) += zoran/
+obj-$(CONFIG_VIDEO_CX18) += cx18/
+obj-$(CONFIG_VIDEO_CX23885) += cx23885/
+obj-$(CONFIG_VIDEO_CX25821) += cx25821/
+obj-$(CONFIG_VIDEO_CX88) += cx88/
+obj-$(CONFIG_VIDEO_BT848) += bt8xx/
+obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
+obj-$(CONFIG_VIDEO_SAA7164) += saa7164/
+obj-$(CONFIG_VIDEO_MEYE) += meye/
+obj-$(CONFIG_STA2X11_VIP) += sta2x11/
diff --git a/drivers/media/pci/b2c2/Kconfig b/drivers/media/pci/b2c2/Kconfig
new file mode 100644 (file)
index 0000000..58761a2
--- /dev/null
@@ -0,0 +1,15 @@
+config DVB_B2C2_FLEXCOP_PCI
+       tristate "Technisat/B2C2 Air/Sky/Cable2PC PCI"
+       depends on DVB_CORE && I2C
+       help
+         Support for the Air/Sky/CableStar2 PCI card (DVB/ATSC) by Technisat/B2C2.
+
+         Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_PCI_DEBUG
+       bool "Enable debug for the B2C2 FlexCop drivers"
+       depends on DVB_B2C2_FLEXCOP_PCI
+       select DVB_B2C2_FLEXCOP_DEBUG
+       help
+       Say Y if you want to enable the module option to control debug messages
+       of all B2C2 FlexCop drivers.
diff --git a/drivers/media/pci/b2c2/Makefile b/drivers/media/pci/b2c2/Makefile
new file mode 100644 (file)
index 0000000..b894320
--- /dev/null
@@ -0,0 +1,9 @@
+ifneq ($(CONFIG_DVB_B2C2_FLEXCOP_PCI),)
+b2c2-flexcop-pci-objs += flexcop-dma.o
+endif
+
+b2c2-flexcop-pci-objs += flexcop-pci.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP_PCI) += b2c2-flexcop-pci.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/common/b2c2/
diff --git a/drivers/media/pci/bt8xx/Kconfig b/drivers/media/pci/bt8xx/Kconfig
new file mode 100644 (file)
index 0000000..61d09e0
--- /dev/null
@@ -0,0 +1,43 @@
+config VIDEO_BT848
+       tristate "BT848 Video For Linux"
+       depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEOBUF_DMA_SG
+       depends on RC_CORE
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TVAUDIO if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TDA7432 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
+       ---help---
+         Support for BT848 based frame grabber/overlay boards. This includes
+         the Miro, Hauppauge and STB boards. Please read the material in
+         <file:Documentation/video4linux/bttv/> for more information.
+
+         To compile this driver as a module, choose M here: the
+         module will be called bttv.
+
+config DVB_BT8XX
+       tristate "DVB/ATSC Support for bt878 based TV cards"
+       depends on DVB_CORE && PCI && I2C && VIDEO_BT848
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_SP887X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_NXT6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24110 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_OR51211 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for PCI cards based on the Bt8xx PCI bridge. Examples are
+         the Nebula cards, the Pinnacle PCTV cards, the Twinhan DST cards,
+         the pcHDTV HD2000 cards, the DViCO FusionHDTV Lite cards, and
+         some AVerMedia cards.
+
+         Since these cards have no MPEG decoder onboard, they transmit
+         only compressed MPEG data over the PCI bus, so you need
+         an external software decoder to watch TV on your computer.
+
+         Say Y if you own such a device and want to use it.
diff --git a/drivers/media/pci/bt8xx/Makefile b/drivers/media/pci/bt8xx/Makefile
new file mode 100644 (file)
index 0000000..5f06597
--- /dev/null
@@ -0,0 +1,11 @@
+bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
+                      bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
+                      bttv-input.o bttv-audio-hook.o
+
+obj-$(CONFIG_VIDEO_BT848) += bttv.o
+obj-$(CONFIG_DVB_BT8XX) += bt878.o dvb-bt8xx.o dst.o dst_ca.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
similarity index 99%
rename from drivers/media/video/bt8xx/bttv-driver.c
rename to drivers/media/pci/bt8xx/bttv-driver.c
index b58ff87db771750dfa7a511d7f382b924dba8814..16f5ca23698c69af3795d5e6a3c90168fc6fee4c 100644 (file)
@@ -2740,7 +2740,7 @@ static int bttv_overlay(struct file *file, void *f, unsigned int on)
 }
 
 static int bttv_s_fbuf(struct file *file, void *f,
-                               struct v4l2_framebuffer *fb)
+                               const struct v4l2_framebuffer *fb)
 {
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
@@ -2986,7 +2986,7 @@ static int bttv_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
        return 0;
 }
 
-static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+static int bttv_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 {
        struct bttv_fh *fh = f;
        struct bttv *btv = fh->btv;
@@ -3028,17 +3028,17 @@ static int bttv_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
        }
 
        /* Min. scaled size 48 x 32. */
-       c.rect.left = clamp(crop->c.left, b_left, b_right - 48);
+       c.rect.left = clamp_t(s32, crop->c.left, b_left, b_right - 48);
        c.rect.left = min(c.rect.left, (__s32) MAX_HDELAY);
 
-       c.rect.width = clamp(crop->c.width,
+       c.rect.width = clamp_t(s32, crop->c.width,
                             48, b_right - c.rect.left);
 
-       c.rect.top = clamp(crop->c.top, b_top, b_bottom - 32);
+       c.rect.top = clamp_t(s32, crop->c.top, b_top, b_bottom - 32);
        /* Top and height must be a multiple of two. */
        c.rect.top = (c.rect.top + 1) & ~1;
 
-       c.rect.height = clamp(crop->c.height,
+       c.rect.height = clamp_t(s32, crop->c.height,
                              32, b_bottom - c.rect.top);
        c.rect.height = (c.rect.height + 1) & ~1;
 
@@ -3076,7 +3076,7 @@ static int bttv_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static int bttv_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int bttv_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
        if (unlikely(a->index))
                return -EINVAL;
@@ -3480,7 +3480,7 @@ static int radio_s_tuner(struct file *file, void *priv,
 }
 
 static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
+                                       const struct v4l2_audio *a)
 {
        if (unlikely(a->index))
                return -EINVAL;
similarity index 99%
rename from drivers/media/dvb/bt8xx/dst_ca.c
rename to drivers/media/pci/bt8xx/dst_ca.c
index 66f52f116b607e8b6613c403a3cfec0ee84d07c3..ee3884fbc9ce3e95120e2e421724833629c6cb11 100644 (file)
@@ -321,7 +321,8 @@ static int ca_get_message(struct dst_state *state, struct ca_msg *p_ca_message,
                return -EFAULT;
 
        if (p_ca_message->msg) {
-               dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%02x %02x %02x]", p_ca_message->msg[0], p_ca_message->msg[1], p_ca_message->msg[2]);
+               dprintk(verbose, DST_CA_NOTICE, 1, " Message = [%*ph]",
+                       3, p_ca_message->msg);
 
                for (i = 0; i < 3; i++) {
                        command = command | p_ca_message->msg[i];
similarity index 68%
rename from drivers/media/video/cx18/Kconfig
rename to drivers/media/pci/cx18/Kconfig
index 53b3c7702573ea66109942a042f8238de815e05e..c675b83c43a96d5e3207c468cc0aba735e5baa44 100644 (file)
@@ -1,6 +1,6 @@
 config VIDEO_CX18
        tristate "Conexant cx23418 MPEG encoder support"
-       depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C && EXPERIMENTAL
+       depends on VIDEO_V4L2 && DVB_CORE && PCI && I2C
        select I2C_ALGOBIT
        select VIDEOBUF_VMALLOC
        depends on RC_CORE
@@ -8,11 +8,11 @@ config VIDEO_CX18
        select VIDEO_TVEEPROM
        select VIDEO_CX2341X
        select VIDEO_CS5345
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MXL5005S if !MEDIA_TUNER_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This is a video4linux driver for Conexant cx23418 based
          PCI combo video recorder devices.
@@ -25,7 +25,7 @@ config VIDEO_CX18
 
 config VIDEO_CX18_ALSA
        tristate "Conexant 23418 DMA audio support"
-       depends on VIDEO_CX18 && SND && EXPERIMENTAL
+       depends on VIDEO_CX18 && SND
        select SND_PCM
        ---help---
          This is a video4linux driver for direct (DMA) audio on
similarity index 78%
rename from drivers/media/video/cx18/Makefile
rename to drivers/media/pci/cx18/Makefile
index a86bab5893ef0a3fd86d2357347d7ded1f841cde..d3ff1545c2c5da5c05748e033abd9da64286ee38 100644 (file)
@@ -8,6 +8,6 @@ cx18-alsa-objs := cx18-alsa-main.o cx18-alsa-pcm.o
 obj-$(CONFIG_VIDEO_CX18) += cx18.o
 obj-$(CONFIG_VIDEO_CX18_ALSA) += cx18-alsa.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
-ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/tuners
similarity index 99%
rename from drivers/media/video/cx18/cx18-av-firmware.c
rename to drivers/media/pci/cx18/cx18-av-firmware.c
index 280aa4d22488c658a712e8907823ef0e800358ed..a34fd082b76ed8e2216bf0bbe1f1d9a382660f8d 100644 (file)
@@ -221,3 +221,5 @@ int cx18_av_loadfw(struct cx18 *cx)
        release_firmware(fw);
        return 0;
 }
+
+MODULE_FIRMWARE(FWFILE);
similarity index 99%
rename from drivers/media/video/cx18/cx18-av-vbi.c
rename to drivers/media/pci/cx18/cx18-av-vbi.c
index baa36fbcd4d4d18c1e1d16906e138fbaaa73fc8e..246982841fece5ac75df67c9beb08604d56f3eba 100644 (file)
@@ -143,7 +143,9 @@ int cx18_av_g_sliced_fmt(struct v4l2_subdev *sd, struct v4l2_sliced_vbi_format *
        int is_pal = !(state->std & V4L2_STD_525_60);
        int i;
 
-       memset(svbi, 0, sizeof(*svbi));
+       memset(svbi->service_lines, 0, sizeof(svbi->service_lines));
+       svbi->service_set = 0;
+
        /* we're done if raw VBI is active */
        if ((cx18_av_read(cx, 0x404) & 0x10) == 0)
                return 0;
similarity index 99%
rename from drivers/media/video/cx18/cx18-driver.c
rename to drivers/media/pci/cx18/cx18-driver.c
index 7e5ffd6f51786d3390b629b8794b4139aa410551..c67733d32c8a888d61ced937bb6427c38dc830fa 100644 (file)
@@ -1357,3 +1357,4 @@ static void __exit module_cleanup(void)
 
 module_init(module_start);
 module_exit(module_cleanup);
+MODULE_FIRMWARE(XC2028_DEFAULT_FIRMWARE);
similarity index 99%
rename from drivers/media/video/cx18/cx18-dvb.c
rename to drivers/media/pci/cx18/cx18-dvb.c
index f41922bd402025118a9e35c8453675ed1ffa62cf..3eac59c51231c0f97b9ae52f1dd8e35f77615427 100644 (file)
@@ -40,6 +40,8 @@
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
+#define FWFILE "dvb-cx18-mpc718-mt352.fw"
+
 #define CX18_REG_DMUX_NUM_PORT_0_CONTROL 0xd5a000
 #define CX18_CLOCK_ENABLE2              0xc71024
 #define CX18_DMUX_CLK_MASK              0x0080
@@ -135,7 +137,7 @@ static int yuan_mpc718_mt352_reqfw(struct cx18_stream *stream,
                                   const struct firmware **fw)
 {
        struct cx18 *cx = stream->cx;
-       const char *fn = "dvb-cx18-mpc718-mt352.fw";
+       const char *fn = FWFILE;
        int ret;
 
        ret = request_firmware(fw, fn, &cx->pci_dev->dev);
@@ -603,3 +605,5 @@ static int dvb_register(struct cx18_stream *stream)
 
        return ret;
 }
+
+MODULE_FIRMWARE(FWFILE);
similarity index 98%
rename from drivers/media/video/cx18/cx18-firmware.c
rename to drivers/media/pci/cx18/cx18-firmware.c
index b85c292a849ac2debe36c828e506254cd65214a7..a1c1cec05f98e4693bdc3dacfa073a64adec1d32 100644 (file)
@@ -376,6 +376,9 @@ void cx18_init_memory(struct cx18 *cx)
        cx18_write_reg(cx, 0x00000101, CX18_WMB_CLIENT14);  /* AVO */
 }
 
+#define CX18_CPU_FIRMWARE "v4l-cx23418-cpu.fw"
+#define CX18_APU_FIRMWARE "v4l-cx23418-apu.fw"
+
 int cx18_firmware_init(struct cx18 *cx)
 {
        u32 fw_entry_addr;
@@ -400,7 +403,7 @@ int cx18_firmware_init(struct cx18 *cx)
        cx18_sw1_irq_enable(cx, IRQ_CPU_TO_EPU | IRQ_APU_TO_EPU);
        cx18_sw2_irq_enable(cx, IRQ_CPU_TO_EPU_ACK | IRQ_APU_TO_EPU_ACK);
 
-       sz = load_cpu_fw_direct("v4l-cx23418-cpu.fw", cx->enc_mem, cx);
+       sz = load_cpu_fw_direct(CX18_CPU_FIRMWARE, cx->enc_mem, cx);
        if (sz <= 0)
                return sz;
 
@@ -408,7 +411,7 @@ int cx18_firmware_init(struct cx18 *cx)
        cx18_init_scb(cx);
 
        fw_entry_addr = 0;
-       sz = load_apu_fw_direct("v4l-cx23418-apu.fw", cx->enc_mem, cx,
+       sz = load_apu_fw_direct(CX18_APU_FIRMWARE, cx->enc_mem, cx,
                                &fw_entry_addr);
        if (sz <= 0)
                return sz;
@@ -451,3 +454,6 @@ int cx18_firmware_init(struct cx18 *cx)
        cx18_write_reg_expect(cx, 0x14001400, 0xc78110, 0x00001400, 0x14001400);
        return 0;
 }
+
+MODULE_FIRMWARE(CX18_CPU_FIRMWARE);
+MODULE_FIRMWARE(CX18_APU_FIRMWARE);
similarity index 99%
rename from drivers/media/video/cx18/cx18-ioctl.c
rename to drivers/media/pci/cx18/cx18-ioctl.c
index e9912db3b496ae69618b411896fe054ba35d4827..cd8d2c2b16246e667e8e78053558cd7c30f6261d 100644 (file)
@@ -210,10 +210,6 @@ static int cx18_g_fmt_sliced_vbi_cap(struct file *file, void *fh,
        if (v4l2_subdev_call(cx->sd_av, vbi, g_sliced_fmt, &fmt->fmt.sliced))
                return -EINVAL;
 
-       /* Ensure V4L2 spec compliant output */
-       vbifmt->reserved[0] = 0;
-       vbifmt->reserved[1] = 0;
-       vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
        vbifmt->service_set = cx18_get_service_set(vbifmt);
        return 0;
 }
@@ -492,7 +488,7 @@ static int cx18_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
        return cx18_get_audio_input(cx, vin->index, vin);
 }
 
-static int cx18_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+static int cx18_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout)
 {
        struct cx18 *cx = fh2id(fh)->cx;
 
@@ -527,7 +523,7 @@ static int cx18_cropcap(struct file *file, void *fh,
        return 0;
 }
 
-static int cx18_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+static int cx18_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct cx18_open_id *id = fh2id(fh);
        struct cx18 *cx = id->cx;
similarity index 98%
rename from drivers/media/video/cx18/cx18-streams.c
rename to drivers/media/pci/cx18/cx18-streams.c
index 9d598ab88615c07a82103010e6cb9c5a1e19600d..72af9b5c2d7dd2fcc2f37c27d568f4292a7b30ec 100644 (file)
@@ -58,42 +58,41 @@ static struct {
        int vfl_type;
        int num_offset;
        int dma;
-       enum v4l2_buf_type buf_type;
 } cx18_stream_info[] = {
        {       /* CX18_ENC_STREAM_TYPE_MPG */
                "encoder MPEG",
                VFL_TYPE_GRABBER, 0,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_TS */
                "TS",
                VFL_TYPE_GRABBER, -1,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_YUV */
                "encoder YUV",
                VFL_TYPE_GRABBER, CX18_V4L2_ENC_YUV_OFFSET,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_VBI */
                "encoder VBI",
                VFL_TYPE_VBI, 0,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VBI_CAPTURE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_PCM */
                "encoder PCM audio",
                VFL_TYPE_GRABBER, CX18_V4L2_ENC_PCM_OFFSET,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_PRIVATE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_IDX */
                "encoder IDX",
                VFL_TYPE_GRABBER, -1,
-               PCI_DMA_FROMDEVICE, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE,
        },
        {       /* CX18_ENC_STREAM_TYPE_RAD */
                "encoder radio",
                VFL_TYPE_RADIO, 0,
-               PCI_DMA_NONE, V4L2_BUF_TYPE_PRIVATE,
+               PCI_DMA_NONE,
        },
 };
 
diff --git a/drivers/media/pci/cx23885/Kconfig b/drivers/media/pci/cx23885/Kconfig
new file mode 100644 (file)
index 0000000..eafa114
--- /dev/null
@@ -0,0 +1,50 @@
+config VIDEO_CX23885
+       tristate "Conexant cx23885 (2388x successor) support"
+       depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
+       select SND_PCM
+       select I2C_ALGOBIT
+       select VIDEO_BTCX
+       select VIDEO_TUNER
+       select VIDEO_TVEEPROM
+       depends on RC_CORE
+       select VIDEOBUF_DVB
+       select VIDEOBUF_DMA_SG
+       select VIDEO_CX25840
+       select VIDEO_CX2341X
+       select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0367 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+       ---help---
+         This is a video4linux driver for Conexant 23885 based
+         TV cards.
+
+         To compile this driver as a module, choose M here: the
+         module will be called cx23885
+
+config MEDIA_ALTERA_CI
+       tristate "Altera FPGA based CI module"
+       depends on VIDEO_CX23885 && DVB_CORE
+       select ALTERA_STAPL
+       ---help---
+         An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
+
+         To compile this driver as a module, choose M here: the
+         module will be called altera-ci
similarity index 72%
rename from drivers/media/video/cx23885/Makefile
rename to drivers/media/pci/cx23885/Makefile
index f81f2796a0f9e45fc0bb717bed3d79e2525e48ba..a2cbdcf15a8c48fde4cd79c43b33dd92c81a8def 100644 (file)
@@ -7,9 +7,9 @@ cx23885-objs    := cx23885-cards.o cx23885-video.o cx23885-vbi.o \
 obj-$(CONFIG_VIDEO_CX23885) += cx23885.o
 obj-$(CONFIG_MEDIA_ALTERA_CI) += altera-ci.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
 
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
similarity index 99%
rename from drivers/media/video/cx23885/altera-ci.c
rename to drivers/media/pci/cx23885/altera-ci.c
index 1fa8927f0d36eecb3946b7c7c48467eb3d540640..aee7f0dacff11a8a61764c274559bf5454909fad 100644 (file)
@@ -724,6 +724,7 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr)
        if (temp_int != NULL) {
                inter = temp_int->internal;
                (inter->cis_used)++;
+                inter->fpga_rw = config->fpga_rw;
                ci_dbg_print("%s: Find Internal Structure!\n", __func__);
        } else {
                inter = kzalloc(sizeof(struct fpga_internal), GFP_KERNEL);
@@ -743,7 +744,6 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr)
 
        ci_dbg_print("%s: setting state = %p for ci = %d\n", __func__,
                                                state, ci_nr - 1);
-       inter->state[ci_nr - 1] = state;
        state->internal = inter;
        state->nr = ci_nr - 1;
 
@@ -765,6 +765,8 @@ int altera_ci_init(struct altera_ci_config *config, int ci_nr)
        if (0 != ret)
                goto err;
 
+       inter->state[ci_nr - 1] = state;
+
        altera_hw_filt_init(config, ci_nr);
 
        if (inter->strt_wrk) {
similarity index 99%
rename from drivers/media/video/cx23885/cx23885-417.c
rename to drivers/media/pci/cx23885/cx23885-417.c
index f5c79e53e5a145bce2fc8a0f898ca7482d2ab0e6..5d5052d0253f00808d5960d46b388b20b6c0bf98 100644 (file)
@@ -1786,3 +1786,5 @@ int cx23885_417_register(struct cx23885_dev *dev)
 
        return 0;
 }
+
+MODULE_FIRMWARE(CX23885_FIRM_IMAGE_NAME);
similarity index 98%
rename from drivers/media/video/cx23885/cx23885-cards.c
rename to drivers/media/pci/cx23885/cx23885-cards.c
index 080e11157e5fe89afdb384c702376d80528daf5d..39a4a4b9ed7e893d97fe3460dcef33dc663de5b8 100644 (file)
@@ -36,7 +36,7 @@
 #include "xc5000.h"
 #include "cx23888-ir.h"
 
-static unsigned int netup_card_rev = 1;
+static unsigned int netup_card_rev = 4;
 module_param(netup_card_rev, int, 0644);
 MODULE_PARM_DESC(netup_card_rev,
                "NetUP Dual DVB-T/C CI card revision");
@@ -46,6 +46,7 @@ MODULE_PARM_DESC(enable_885_ir,
                 "Enable integrated IR controller for supported\n"
                 "\t\t    CX2388[57] boards that are wired for it:\n"
                 "\t\t\tHVR-1250 (reported safe)\n"
+                "\t\t\tTerraTec Cinergy T PCIe Dual (not well tested, appears to be safe)\n"
                 "\t\t\tTeVii S470 (reported unsafe)\n"
                 "\t\t    This can cause an interrupt storm with some cards.\n"
                 "\t\t    Default: 0 [Disabled]");
@@ -564,6 +565,10 @@ struct cx23885_board cx23885_boards[] = {
        [CX23885_BOARD_TEVII_S471] = {
                .name           = "TeVii S471",
                .portb          = CX23885_MPEG_DVB,
+       },
+       [CX23885_BOARD_PROF_8000] = {
+               .name           = "Prof Revolution DVB-S2 8000",
+               .portb          = CX23885_MPEG_DVB,
        }
 };
 const unsigned int cx23885_bcount = ARRAY_SIZE(cx23885_boards);
@@ -776,6 +781,10 @@ struct cx23885_subid cx23885_subids[] = {
                .subvendor = 0xd471,
                .subdevice = 0x9022,
                .card      = CX23885_BOARD_TEVII_S471,
+       }, {
+               .subvendor = 0x8000,
+               .subdevice = 0x3034,
+               .card      = CX23885_BOARD_PROF_8000,
        },
 };
 const unsigned int cx23885_idcount = ARRAY_SIZE(cx23885_subids);
@@ -1155,6 +1164,7 @@ void cx23885_gpio_setup(struct cx23885_dev *dev)
                cx_set(GP0_IO, 0x00040004);
                break;
        case CX23885_BOARD_TBS_6920:
+       case CX23885_BOARD_PROF_8000:
                cx_write(MC417_CTL, 0x00000036);
                cx_write(MC417_OEN, 0x00001000);
                cx_set(MC417_RWD, 0x00000002);
@@ -1363,6 +1373,7 @@ int cx23885_ir_init(struct cx23885_dev *dev)
                params.shutdown = true;
                v4l2_subdev_call(dev->sd_ir, ir, tx_s_parameters, &params);
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
                if (!enable_885_ir)
                        break;
@@ -1403,6 +1414,7 @@ void cx23885_ir_fini(struct cx23885_dev *dev)
                cx23888_ir_remove(dev);
                dev->sd_ir = NULL;
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
                cx23885_irq_remove(dev, PCI_MSK_AV_CORE);
@@ -1446,6 +1458,7 @@ void cx23885_ir_pci_int_enable(struct cx23885_dev *dev)
                if (dev->sd_ir)
                        cx23885_irq_add_enable(dev, PCI_MSK_IR);
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
                if (dev->sd_ir)
@@ -1536,6 +1549,7 @@ void cx23885_card_setup(struct cx23885_dev *dev)
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_TEVII_S471:
        case CX23885_BOARD_DVBWORLD_2005:
+       case CX23885_BOARD_PROF_8000:
                ts1->gen_ctrl_val  = 0x5; /* Parallel */
                ts1->ts_clk_en_val = 0x1; /* Enable TS_CLK */
                ts1->src_sel_val   = CX23885_SRC_SEL_PARALLEL_MPEG_VIDEO;
similarity index 95%
rename from drivers/media/video/cx23885/cx23885-dvb.c
rename to drivers/media/pci/cx23885/cx23885-dvb.c
index cd542684ba022c4f194928e37cfc318d6a1b0b79..4379d8a6dad5f6d4f8376f7d3d1f4dc68bc97b59 100644 (file)
@@ -63,6 +63,9 @@
 #include "stv0367.h"
 #include "drxk.h"
 #include "mt2063.h"
+#include "stv090x.h"
+#include "stb6100.h"
+#include "stb6100_cfg.h"
 
 static unsigned int debug;
 
@@ -489,6 +492,42 @@ static struct xc5000_config mygica_x8506_xc5000_config = {
        .if_khz = 5380,
 };
 
+static struct stv090x_config prof_8000_stv090x_config = {
+        .device                 = STV0903,
+        .demod_mode             = STV090x_SINGLE,
+        .clk_mode               = STV090x_CLK_EXT,
+        .xtal                   = 27000000,
+        .address                = 0x6A,
+        .ts1_mode               = STV090x_TSMODE_PARALLEL_PUNCTURED,
+        .repeater_level         = STV090x_RPTLEVEL_64,
+        .adc1_range             = STV090x_ADC_2Vpp,
+        .diseqc_envelope_mode   = false,
+
+        .tuner_get_frequency    = stb6100_get_frequency,
+        .tuner_set_frequency    = stb6100_set_frequency,
+        .tuner_set_bandwidth    = stb6100_set_bandwidth,
+        .tuner_get_bandwidth    = stb6100_get_bandwidth,
+};
+
+static struct stb6100_config prof_8000_stb6100_config = {
+       .tuner_address = 0x60,
+       .refclock = 27000000,
+};
+
+static int p8000_set_voltage(struct dvb_frontend *fe, fe_sec_voltage_t voltage)
+{
+       struct cx23885_tsport *port = fe->dvb->priv;
+       struct cx23885_dev *dev = port->dev;
+
+       if (voltage == SEC_VOLTAGE_18)
+               cx_write(MC417_RWD, 0x00001e00);
+       else if (voltage == SEC_VOLTAGE_13)
+               cx_write(MC417_RWD, 0x00001a00);
+       else
+               cx_write(MC417_RWD, 0x00001800);
+       return 0;
+}
+
 static int cx23885_dvb_set_frontend(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *p = &fe->dtv_property_cache;
@@ -1186,6 +1225,23 @@ static int dvb_register(struct cx23885_tsport *port)
                                        &tevii_ds3000_config,
                                        &i2c_bus->i2c_adap);
                break;
+       case CX23885_BOARD_PROF_8000:
+               i2c_bus = &dev->i2c_bus[0];
+
+               fe0->dvb.frontend = dvb_attach(stv090x_attach,
+                                               &prof_8000_stv090x_config,
+                                               &i2c_bus->i2c_adap,
+                                               STV090x_DEMODULATOR_0);
+               if (fe0->dvb.frontend != NULL) {
+                       if (!dvb_attach(stb6100_attach,
+                                       fe0->dvb.frontend,
+                                       &prof_8000_stb6100_config,
+                                       &i2c_bus->i2c_adap))
+                               goto frontend_detach;
+
+                       fe0->dvb.frontend->ops.set_voltage = p8000_set_voltage;
+               }
+               break;
        default:
                printk(KERN_INFO "%s: The frontend of your DVB/ATSC card "
                        " isn't supported yet\n",
@@ -1218,8 +1274,7 @@ static int dvb_register(struct cx23885_tsport *port)
 
        /* register everything */
        ret = videobuf_dvb_register_bus(&port->frontends, THIS_MODULE, port,
-                                       &dev->pci->dev, adapter_nr, mfe_shared,
-                                       NULL);
+                                       &dev->pci->dev, adapter_nr, mfe_shared);
        if (ret)
                goto frontend_detach;
 
similarity index 96%
rename from drivers/media/video/cx23885/cx23885-input.c
rename to drivers/media/pci/cx23885/cx23885-input.c
index ce765e3f77bdf6b679ba1b56900035f4f38d51c2..56066721edc17423726188858aa66e4ea017ff0b 100644 (file)
@@ -85,6 +85,7 @@ void cx23885_input_rx_work_handler(struct cx23885_dev *dev, u32 events)
        case CX23885_BOARD_HAUPPAUGE_HVR1270:
        case CX23885_BOARD_HAUPPAUGE_HVR1850:
        case CX23885_BOARD_HAUPPAUGE_HVR1290:
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
        case CX23885_BOARD_HAUPPAUGE_HVR1250:
                /*
@@ -162,6 +163,7 @@ static int cx23885_input_ir_start(struct cx23885_dev *dev)
                 */
                params.invert_level = true;
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
        case CX23885_BOARD_TEVII_S470:
                /*
                 * The IR controller on this board only returns pulse widths.
@@ -272,6 +274,13 @@ int cx23885_input_init(struct cx23885_dev *dev)
                /* The grey Hauppauge RC-5 remote */
                rc_map = RC_MAP_HAUPPAUGE;
                break;
+       case CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL:
+               /* Integrated CX23885 IR controller */
+               driver_type = RC_DRIVER_IR_RAW;
+               allowed_protos = RC_TYPE_NEC;
+               /* The grey Terratec remote with orange buttons */
+               rc_map = RC_MAP_NEC_TERRATEC_CINERGY_XS;
+               break;
        case CX23885_BOARD_TEVII_S470:
                /* Integrated CX23885 IR controller */
                driver_type = RC_DRIVER_IR_RAW;
similarity index 99%
rename from drivers/media/video/cx23885/cx23885-video.c
rename to drivers/media/pci/cx23885/cx23885-video.c
index 22f8e7fbd6656fe81f33f824832a38cc7e2dd14c..8c4a9a5f9a504ff2959df17d189ab148644f6a03 100644 (file)
@@ -1426,7 +1426,7 @@ static int vidioc_g_audinput(struct file *file, void *priv,
 }
 
 static int vidioc_s_audinput(struct file *file, void *priv,
-       struct v4l2_audio *i)
+       const struct v4l2_audio *i)
 {
        struct cx23885_dev *dev = ((struct cx23885_fh *)priv)->dev;
        if (i->index >= 2)
similarity index 99%
rename from drivers/media/video/cx23885/cx23885.h
rename to drivers/media/pci/cx23885/cx23885.h
index 5d560c747e09346d7f90b70b6eccb24a6c949ea1..67f40d31450be7e81d79fd24526e5436d7bb336a 100644 (file)
@@ -90,6 +90,7 @@
 #define CX23885_BOARD_TERRATEC_CINERGY_T_PCIE_DUAL 34
 #define CX23885_BOARD_TEVII_S471               35
 #define CX23885_BOARD_HAUPPAUGE_HVR1255_22111  36
+#define CX23885_BOARD_PROF_8000                37
 
 #define GPIO_0 0x00000001
 #define GPIO_1 0x00000002
similarity index 67%
rename from drivers/media/video/cx25821/Makefile
rename to drivers/media/pci/cx25821/Makefile
index aedde18c68f96f68e377e43eb2d3d2824c7b213c..5bf3ea4c1556a642d11dc7709faf8cb64a6a0b9e 100644 (file)
@@ -7,7 +7,7 @@ cx25821-y   := cx25821-core.o cx25821-cards.o cx25821-i2c.o \
 obj-$(CONFIG_VIDEO_CX25821) += cx25821.o
 obj-$(CONFIG_VIDEO_CX25821_ALSA) += cx25821-alsa.o
 
-ccflags-y := -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
similarity index 99%
rename from drivers/media/video/cx25821/cx25821-video.c
rename to drivers/media/pci/cx25821/cx25821-video.c
index b38d4379cc362b954e4f20db989ca5b5aa2501ea..0a80245165d0d8d6e51f876494c1f886893dd43f 100644 (file)
@@ -1610,7 +1610,7 @@ int cx25821_vidioc_cropcap(struct file *file, void *priv,
        return 0;
 }
 
-int cx25821_vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+int cx25821_vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
 {
        struct cx25821_dev *dev = ((struct cx25821_fh *)priv)->dev;
        struct cx25821_fh *fh = priv;
similarity index 99%
rename from drivers/media/video/cx25821/cx25821-video.h
rename to drivers/media/pci/cx25821/cx25821-video.h
index 9652a5e35ba23e1b2dff9e4704db03f93cd563e3..c265e35b37c3e54a9ddbe0b57f0fb31e3fda8d89 100644 (file)
@@ -177,7 +177,7 @@ extern int cx25821_set_control(struct cx25821_dev *dev,
 extern int cx25821_vidioc_cropcap(struct file *file, void *fh,
                                  struct v4l2_cropcap *cropcap);
 extern int cx25821_vidioc_s_crop(struct file *file, void *priv,
-                                struct v4l2_crop *crop);
+                                const struct v4l2_crop *crop);
 extern int cx25821_vidioc_g_crop(struct file *file, void *priv,
                                 struct v4l2_crop *crop);
 
similarity index 70%
rename from drivers/media/video/cx88/Kconfig
rename to drivers/media/pci/cx88/Kconfig
index 3598dc087b0880fd5214f8f96b36b377678b1a00..d27fccbf03c441055859eb84a503803d4f265ba5 100644 (file)
@@ -6,7 +6,7 @@ config VIDEO_CX88
        select VIDEOBUF_DMA_SG
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
-       select VIDEO_WM8775 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_WM8775 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This is a video4linux driver for Conexant 2388x based
          TV cards.
@@ -46,23 +46,23 @@ config VIDEO_CX88_DVB
        tristate "DVB/ATSC Support for cx2388x based TV cards"
        depends on VIDEO_CX88 && DVB_CORE
        select VIDEOBUF_DVB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_OR51132 if !DVB_FE_CUSTOMISE
-       select DVB_CX22702 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_NXT200X if !DVB_FE_CUSTOMISE
-       select DVB_CX24123 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_STB6000 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_OR51132 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24123 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This adds support for DVB/ATSC cards based on the
          Conexant 2388x chip.
similarity index 73%
rename from drivers/media/video/cx88/Makefile
rename to drivers/media/pci/cx88/Makefile
index c1a2785ba2431a607e9791edeeae6fa4f05adb5c..d3679c3ee248bf5bf5e14d1d0de2ea166bb2f1aa 100644 (file)
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_CX88_BLACKBIRD) += cx88-blackbird.o
 obj-$(CONFIG_VIDEO_CX88_DVB) += cx88-dvb.o
 obj-$(CONFIG_VIDEO_CX88_VP3054) += cx88-vp3054-i2c.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
similarity index 99%
rename from drivers/media/video/cx88/cx88-alsa.c
rename to drivers/media/pci/cx88/cx88-alsa.c
index dfac6e34859fc2d7b8647ac4c8afdd70f6e2de8b..3aa6856ead3b2f13f71db61ee9ea329808c01be4 100644 (file)
@@ -749,7 +749,7 @@ static struct snd_kcontrol_new snd_cx88_alc_switch = {
  * Only boards with eeprom and byte 1 at eeprom=1 have it
  */
 
-static const struct pci_device_id const cx88_audio_pci_tbl[] __devinitdata = {
+static const struct pci_device_id cx88_audio_pci_tbl[] __devinitdata = {
        {0x14f1,0x8801,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
        {0x14f1,0x8811,PCI_ANY_ID,PCI_ANY_ID,0,0,0},
        {0, }
similarity index 99%
rename from drivers/media/video/cx88/cx88-blackbird.c
rename to drivers/media/pci/cx88/cx88-blackbird.c
index 843ffd9e533b06a04e4eb7720743ec35624e4eb0..def363fb71c0664a72e6cf8fff5d54d398b7d3bc 100644 (file)
@@ -1236,7 +1236,7 @@ static int cx8802_blackbird_probe(struct cx8802_driver *drv)
        err = cx2341x_handler_init(&dev->cxhdl, 36);
        if (err)
                goto fail_core;
-       v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl);
+       v4l2_ctrl_add_handler(&dev->cxhdl.hdl, &core->video_hdl, NULL);
 
        /* blackbird stuff */
        printk("%s/2: cx23416 based mpeg encoder (blackbird reference design)\n",
similarity index 99%
rename from drivers/media/video/cx88/cx88-cards.c
rename to drivers/media/pci/cx88/cx88-cards.c
index 4e9d4f7229602e3e3a4f3fbc1a321507a07d894a..0c255248cbcdb2054a3e02d4899f6f2688c2844f 100644 (file)
@@ -3028,9 +3028,9 @@ static int cx88_xc3028_winfast1800h_callback(struct cx88_core *core,
                cx_set(MO_GP1_IO, 0x1010);
                mdelay(50);
                cx_clear(MO_GP1_IO, 0x10);
-               mdelay(50);
+               mdelay(75);
                cx_set(MO_GP1_IO, 0x10);
-               mdelay(50);
+               mdelay(75);
                return 0;
        }
        return -EINVAL;
similarity index 99%
rename from drivers/media/video/cx88/cx88-core.c
rename to drivers/media/pci/cx88/cx88-core.c
index e81c735f012a263b918bfdb324aff12578b06c1d..c97b174be3ab6313e9810c0c27b13b97ce2f3384 100644 (file)
@@ -253,7 +253,7 @@ cx88_free_buffer(struct videobuf_queue *q, struct cx88_buffer *buf)
  *    0x0c00 -           FIFOs
  */
 
-const struct sram_channel const cx88_sram_channels[] = {
+const struct sram_channel cx88_sram_channels[] = {
        [SRAM_CH21] = {
                .name       = "video y / packed",
                .cmds_start = 0x180040,
similarity index 99%
rename from drivers/media/video/cx88/cx88-dvb.c
rename to drivers/media/pci/cx88/cx88-dvb.c
index 003937cd72f553e80bceecdcb9a0befe8986630a..d803bba09525206e9710d401829251d829e04ede 100644 (file)
@@ -1578,7 +1578,7 @@ static int dvb_register(struct cx8802_dev *dev)
 
        /* register everything */
        res = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-               &dev->pci->dev, adapter_nr, mfe_shared, NULL);
+               &dev->pci->dev, adapter_nr, mfe_shared);
        if (res)
                goto frontend_detach;
        return res;
similarity index 99%
rename from drivers/media/video/cx88/cx88-video.c
rename to drivers/media/pci/cx88/cx88-video.c
index f6fcc7e763ab9c1964bbd9eab1d18b6bb6749eec..a146d50d77952fda04871e9a51c3136818d45f22 100644 (file)
@@ -1795,7 +1795,7 @@ static int __devinit cx8800_initdev(struct pci_dev *pci_dev,
                if (vc->id == V4L2_CID_CHROMA_AGC)
                        core->chroma_agc = vc;
        }
-       v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl);
+       v4l2_ctrl_add_handler(&core->video_hdl, &core->audio_hdl, NULL);
 
        /* load and configure helper modules */
 
similarity index 99%
rename from drivers/media/video/cx88/cx88.h
rename to drivers/media/pci/cx88/cx88.h
index 0cae0fd9e1647d50f73b4826c2a35861f71a771c..44ffc8b3d45f9f7a586404a0b37e8520ae804fa0 100644 (file)
@@ -141,7 +141,7 @@ struct sram_channel {
        u32  cnt1_reg;
        u32  cnt2_reg;
 };
-extern const struct sram_channel const cx88_sram_channels[];
+extern const struct sram_channel cx88_sram_channels[];
 
 /* ----------------------------------------------------------- */
 /* card configuration                                          */
similarity index 60%
rename from drivers/media/dvb/ddbridge/Kconfig
rename to drivers/media/pci/ddbridge/Kconfig
index d099e1a12c85ec0e6b03673f404a9714eb3dc2d0..44e5dc15e60a3712b874d3680e865e83df1f2b82 100644 (file)
@@ -1,11 +1,11 @@
 config DVB_DDBRIDGE
        tristate "Digital Devices bridge support"
        depends on DVB_CORE && PCI && I2C
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110x if !DVB_FE_CUSTOMISE
-       select DVB_STV090x if !DVB_FE_CUSTOMISE
-       select DVB_DRXK if !DVB_FE_CUSTOMISE
-       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          Support for cards with the Digital Devices PCI express bridge:
          - Octopus PCIe Bridge
similarity index 61%
rename from drivers/media/dvb/ddbridge/Makefile
rename to drivers/media/pci/ddbridge/Makefile
index 38019bafb862246b992f6026f77314f460cb2c78..7446c8b677b5c393a30edabdab8c55930b872b9c 100644 (file)
@@ -6,9 +6,9 @@ ddbridge-objs := ddbridge-core.o
 
 obj-$(CONFIG_DVB_DDBRIDGE) += ddbridge.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
 
 # For the staging CI driver cxd2099
 ccflags-y += -Idrivers/staging/media/cxd2099/
similarity index 99%
rename from drivers/media/dvb/ddbridge/ddbridge-core.c
rename to drivers/media/pci/ddbridge/ddbridge-core.c
index ebf3f05839d2c5416488b77df70c825dc01ae467..feff57ee5a083b55ec1c822b69807d4d1df84851 100644 (file)
@@ -1497,7 +1497,7 @@ static int ddb_class_create(void)
        ddb_class = class_create(THIS_MODULE, DDB_NAME);
        if (IS_ERR(ddb_class)) {
                unregister_chrdev(ddb_major, DDB_NAME);
-               return -1;
+               return PTR_ERR(ddb_class);
        }
        ddb_class->devnode = ddb_devnode;
        return 0;
@@ -1701,11 +1701,18 @@ static struct pci_driver ddb_pci_driver = {
 
 static __init int module_init_ddbridge(void)
 {
+       int ret;
+
        printk(KERN_INFO "Digital Devices PCIE bridge driver, "
               "Copyright (C) 2010-11 Digital Devices GmbH\n");
-       if (ddb_class_create())
-               return -1;
-       return pci_register_driver(&ddb_pci_driver);
+
+       ret = ddb_class_create();
+       if (ret < 0)
+               return ret;
+       ret = pci_register_driver(&ddb_pci_driver);
+       if (ret < 0)
+               ddb_class_destroy();
+       return ret;
 }
 
 static __exit void module_exit_ddbridge(void)
similarity index 57%
rename from drivers/media/dvb/dm1105/Kconfig
rename to drivers/media/pci/dm1105/Kconfig
index f3de0a4d63f26cd167134fc09c94137ef0a2a645..013df4e015cdcd0bd3ef08bf1b0d699e2ceeab93 100644 (file)
@@ -1,13 +1,13 @@
 config DVB_DM1105
        tristate "SDMC DM1105 based PCI cards"
        depends on DVB_CORE && PCI && I2C
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_STB6000 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_SI21XX if !DVB_FE_CUSTOMISE
-       select DVB_DS3000 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
        depends on RC_CORE
        help
          Support for cards based on the SDMC DM1105 PCI chip like
diff --git a/drivers/media/pci/dm1105/Makefile b/drivers/media/pci/dm1105/Makefile
new file mode 100644 (file)
index 0000000..3275851
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_DM1105) += dm1105.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends
similarity index 67%
rename from drivers/media/video/ivtv/Kconfig
rename to drivers/media/pci/ivtv/Kconfig
index 89f65914cc8eb745f3659cfc6a44f93e1f7cf26b..dd6ee57e3a4c680da2708151275ce5e453a5892a 100644 (file)
@@ -28,6 +28,22 @@ config VIDEO_IVTV
          To compile this driver as a module, choose M here: the
          module will be called ivtv.
 
+config VIDEO_IVTV_ALSA
+       tristate "Conexant cx23415/cx23416 ALSA interface for PCM audio capture"
+       depends on VIDEO_IVTV && SND
+       select SND_PCM
+       ---help---
+         This driver provides an ALSA interface as another method for user
+         applications to obtain PCM audio data from Conexant cx23415/cx23416
+         based PCI TV cards supported by the ivtv driver.
+
+         The ALSA interface has much wider use in user applications performing
+         PCM audio capture, than the V4L2 "/dev/video24" PCM audio interface
+         provided by the main ivtv driver.
+
+         To compile this driver as a module, choose M here: the
+         module will be called ivtv-alsa.
+
 config VIDEO_FB_IVTV
        tristate "Conexant cx23415 framebuffer support"
        depends on VIDEO_IVTV && FB
similarity index 53%
rename from drivers/media/video/ivtv/Makefile
rename to drivers/media/pci/ivtv/Makefile
index 77de8a45b46f56ca4a0d42e732164b562fb0c951..0eaa88298b7e11deea078cbf8b1d5c509c1c3b35 100644 (file)
@@ -3,12 +3,14 @@ ivtv-objs     := ivtv-routing.o ivtv-cards.o ivtv-controls.o \
                   ivtv-gpio.o ivtv-i2c.o ivtv-ioctl.o ivtv-irq.o \
                   ivtv-mailbox.o ivtv-queue.o ivtv-streams.o ivtv-udma.o \
                   ivtv-vbi.o ivtv-yuv.o
+ivtv-alsa-objs := ivtv-alsa-main.o ivtv-alsa-pcm.o
 
 obj-$(CONFIG_VIDEO_IVTV) += ivtv.o
+obj-$(CONFIG_VIDEO_IVTV_ALSA) += ivtv-alsa.o
 obj-$(CONFIG_VIDEO_FB_IVTV) += ivtvfb.o
 
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
+ccflags-y += -I$(srctree)/drivers/media/i2c
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-main.c b/drivers/media/pci/ivtv/ivtv-alsa-main.c
new file mode 100644 (file)
index 0000000..8deab16
--- /dev/null
@@ -0,0 +1,303 @@
+/*
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited for the cx18 driver
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/initval.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-version.h"
+#include "ivtv-alsa.h"
+#include "ivtv-alsa-mixer.h"
+#include "ivtv-alsa-pcm.h"
+
+int ivtv_alsa_debug;
+
+#define IVTV_DEBUG_ALSA_INFO(fmt, arg...) \
+       do { \
+               if (ivtv_alsa_debug & 2) \
+                       pr_info("%s: " fmt, "ivtv-alsa", ## arg); \
+       } while (0)
+
+module_param_named(debug, ivtv_alsa_debug, int, 0644);
+MODULE_PARM_DESC(debug,
+                "Debug level (bitmask). Default: 0\n"
+                "\t\t\t  1/0x0001: warning\n"
+                "\t\t\t  2/0x0002: info\n");
+
+MODULE_AUTHOR("Andy Walls");
+MODULE_DESCRIPTION("CX23415/CX23416 ALSA Interface");
+MODULE_SUPPORTED_DEVICE("CX23415/CX23416 MPEG2 encoder");
+MODULE_LICENSE("GPL");
+
+MODULE_VERSION(IVTV_VERSION);
+
+static inline
+struct snd_ivtv_card *to_snd_ivtv_card(struct v4l2_device *v4l2_dev)
+{
+       return to_ivtv(v4l2_dev)->alsa;
+}
+
+static inline
+struct snd_ivtv_card *p_to_snd_ivtv_card(struct v4l2_device **v4l2_dev)
+{
+       return container_of(v4l2_dev, struct snd_ivtv_card, v4l2_dev);
+}
+
+static void snd_ivtv_card_free(struct snd_ivtv_card *itvsc)
+{
+       if (itvsc == NULL)
+               return;
+
+       if (itvsc->v4l2_dev != NULL)
+               to_ivtv(itvsc->v4l2_dev)->alsa = NULL;
+
+       /* FIXME - take any other stopping actions needed */
+
+       kfree(itvsc);
+}
+
+static void snd_ivtv_card_private_free(struct snd_card *sc)
+{
+       if (sc == NULL)
+               return;
+       snd_ivtv_card_free(sc->private_data);
+       sc->private_data = NULL;
+       sc->private_free = NULL;
+}
+
+static int snd_ivtv_card_create(struct v4l2_device *v4l2_dev,
+                                      struct snd_card *sc,
+                                      struct snd_ivtv_card **itvsc)
+{
+       *itvsc = kzalloc(sizeof(struct snd_ivtv_card), GFP_KERNEL);
+       if (*itvsc == NULL)
+               return -ENOMEM;
+
+       (*itvsc)->v4l2_dev = v4l2_dev;
+       (*itvsc)->sc = sc;
+
+       sc->private_data = *itvsc;
+       sc->private_free = snd_ivtv_card_private_free;
+
+       return 0;
+}
+
+static int snd_ivtv_card_set_names(struct snd_ivtv_card *itvsc)
+{
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+       struct snd_card *sc = itvsc->sc;
+
+       /* sc->driver is used by alsa-lib's configurator: simple, unique */
+       strlcpy(sc->driver, "CX2341[56]", sizeof(sc->driver));
+
+       /* sc->shortname is a symlink in /proc/asound: IVTV-M -> cardN */
+       snprintf(sc->shortname,  sizeof(sc->shortname), "IVTV-%d",
+                itv->instance);
+
+       /* sc->longname is read from /proc/asound/cards */
+       snprintf(sc->longname, sizeof(sc->longname),
+                "CX2341[56] #%d %s TV/FM Radio/Line-In Capture",
+                itv->instance, itv->card_name);
+
+       return 0;
+}
+
+static int snd_ivtv_init(struct v4l2_device *v4l2_dev)
+{
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       struct snd_card *sc = NULL;
+       struct snd_ivtv_card *itvsc;
+       int ret;
+
+       /* Numbrs steps from "Writing an ALSA Driver" by Takashi Iwai */
+
+       /* (1) Check and increment the device index */
+       /* This is a no-op for us.  We'll use the itv->instance */
+
+       /* (2) Create a card instance */
+       ret = snd_card_create(SNDRV_DEFAULT_IDX1, /* use first available id */
+                             SNDRV_DEFAULT_STR1, /* xid from end of shortname*/
+                             THIS_MODULE, 0, &sc);
+       if (ret) {
+               IVTV_ALSA_ERR("%s: snd_card_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit;
+       }
+
+       /* (3) Create a main component */
+       ret = snd_ivtv_card_create(v4l2_dev, sc, &itvsc);
+       if (ret) {
+               IVTV_ALSA_ERR("%s: snd_ivtv_card_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+
+       /* (4) Set the driver ID and name strings */
+       snd_ivtv_card_set_names(itvsc);
+
+       /* (5) Create other components: mixer, PCM, & proc files */
+#if 0
+       ret = snd_ivtv_mixer_create(itvsc);
+       if (ret) {
+               IVTV_ALSA_WARN("%s: snd_ivtv_mixer_create() failed with err %d:"
+                              " proceeding anyway\n", __func__, ret);
+       }
+#endif
+
+       ret = snd_ivtv_pcm_create(itvsc);
+       if (ret) {
+               IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+       /* FIXME - proc files */
+
+       /* (7) Set the driver data and return 0 */
+       /* We do this out of normal order for PCI drivers to avoid races */
+       itv->alsa = itvsc;
+
+       /* (6) Register the card instance */
+       ret = snd_card_register(sc);
+       if (ret) {
+               itv->alsa = NULL;
+               IVTV_ALSA_ERR("%s: snd_card_register() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit_free;
+       }
+
+       return 0;
+
+err_exit_free:
+       if (sc != NULL)
+               snd_card_free(sc);
+       kfree(itvsc);
+err_exit:
+       return ret;
+}
+
+int ivtv_alsa_load(struct ivtv *itv)
+{
+       struct v4l2_device *v4l2_dev = &itv->v4l2_dev;
+       struct ivtv_stream *s;
+
+       if (v4l2_dev == NULL) {
+               pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n",
+                      __func__);
+               return 0;
+       }
+
+       itv = to_ivtv(v4l2_dev);
+       if (itv == NULL) {
+               pr_err("ivtv-alsa itv is NULL\n");
+               return 0;
+       }
+
+       s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+       if (s->vdev == NULL) {
+               IVTV_DEBUG_ALSA_INFO("%s: PCM stream for card is disabled - "
+                                    "skipping\n", __func__);
+               return 0;
+       }
+
+       if (itv->alsa != NULL) {
+               IVTV_ALSA_ERR("%s: struct snd_ivtv_card * already exists\n",
+                             __func__);
+               return 0;
+       }
+
+       if (snd_ivtv_init(v4l2_dev)) {
+               IVTV_ALSA_ERR("%s: failed to create struct snd_ivtv_card\n",
+                             __func__);
+       } else {
+               IVTV_DEBUG_ALSA_INFO("%s: created ivtv ALSA interface instance "
+                                    "\n", __func__);
+       }
+       return 0;
+}
+
+static int __init ivtv_alsa_init(void)
+{
+       pr_info("ivtv-alsa: module loading...\n");
+       ivtv_ext_init = &ivtv_alsa_load;
+       return 0;
+}
+
+static void __exit snd_ivtv_exit(struct snd_ivtv_card *itvsc)
+{
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+
+       /* FIXME - pointer checks & shutdown itvsc */
+
+       snd_card_free(itvsc->sc);
+       itv->alsa = NULL;
+}
+
+static int __exit ivtv_alsa_exit_callback(struct device *dev, void *data)
+{
+       struct v4l2_device *v4l2_dev = dev_get_drvdata(dev);
+       struct snd_ivtv_card *itvsc;
+
+       if (v4l2_dev == NULL) {
+               pr_err("ivtv-alsa: %s: struct v4l2_device * is NULL\n",
+                      __func__);
+               return 0;
+       }
+
+       itvsc = to_snd_ivtv_card(v4l2_dev);
+       if (itvsc == NULL) {
+               IVTV_ALSA_WARN("%s: struct snd_ivtv_card * is NULL\n",
+                              __func__);
+               return 0;
+       }
+
+       snd_ivtv_exit(itvsc);
+       return 0;
+}
+
+static void __exit ivtv_alsa_exit(void)
+{
+       struct device_driver *drv;
+       int ret;
+
+       pr_info("ivtv-alsa: module unloading...\n");
+
+       drv = driver_find("ivtv", &pci_bus_type);
+       ret = driver_for_each_device(drv, NULL, NULL, ivtv_alsa_exit_callback);
+       (void)ret;      /* suppress compiler warning */
+
+       ivtv_ext_init = NULL;
+       pr_info("ivtv-alsa: module unload complete\n");
+}
+
+module_init(ivtv_alsa_init);
+module_exit(ivtv_alsa_exit);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.c b/drivers/media/pci/ivtv/ivtv-alsa-mixer.c
new file mode 100644 (file)
index 0000000..33ec05b
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/device.h>
+#include <linux/spinlock.h>
+#include <linux/videodev2.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/control.h>
+#include <sound/tlv.h>
+
+#include "ivtv-alsa.h"
+#include "ivtv-driver.h"
+
+/*
+ * Note the cx25840-core volume scale is funny, due to the alignment of the
+ * scale with another chip's range:
+ *
+ * v4l2_control value  /512    indicated dB    actual dB       reg 0x8d4
+ * 0x0000 - 0x01ff       0     -119            -96             228
+ * 0x0200 - 0x02ff       1     -118            -96             228
+ * ...
+ * 0x2c00 - 0x2dff      22      -97            -96             228
+ * 0x2e00 - 0x2fff      23      -96            -96             228
+ * 0x3000 - 0x31ff      24      -95            -95             226
+ * ...
+ * 0xee00 - 0xefff     119        0              0              36
+ * ...
+ * 0xfe00 - 0xffff     127       +8             +8              20
+ */
+static inline int dB_to_cx25840_vol(int dB)
+{
+       if (dB < -96)
+               dB = -96;
+       else if (dB > 8)
+               dB = 8;
+       return (dB + 119) << 9;
+}
+
+static inline int cx25840_vol_to_dB(int v)
+{
+       if (v < (23 << 9))
+               v = (23 << 9);
+       else if (v > (127 << 9))
+               v = (127 << 9);
+       return (v >> 9) - 119;
+}
+
+static int snd_ivtv_mixer_tv_vol_info(struct snd_kcontrol *kcontrol,
+                                     struct snd_ctl_elem_info *uinfo)
+{
+       uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER;
+       uinfo->count = 1;
+       /* We're already translating values, just keep this control in dB */
+       uinfo->value.integer.min  = -96;
+       uinfo->value.integer.max  =   8;
+       uinfo->value.integer.step =   1;
+       return 0;
+}
+
+static int snd_ivtv_mixer_tv_vol_get(struct snd_kcontrol *kctl,
+                                    struct snd_ctl_elem_value *uctl)
+{
+       struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl);
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+       struct v4l2_control vctrl;
+       int ret;
+
+       vctrl.id = V4L2_CID_AUDIO_VOLUME;
+       vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+
+       snd_ivtv_lock(itvsc);
+       ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+       snd_ivtv_unlock(itvsc);
+
+       if (!ret)
+               uctl->value.integer.value[0] = cx25840_vol_to_dB(vctrl.value);
+       return ret;
+}
+
+static int snd_ivtv_mixer_tv_vol_put(struct snd_kcontrol *kctl,
+                                    struct snd_ctl_elem_value *uctl)
+{
+       struct snd_ivtv_card *itvsc = snd_kcontrol_chip(kctl);
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+       struct v4l2_control vctrl;
+       int ret;
+
+       vctrl.id = V4L2_CID_AUDIO_VOLUME;
+       vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+
+       snd_ivtv_lock(itvsc);
+
+       /* Fetch current state */
+       ret = v4l2_subdev_call(itv->sd_audio, core, g_ctrl, &vctrl);
+
+       if (ret ||
+           (cx25840_vol_to_dB(vctrl.value) != uctl->value.integer.value[0])) {
+
+               /* Set, if needed */
+               vctrl.value = dB_to_cx25840_vol(uctl->value.integer.value[0]);
+               ret = v4l2_subdev_call(itv->sd_audio, core, s_ctrl, &vctrl);
+               if (!ret)
+                       ret = 1; /* Indicate control was changed w/o error */
+       }
+       snd_ivtv_unlock(itvsc);
+
+       return ret;
+}
+
+
+/* This is a bit of overkill, the slider is already in dB internally */
+static DECLARE_TLV_DB_SCALE(snd_ivtv_mixer_tv_vol_db_scale, -9600, 100, 0);
+
+static struct snd_kcontrol_new snd_ivtv_mixer_tv_vol __initdata = {
+       .iface = SNDRV_CTL_ELEM_IFACE_MIXER,
+       .name = "Analog TV Capture Volume",
+       .access = SNDRV_CTL_ELEM_ACCESS_READWRITE |
+                 SNDRV_CTL_ELEM_ACCESS_TLV_READ,
+       .info = snd_ivtv_mixer_tv_volume_info,
+       .get = snd_ivtv_mixer_tv_volume_get,
+       .put = snd_ivtv_mixer_tv_volume_put,
+       .tlv.p = snd_ivtv_mixer_tv_vol_db_scale
+};
+
+/* FIXME - add mute switch and balance, bass, treble sliders:
+       V4L2_CID_AUDIO_MUTE
+
+       V4L2_CID_AUDIO_BALANCE
+
+       V4L2_CID_AUDIO_BASS
+       V4L2_CID_AUDIO_TREBLE
+*/
+
+/* FIXME - add stereo, lang1, lang2, mono menu */
+/* FIXME - add I2S volume */
+
+int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc)
+{
+       struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+       struct snd_card *sc = itvsc->sc;
+       int ret;
+
+       strlcpy(sc->mixername, "CX2341[56] Mixer", sizeof(sc->mixername));
+
+       ret = snd_ctl_add(sc, snd_ctl_new1(snd_ivtv_mixer_tv_vol, itvsc));
+       if (ret) {
+               IVTV_ALSA_WARN("%s: failed to add %s control, err %d\n",
+                              __func__, snd_ivtv_mixer_tv_vol.name, ret);
+       }
+       return ret;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-mixer.h b/drivers/media/pci/ivtv/ivtv-alsa-mixer.h
new file mode 100644 (file)
index 0000000..cdde367
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ *  ALSA mixer controls for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_ivtv_mixer_create(struct snd_ivtv_card *itvsc);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.c b/drivers/media/pci/ivtv/ivtv-alsa-pcm.c
new file mode 100644 (file)
index 0000000..f7022bd
--- /dev/null
@@ -0,0 +1,356 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.com>
+ *
+ *  Portions of this work were sponsored by ONELAN Limited for the cx18 driver
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/vmalloc.h>
+
+#include <media/v4l2-device.h>
+
+#include <sound/core.h>
+#include <sound/pcm.h>
+
+#include "ivtv-driver.h"
+#include "ivtv-queue.h"
+#include "ivtv-streams.h"
+#include "ivtv-fileops.h"
+#include "ivtv-alsa.h"
+
+static unsigned int pcm_debug;
+module_param(pcm_debug, int, 0644);
+MODULE_PARM_DESC(pcm_debug, "enable debug messages for pcm");
+
+#define dprintk(fmt, arg...) \
+       do { \
+               if (pcm_debug) \
+                       pr_info("ivtv-alsa-pcm %s: " fmt, __func__, ##arg); \
+       } while (0)
+
+static struct snd_pcm_hardware snd_ivtv_hw_capture = {
+       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
+               SNDRV_PCM_INFO_MMAP           |
+               SNDRV_PCM_INFO_INTERLEAVED    |
+               SNDRV_PCM_INFO_MMAP_VALID,
+
+       .formats = SNDRV_PCM_FMTBIT_S16_LE,
+
+       .rates = SNDRV_PCM_RATE_48000,
+
+       .rate_min = 48000,
+       .rate_max = 48000,
+       .channels_min = 2,
+       .channels_max = 2,
+       .buffer_bytes_max = 62720 * 8,  /* just about the value in usbaudio.c */
+       .period_bytes_min = 64,         /* 12544/2, */
+       .period_bytes_max = 12544,
+       .periods_min = 2,
+       .periods_max = 98,              /* 12544, */
+};
+
+void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *itvsc, u8 *pcm_data,
+                                size_t num_bytes)
+{
+       struct snd_pcm_substream *substream;
+       struct snd_pcm_runtime *runtime;
+       unsigned int oldptr;
+       unsigned int stride;
+       int period_elapsed = 0;
+       int length;
+
+       dprintk("ivtv alsa announce ptr=%p data=%p num_bytes=%zd\n", itvsc,
+               pcm_data, num_bytes);
+
+       substream = itvsc->capture_pcm_substream;
+       if (substream == NULL) {
+               dprintk("substream was NULL\n");
+               return;
+       }
+
+       runtime = substream->runtime;
+       if (runtime == NULL) {
+               dprintk("runtime was NULL\n");
+               return;
+       }
+
+       stride = runtime->frame_bits >> 3;
+       if (stride == 0) {
+               dprintk("stride is zero\n");
+               return;
+       }
+
+       length = num_bytes / stride;
+       if (length == 0) {
+               dprintk("%s: length was zero\n", __func__);
+               return;
+       }
+
+       if (runtime->dma_area == NULL) {
+               dprintk("dma area was NULL - ignoring\n");
+               return;
+       }
+
+       oldptr = itvsc->hwptr_done_capture;
+       if (oldptr + length >= runtime->buffer_size) {
+               unsigned int cnt =
+                       runtime->buffer_size - oldptr;
+               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+                      cnt * stride);
+               memcpy(runtime->dma_area, pcm_data + cnt * stride,
+                      length * stride - cnt * stride);
+       } else {
+               memcpy(runtime->dma_area + oldptr * stride, pcm_data,
+                      length * stride);
+       }
+       snd_pcm_stream_lock(substream);
+
+       itvsc->hwptr_done_capture += length;
+       if (itvsc->hwptr_done_capture >=
+           runtime->buffer_size)
+               itvsc->hwptr_done_capture -=
+                       runtime->buffer_size;
+
+       itvsc->capture_transfer_done += length;
+       if (itvsc->capture_transfer_done >=
+           runtime->period_size) {
+               itvsc->capture_transfer_done -=
+                       runtime->period_size;
+               period_elapsed = 1;
+       }
+
+       snd_pcm_stream_unlock(substream);
+
+       if (period_elapsed)
+               snd_pcm_period_elapsed(substream);
+}
+
+static int snd_ivtv_pcm_capture_open(struct snd_pcm_substream *substream)
+{
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+       struct snd_pcm_runtime *runtime = substream->runtime;
+       struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       struct ivtv_stream *s;
+       struct ivtv_open_id item;
+       int ret;
+
+       /* Instruct the CX2341[56] to start sending packets */
+       snd_ivtv_lock(itvsc);
+       s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+
+       v4l2_fh_init(&item.fh, s->vdev);
+       item.itv = itv;
+       item.type = s->type;
+
+       /* See if the stream is available */
+       if (ivtv_claim_stream(&item, item.type)) {
+               /* No, it's already in use */
+               snd_ivtv_unlock(itvsc);
+               return -EBUSY;
+       }
+
+       if (test_bit(IVTV_F_S_STREAMOFF, &s->s_flags) ||
+           test_and_set_bit(IVTV_F_S_STREAMING, &s->s_flags)) {
+               /* We're already streaming.  No additional action required */
+               snd_ivtv_unlock(itvsc);
+               return 0;
+       }
+
+
+       runtime->hw = snd_ivtv_hw_capture;
+       snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
+       itvsc->capture_pcm_substream = substream;
+       runtime->private_data = itv;
+
+       itv->pcm_announce_callback = ivtv_alsa_announce_pcm_data;
+
+       /* Not currently streaming, so start it up */
+       set_bit(IVTV_F_S_STREAMING, &s->s_flags);
+       ret = ivtv_start_v4l2_encode_stream(s);
+       snd_ivtv_unlock(itvsc);
+
+       return ret;
+}
+
+static int snd_ivtv_pcm_capture_close(struct snd_pcm_substream *substream)
+{
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+       struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       struct ivtv_stream *s;
+
+       /* Instruct the ivtv to stop sending packets */
+       snd_ivtv_lock(itvsc);
+       s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+       ivtv_stop_v4l2_encode_stream(s, 0);
+       clear_bit(IVTV_F_S_STREAMING, &s->s_flags);
+
+       ivtv_release_stream(s);
+
+       itv->pcm_announce_callback = NULL;
+       snd_ivtv_unlock(itvsc);
+
+       return 0;
+}
+
+static int snd_ivtv_pcm_ioctl(struct snd_pcm_substream *substream,
+                    unsigned int cmd, void *arg)
+{
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+       int ret;
+
+       snd_ivtv_lock(itvsc);
+       ret = snd_pcm_lib_ioctl(substream, cmd, arg);
+       snd_ivtv_unlock(itvsc);
+       return ret;
+}
+
+
+static int snd_pcm_alloc_vmalloc_buffer(struct snd_pcm_substream *subs,
+                                       size_t size)
+{
+       struct snd_pcm_runtime *runtime = subs->runtime;
+
+       dprintk("Allocating vbuffer\n");
+       if (runtime->dma_area) {
+               if (runtime->dma_bytes > size)
+                       return 0;
+
+               vfree(runtime->dma_area);
+       }
+       runtime->dma_area = vmalloc(size);
+       if (!runtime->dma_area)
+               return -ENOMEM;
+
+       runtime->dma_bytes = size;
+
+       return 0;
+}
+
+static int snd_ivtv_pcm_hw_params(struct snd_pcm_substream *substream,
+                        struct snd_pcm_hw_params *params)
+{
+       dprintk("%s called\n", __func__);
+
+       return snd_pcm_alloc_vmalloc_buffer(substream,
+                                          params_buffer_bytes(params));
+}
+
+static int snd_ivtv_pcm_hw_free(struct snd_pcm_substream *substream)
+{
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+       unsigned long flags;
+
+       spin_lock_irqsave(&itvsc->slock, flags);
+       if (substream->runtime->dma_area) {
+               dprintk("freeing pcm capture region\n");
+               vfree(substream->runtime->dma_area);
+               substream->runtime->dma_area = NULL;
+       }
+       spin_unlock_irqrestore(&itvsc->slock, flags);
+
+       return 0;
+}
+
+static int snd_ivtv_pcm_prepare(struct snd_pcm_substream *substream)
+{
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+
+       itvsc->hwptr_done_capture = 0;
+       itvsc->capture_transfer_done = 0;
+
+       return 0;
+}
+
+static int snd_ivtv_pcm_trigger(struct snd_pcm_substream *substream, int cmd)
+{
+       return 0;
+}
+
+static
+snd_pcm_uframes_t snd_ivtv_pcm_pointer(struct snd_pcm_substream *substream)
+{
+       unsigned long flags;
+       snd_pcm_uframes_t hwptr_done;
+       struct snd_ivtv_card *itvsc = snd_pcm_substream_chip(substream);
+
+       spin_lock_irqsave(&itvsc->slock, flags);
+       hwptr_done = itvsc->hwptr_done_capture;
+       spin_unlock_irqrestore(&itvsc->slock, flags);
+
+       return hwptr_done;
+}
+
+static struct page *snd_pcm_get_vmalloc_page(struct snd_pcm_substream *subs,
+                                            unsigned long offset)
+{
+       void *pageptr = subs->runtime->dma_area + offset;
+
+       return vmalloc_to_page(pageptr);
+}
+
+static struct snd_pcm_ops snd_ivtv_pcm_capture_ops = {
+       .open           = snd_ivtv_pcm_capture_open,
+       .close          = snd_ivtv_pcm_capture_close,
+       .ioctl          = snd_ivtv_pcm_ioctl,
+       .hw_params      = snd_ivtv_pcm_hw_params,
+       .hw_free        = snd_ivtv_pcm_hw_free,
+       .prepare        = snd_ivtv_pcm_prepare,
+       .trigger        = snd_ivtv_pcm_trigger,
+       .pointer        = snd_ivtv_pcm_pointer,
+       .page           = snd_pcm_get_vmalloc_page,
+};
+
+int snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc)
+{
+       struct snd_pcm *sp;
+       struct snd_card *sc = itvsc->sc;
+       struct v4l2_device *v4l2_dev = itvsc->v4l2_dev;
+       struct ivtv *itv = to_ivtv(v4l2_dev);
+       int ret;
+
+       ret = snd_pcm_new(sc, "CX2341[56] PCM",
+                         0, /* PCM device 0, the only one for this card */
+                         0, /* 0 playback substreams */
+                         1, /* 1 capture substream */
+                         &sp);
+       if (ret) {
+               IVTV_ALSA_ERR("%s: snd_ivtv_pcm_create() failed with err %d\n",
+                             __func__, ret);
+               goto err_exit;
+       }
+
+       spin_lock_init(&itvsc->slock);
+
+       snd_pcm_set_ops(sp, SNDRV_PCM_STREAM_CAPTURE,
+                       &snd_ivtv_pcm_capture_ops);
+       sp->info_flags = 0;
+       sp->private_data = itvsc;
+       strlcpy(sp->name, itv->card_name, sizeof(sp->name));
+
+       return 0;
+
+err_exit:
+       return ret;
+}
diff --git a/drivers/media/pci/ivtv/ivtv-alsa-pcm.h b/drivers/media/pci/ivtv/ivtv-alsa-pcm.h
new file mode 100644 (file)
index 0000000..5ab1831
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *  ALSA PCM device for the
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA
+ *  02111-1307  USA
+ */
+
+int __init snd_ivtv_pcm_create(struct snd_ivtv_card *itvsc);
+
+/* Used by ivtv driver to announce the PCM data to the module */
+void ivtv_alsa_announce_pcm_data(struct snd_ivtv_card *card, u8 *pcm_data,
+                                size_t num_bytes);
diff --git a/drivers/media/pci/ivtv/ivtv-alsa.h b/drivers/media/pci/ivtv/ivtv-alsa.h
new file mode 100644 (file)
index 0000000..4a0d8f2
--- /dev/null
@@ -0,0 +1,75 @@
+/*
+ *  ALSA interface to ivtv PCM capture streams
+ *
+ *  Copyright (C) 2009,2012  Andy Walls <awalls@md.metrocast.net>
+ *  Copyright (C) 2009  Devin Heitmueller <dheitmueller@kernellabs.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.
+ *
+ *  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
+ */
+
+struct snd_card;
+
+struct snd_ivtv_card {
+       struct v4l2_device *v4l2_dev;
+       struct snd_card *sc;
+       unsigned int capture_transfer_done;
+       unsigned int hwptr_done_capture;
+       struct snd_pcm_substream *capture_pcm_substream;
+       spinlock_t slock;
+};
+
+extern int ivtv_alsa_debug;
+
+/*
+ * File operations that manipulate the encoder or video or audio subdevices
+ * need to be serialized.  Use the same lock we use for v4l2 file ops.
+ */
+static inline void snd_ivtv_lock(struct snd_ivtv_card *itvsc)
+{
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+       mutex_lock(&itv->serialize_lock);
+}
+
+static inline void snd_ivtv_unlock(struct snd_ivtv_card *itvsc)
+{
+       struct ivtv *itv = to_ivtv(itvsc->v4l2_dev);
+       mutex_unlock(&itv->serialize_lock);
+}
+
+#define IVTV_ALSA_DBGFLG_WARN  (1 << 0)
+#define IVTV_ALSA_DBGFLG_INFO  (1 << 1)
+
+#define IVTV_ALSA_DEBUG(x, type, fmt, args...) \
+       do { \
+               if ((x) & ivtv_alsa_debug) \
+                       pr_info("%s-alsa: " type ": " fmt, \
+                               v4l2_dev->name , ## args); \
+       } while (0)
+
+#define IVTV_ALSA_DEBUG_WARN(fmt, args...) \
+       IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_WARN, "warning", fmt , ## args)
+
+#define IVTV_ALSA_DEBUG_INFO(fmt, args...) \
+       IVTV_ALSA_DEBUG(IVTV_ALSA_DBGFLG_INFO, "info", fmt , ## args)
+
+#define IVTV_ALSA_ERR(fmt, args...) \
+       pr_err("%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define IVTV_ALSA_WARN(fmt, args...) \
+       pr_warn("%s-alsa: " fmt, v4l2_dev->name , ## args)
+
+#define IVTV_ALSA_INFO(fmt, args...) \
+       pr_info("%s-alsa: " fmt, v4l2_dev->name , ## args)
similarity index 97%
rename from drivers/media/video/ivtv/ivtv-driver.c
rename to drivers/media/pci/ivtv/ivtv-driver.c
index 5462ce2f60ea9dc647572a0ae93796c26f1b3775..74e9a503236432b8c606ebfed56e87bca1fca10d 100644 (file)
    setting this to 1 you ensure that radio0 is now also radio1. */
 int ivtv_first_minor;
 
+/* Callback for registering extensions */
+int (*ivtv_ext_init)(struct ivtv *);
+EXPORT_SYMBOL(ivtv_ext_init);
+
 /* add your revision and whatnot here */
 static struct pci_device_id ivtv_pci_tbl[] __devinitdata = {
        {PCI_VENDOR_ID_ICOMP, PCI_DEVICE_ID_IVTV15,
@@ -279,6 +283,34 @@ MODULE_LICENSE("GPL");
 
 MODULE_VERSION(IVTV_VERSION);
 
+#if defined(CONFIG_MODULES) && defined(MODULE)
+static void request_module_async(struct work_struct *work)
+{
+       struct ivtv *dev = container_of(work, struct ivtv, request_module_wk);
+
+       /* Make sure ivtv-alsa module is loaded */
+       request_module("ivtv-alsa");
+
+       /* Initialize ivtv-alsa for this instance of the cx18 device */
+       if (ivtv_ext_init != NULL)
+               ivtv_ext_init(dev);
+}
+
+static void request_modules(struct ivtv *dev)
+{
+       INIT_WORK(&dev->request_module_wk, request_module_async);
+       schedule_work(&dev->request_module_wk);
+}
+
+static void flush_request_modules(struct ivtv *dev)
+{
+       flush_work_sync(&dev->request_module_wk);
+}
+#else
+#define request_modules(dev)
+#define flush_request_modules(dev)
+#endif /* CONFIG_MODULES */
+
 void ivtv_clear_irq_mask(struct ivtv *itv, u32 mask)
 {
        itv->irqmask &= ~mask;
@@ -1253,6 +1285,9 @@ static int __devinit ivtv_probe(struct pci_dev *pdev,
                goto free_streams;
        }
        IVTV_INFO("Initialized card: %s\n", itv->card_name);
+
+       /* Load ivtv submodules (ivtv-alsa) */
+       request_modules(itv);
        return 0;
 
 free_streams:
@@ -1290,6 +1325,7 @@ int ivtv_init_on_first_open(struct ivtv *itv)
        int video_input;
 
        fh.itv = itv;
+       fh.type = IVTV_ENC_STREAM_TYPE_MPG;
 
        if (test_bit(IVTV_F_I_FAILED, &itv->i_flags))
                return -ENXIO;
@@ -1380,6 +1416,8 @@ static void ivtv_remove(struct pci_dev *pdev)
 
        IVTV_DEBUG_INFO("Removing card\n");
 
+       flush_request_modules(itv);
+
        if (test_bit(IVTV_F_I_INITED, &itv->i_flags)) {
                /* Stop all captures */
                IVTV_DEBUG_INFO("Stopping all streams\n");
similarity index 98%
rename from drivers/media/video/ivtv/ivtv-driver.h
rename to drivers/media/pci/ivtv/ivtv-driver.h
index a7e00f8938f818a1b2a0730fac2517f5005d65fb..bc309f42c8ed29bb2782cb70521250b6f809c7d4 100644 (file)
@@ -259,6 +259,7 @@ struct ivtv_mailbox_data {
 #define IVTV_F_I_DEC_PAUSED       20   /* the decoder is paused */
 #define IVTV_F_I_INITED                   21   /* set after first open */
 #define IVTV_F_I_FAILED                   22   /* set if first open failed */
+#define IVTV_F_I_WORK_HANDLER_PCM  23  /* there is work to be done for PCM */
 
 /* Event notifications */
 #define IVTV_F_I_EV_DEC_STOPPED           28   /* decoder stopped event */
@@ -669,6 +670,13 @@ struct ivtv {
        atomic_t capturing;             /* count number of active capture streams */
        atomic_t decoding;              /* count number of active decoding streams */
 
+       /* ALSA interface for PCM capture stream */
+       struct snd_ivtv_card *alsa;
+       void (*pcm_announce_callback)(struct snd_ivtv_card *card, u8 *pcm_data,
+                                     size_t num_bytes);
+
+       /* Used for ivtv-alsa module loading */
+       struct work_struct request_module_wk;
 
        /* Interrupts & DMA */
        u32 irqmask;                    /* active interrupts */
@@ -752,6 +760,9 @@ static inline struct ivtv *to_ivtv(struct v4l2_device *v4l2_dev)
        return container_of(v4l2_dev, struct ivtv, v4l2_dev);
 }
 
+/* ivtv extensions to be loaded */
+extern int (*ivtv_ext_init)(struct ivtv *);
+
 /* Globals */
 extern int ivtv_first_minor;
 
similarity index 96%
rename from drivers/media/video/ivtv/ivtv-fileops.c
rename to drivers/media/pci/ivtv/ivtv-fileops.c
index 9ff69b5a87e2bda7294e29480f751ffdefd08ac2..9caffd8aa99513075fd9c4a86527c0c0bb3ba323 100644 (file)
@@ -41,7 +41,7 @@
    associated VBI streams are also automatically claimed.
    Possible error returns: -EBUSY if someone else has claimed
    the stream or 0 on success. */
-static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
+int ivtv_claim_stream(struct ivtv_open_id *id, int type)
 {
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[type];
@@ -96,6 +96,7 @@ static int ivtv_claim_stream(struct ivtv_open_id *id, int type)
        set_bit(IVTV_F_S_INTERNAL_USE, &s_vbi->s_flags);
        return 0;
 }
+EXPORT_SYMBOL(ivtv_claim_stream);
 
 /* This function releases a previously claimed stream. It will take into
    account associated VBI streams. */
@@ -146,6 +147,7 @@ void ivtv_release_stream(struct ivtv_stream *s)
        clear_bit(IVTV_F_S_CLAIMED, &s_vbi->s_flags);
        ivtv_flush_queues(s_vbi);
 }
+EXPORT_SYMBOL(ivtv_release_stream);
 
 static void ivtv_dualwatch(struct ivtv *itv)
 {
@@ -433,7 +435,7 @@ int ivtv_start_capture(struct ivtv_open_id *id)
            s->type == IVTV_DEC_STREAM_TYPE_YUV ||
            s->type == IVTV_DEC_STREAM_TYPE_VOUT) {
                /* you cannot read from these stream types. */
-               return -EPERM;
+               return -EINVAL;
        }
 
        /* Try to claim this stream. */
@@ -505,14 +507,17 @@ ssize_t ivtv_v4l2_read(struct file * filp, char __user *buf, size_t count, loff_
        struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
        struct ivtv_stream *s = &itv->streams[id->type];
-       int rc;
+       ssize_t rc;
 
        IVTV_DEBUG_HI_FILE("read %zd bytes from %s\n", count, s->name);
 
+       if (mutex_lock_interruptible(&itv->serialize_lock))
+               return -ERESTARTSYS;
        rc = ivtv_start_capture(id);
-       if (rc)
-               return rc;
-       return ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+       if (!rc)
+               rc = ivtv_read_pos(s, buf, count, pos, filp->f_flags & O_NONBLOCK);
+       mutex_unlock(&itv->serialize_lock);
+       return rc;
 }
 
 int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
@@ -540,7 +545,7 @@ int ivtv_start_decoding(struct ivtv_open_id *id, int speed)
        return 0;
 }
 
-ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+static ssize_t ivtv_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
 {
        struct ivtv_open_id *id = fh2id(filp->private_data);
        struct ivtv *itv = id->itv;
@@ -559,7 +564,7 @@ ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t c
            s->type != IVTV_DEC_STREAM_TYPE_YUV &&
            s->type != IVTV_DEC_STREAM_TYPE_VOUT)
                /* not decoder streams */
-               return -EPERM;
+               return -EINVAL;
 
        /* Try to claim this stream */
        if (ivtv_claim_stream(id, s->type))
@@ -712,6 +717,19 @@ retry:
        return bytes_written;
 }
 
+ssize_t ivtv_v4l2_write(struct file *filp, const char __user *user_buf, size_t count, loff_t *pos)
+{
+       struct ivtv_open_id *id = fh2id(filp->private_data);
+       struct ivtv *itv = id->itv;
+       ssize_t res;
+
+       if (mutex_lock_interruptible(&itv->serialize_lock))
+               return -ERESTARTSYS;
+       res = ivtv_write(filp, user_buf, count, pos);
+       mutex_unlock(&itv->serialize_lock);
+       return res;
+}
+
 unsigned int ivtv_v4l2_dec_poll(struct file *filp, poll_table *wait)
 {
        struct ivtv_open_id *id = fh2id(filp->private_data);
@@ -757,10 +775,13 @@ unsigned int ivtv_v4l2_enc_poll(struct file *filp, poll_table *wait)
 
        /* Start a capture if there is none */
        if (!eof && !test_bit(IVTV_F_S_STREAMING, &s->s_flags) &&
+                       s->type != IVTV_ENC_STREAM_TYPE_RAD &&
                        (req_events & (POLLIN | POLLRDNORM))) {
                int rc;
 
+               mutex_lock(&itv->serialize_lock);
                rc = ivtv_start_capture(id);
+               mutex_unlock(&itv->serialize_lock);
                if (rc) {
                        IVTV_DEBUG_INFO("Could not start capture for %s (%d)\n",
                                        s->name, rc);
@@ -863,6 +884,8 @@ int ivtv_v4l2_close(struct file *filp)
 
        IVTV_DEBUG_FILE("close %s\n", s->name);
 
+       mutex_lock(&itv->serialize_lock);
+
        /* Stop radio */
        if (id->type == IVTV_ENC_STREAM_TYPE_RAD &&
                        v4l2_fh_is_singular_file(filp)) {
@@ -892,10 +915,8 @@ int ivtv_v4l2_close(struct file *filp)
        v4l2_fh_exit(fh);
 
        /* Easy case first: this stream was never claimed by us */
-       if (s->fh != &id->fh) {
-               kfree(id);
-               return 0;
-       }
+       if (s->fh != &id->fh)
+               goto close_done;
 
        /* 'Unclaim' this stream */
 
@@ -913,11 +934,13 @@ int ivtv_v4l2_close(struct file *filp)
        } else {
                ivtv_stop_capture(id, 0);
        }
+close_done:
        kfree(id);
+       mutex_unlock(&itv->serialize_lock);
        return 0;
 }
 
-int ivtv_v4l2_open(struct file *filp)
+static int ivtv_open(struct file *filp)
 {
        struct video_device *vdev = video_devdata(filp);
        struct ivtv_stream *s = video_get_drvdata(vdev);
@@ -1020,6 +1043,18 @@ int ivtv_v4l2_open(struct file *filp)
        return 0;
 }
 
+int ivtv_v4l2_open(struct file *filp)
+{
+       struct video_device *vdev = video_devdata(filp);
+       int res;
+
+       if (mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
+       res = ivtv_open(filp);
+       mutex_unlock(vdev->lock);
+       return res;
+}
+
 void ivtv_mute(struct ivtv *itv)
 {
        if (atomic_read(&itv->capturing))
similarity index 94%
rename from drivers/media/video/ivtv/ivtv-fileops.h
rename to drivers/media/pci/ivtv/ivtv-fileops.h
index 049a2923965d9259713230f5612f150d69773f79..5e08800772ca64830f90d09a55197e5dde94f216 100644 (file)
@@ -37,8 +37,8 @@ void ivtv_mute(struct ivtv *itv);
 void ivtv_unmute(struct ivtv *itv);
 
 /* Utilities */
-
-/* Release a previously claimed stream. */
+/* Shared with ivtv-alsa module */
+int ivtv_claim_stream(struct ivtv_open_id *id, int type);
 void ivtv_release_stream(struct ivtv_stream *s);
 
 #endif
similarity index 98%
rename from drivers/media/video/ivtv/ivtv-firmware.c
rename to drivers/media/pci/ivtv/ivtv-firmware.c
index 02c5adebf517aac57248c473a60c793952629e75..6ec7705af55592015ed8ca07fc8e311866077d69 100644 (file)
@@ -396,3 +396,7 @@ int ivtv_firmware_check(struct ivtv *itv, char *where)
 
        return res;
 }
+
+MODULE_FIRMWARE(CX2341X_FIRM_ENC_FILENAME);
+MODULE_FIRMWARE(CX2341X_FIRM_DEC_FILENAME);
+MODULE_FIRMWARE(IVTV_DECODE_INIT_MPEG_FILENAME);
similarity index 95%
rename from drivers/media/video/ivtv/ivtv-ioctl.c
rename to drivers/media/pci/ivtv/ivtv-ioctl.c
index 32a591062d0b0b3b59f925c496d9cc60aa6ef230..949ae230e119b80caae93490186613d51bd5e151 100644 (file)
@@ -289,6 +289,8 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
        case V4L2_DEC_CMD_PAUSE:
                dc->flags &= V4L2_DEC_CMD_PAUSE_TO_BLACK;
                if (try) break;
+               if (!atomic_read(&itv->decoding))
+                       return -EPERM;
                if (itv->output_mode != OUT_MPG)
                        return -EBUSY;
                if (atomic_read(&itv->decoding) > 0) {
@@ -301,6 +303,8 @@ static int ivtv_video_command(struct ivtv *itv, struct ivtv_open_id *id,
        case V4L2_DEC_CMD_RESUME:
                dc->flags = 0;
                if (try) break;
+               if (!atomic_read(&itv->decoding))
+                       return -EPERM;
                if (itv->output_mode != OUT_MPG)
                        return -EBUSY;
                if (test_and_clear_bit(IVTV_F_I_DEC_PAUSED, &itv->i_flags)) {
@@ -326,6 +330,7 @@ static int ivtv_g_fmt_sliced_vbi_out(struct file *file, void *fh, struct v4l2_fo
        if (!(itv->v4l2_cap & V4L2_CAP_SLICED_VBI_OUTPUT))
                return -EINVAL;
        vbifmt->io_size = sizeof(struct v4l2_sliced_vbi_data) * 36;
+       memset(vbifmt->service_lines, 0, sizeof(vbifmt->service_lines));
        if (itv->is_60hz) {
                vbifmt->service_lines[0][21] = V4L2_SLICED_CAPTION_525;
                vbifmt->service_lines[1][21] = V4L2_SLICED_CAPTION_525;
@@ -393,6 +398,7 @@ static int ivtv_g_fmt_sliced_vbi_cap(struct file *file, void *fh, struct v4l2_fo
                vbifmt->service_set = itv->is_50hz ? V4L2_SLICED_VBI_625 :
                        V4L2_SLICED_VBI_525;
                ivtv_expand_service_set(vbifmt, itv->is_50hz);
+               vbifmt->service_set = ivtv_get_service_set(vbifmt);
                return 0;
        }
 
@@ -784,7 +790,7 @@ static int ivtv_g_audio(struct file *file, void *fh, struct v4l2_audio *vin)
        return ivtv_get_audio_input(itv, vin->index, vin);
 }
 
-static int ivtv_s_audio(struct file *file, void *fh, struct v4l2_audio *vout)
+static int ivtv_s_audio(struct file *file, void *fh, const struct v4l2_audio *vout)
 {
        struct ivtv *itv = fh2id(fh)->itv;
 
@@ -813,11 +819,13 @@ static int ivtv_g_audout(struct file *file, void *fh, struct v4l2_audioout *vin)
        return ivtv_get_audio_output(itv, vin->index, vin);
 }
 
-static int ivtv_s_audout(struct file *file, void *fh, struct v4l2_audioout *vout)
+static int ivtv_s_audout(struct file *file, void *fh, const struct v4l2_audioout *vout)
 {
        struct ivtv *itv = fh2id(fh)->itv;
 
-       return ivtv_get_audio_output(itv, vout->index, vout);
+       if (itv->card->video_outputs == NULL || vout->index != 0)
+               return -EINVAL;
+       return 0;
 }
 
 static int ivtv_enum_input(struct file *file, void *fh, struct v4l2_input *vin)
@@ -872,7 +880,7 @@ static int ivtv_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropca
        return 0;
 }
 
-static int ivtv_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+static int ivtv_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
@@ -920,51 +928,53 @@ static int ivtv_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
 
 static int ivtv_enum_fmt_vid_cap(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 {
-       static struct v4l2_fmtdesc formats[] = {
-               { 0, 0, 0,
-                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
-                 { 0, 0, 0, 0 }
-               },
-               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
-                 "MPEG", V4L2_PIX_FMT_MPEG,
-                 { 0, 0, 0, 0 }
-               }
+       static const struct v4l2_fmtdesc hm12 = {
+               0, V4L2_BUF_TYPE_VIDEO_CAPTURE, 0,
+               "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+               { 0, 0, 0, 0 }
+       };
+       static const struct v4l2_fmtdesc mpeg = {
+               0, V4L2_BUF_TYPE_VIDEO_CAPTURE, V4L2_FMT_FLAG_COMPRESSED,
+               "MPEG", V4L2_PIX_FMT_MPEG,
+               { 0, 0, 0, 0 }
        };
-       enum v4l2_buf_type type = fmt->type;
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-       if (fmt->index > 1)
+       if (fmt->index)
+               return -EINVAL;
+       if (s->type == IVTV_ENC_STREAM_TYPE_MPG)
+               *fmt = mpeg;
+       else if (s->type == IVTV_ENC_STREAM_TYPE_YUV)
+               *fmt = hm12;
+       else
                return -EINVAL;
-
-       *fmt = formats[fmt->index];
-       fmt->type = type;
        return 0;
 }
 
 static int ivtv_enum_fmt_vid_out(struct file *file, void *fh, struct v4l2_fmtdesc *fmt)
 {
-       struct ivtv *itv = fh2id(fh)->itv;
-
-       static struct v4l2_fmtdesc formats[] = {
-               { 0, 0, 0,
-                 "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
-                 { 0, 0, 0, 0 }
-               },
-               { 1, 0, V4L2_FMT_FLAG_COMPRESSED,
-                 "MPEG", V4L2_PIX_FMT_MPEG,
-                 { 0, 0, 0, 0 }
-               }
+       static const struct v4l2_fmtdesc hm12 = {
+               0, V4L2_BUF_TYPE_VIDEO_OUTPUT, 0,
+               "HM12 (YUV 4:2:0)", V4L2_PIX_FMT_HM12,
+               { 0, 0, 0, 0 }
+       };
+       static const struct v4l2_fmtdesc mpeg = {
+               0, V4L2_BUF_TYPE_VIDEO_OUTPUT, V4L2_FMT_FLAG_COMPRESSED,
+               "MPEG", V4L2_PIX_FMT_MPEG,
+               { 0, 0, 0, 0 }
        };
-       enum v4l2_buf_type type = fmt->type;
+       struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
-       if (!(itv->v4l2_cap & V4L2_CAP_VIDEO_OUTPUT))
+       if (fmt->index)
                return -EINVAL;
-
-       if (fmt->index > 1)
+       if (s->type == IVTV_DEC_STREAM_TYPE_MPG)
+               *fmt = mpeg;
+       else if (s->type == IVTV_DEC_STREAM_TYPE_YUV)
+               *fmt = hm12;
+       else
                return -EINVAL;
-
-       *fmt = formats[fmt->index];
-       fmt->type = type;
-
        return 0;
 }
 
@@ -980,6 +990,8 @@ static int ivtv_g_input(struct file *file, void *fh, unsigned int *i)
 int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       v4l2_std_id std;
+       int i;
 
        if (inp < 0 || inp >= itv->nof_inputs)
                return -EINVAL;
@@ -1001,6 +1013,13 @@ int ivtv_s_input(struct file *file, void *fh, unsigned int inp)
           input type. */
        itv->audio_input = itv->card->video_inputs[inp].audio_index;
 
+       if (itv->card->video_inputs[inp].video_type == IVTV_CARD_INPUT_VID_TUNER)
+               std = itv->tuner_std;
+       else
+               std = V4L2_STD_ALL;
+       for (i = 0; i <= IVTV_ENC_STREAM_TYPE_VBI; i++)
+               itv->streams[i].vdev->tvnorms = std;
+
        /* prevent others from messing with the streams until
           we're finished changing inputs. */
        ivtv_mute(itv);
@@ -1048,7 +1067,10 @@ static int ivtv_s_output(struct file *file, void *fh, unsigned int outp)
 static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
+       if (s->vdev->vfl_dir)
+               return -ENOTTY;
        if (vf->tuner != 0)
                return -EINVAL;
 
@@ -1059,7 +1081,10 @@ static int ivtv_g_frequency(struct file *file, void *fh, struct v4l2_frequency *
 int ivtv_s_frequency(struct file *file, void *fh, struct v4l2_frequency *vf)
 {
        struct ivtv *itv = fh2id(fh)->itv;
+       struct ivtv_stream *s = &itv->streams[fh2id(fh)->type];
 
+       if (s->vdev->vfl_dir)
+               return -ENOTTY;
        if (vf->tuner != 0)
                return -EINVAL;
 
@@ -1247,6 +1272,9 @@ static int ivtv_g_enc_index(struct file *file, void *fh, struct v4l2_enc_idx *id
        if (entries > V4L2_ENC_IDX_ENTRIES)
                entries = V4L2_ENC_IDX_ENTRIES;
        idx->entries = 0;
+       idx->entries_cap = IVTV_MAX_PGM_INDEX;
+       if (!atomic_read(&itv->capturing))
+               return 0;
        for (i = 0; i < entries; i++) {
                *e = itv->pgm_info[(itv->pgm_info_read_idx + i) % IVTV_MAX_PGM_INDEX];
                if ((e->flags & V4L2_ENC_IDX_FRAME_MASK) <= V4L2_ENC_IDX_FRAME_B) {
@@ -1427,7 +1455,7 @@ static int ivtv_g_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
        return 0;
 }
 
-static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
+static int ivtv_s_fbuf(struct file *file, void *fh, const struct v4l2_framebuffer *fb)
 {
        struct ivtv_open_id *id = fh2id(fh);
        struct ivtv *itv = id->itv;
@@ -1444,7 +1472,7 @@ static int ivtv_s_fbuf(struct file *file, void *fh, struct v4l2_framebuffer *fb)
        itv->osd_chroma_key_state = (fb->flags & V4L2_FBUF_FLAG_CHROMAKEY) != 0;
        ivtv_set_osd_alpha(itv);
        yi->track_osd = (fb->flags & V4L2_FBUF_FLAG_OVERLAY) != 0;
-       return ivtv_g_fbuf(file, fh, fb);
+       return 0;
 }
 
 static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
@@ -1460,7 +1488,7 @@ static int ivtv_overlay(struct file *file, void *fh, unsigned int on)
        return 0;
 }
 
-static int ivtv_subscribe_event(struct v4l2_fh *fh, struct v4l2_event_subscription *sub)
+static int ivtv_subscribe_event(struct v4l2_fh *fh, const struct v4l2_event_subscription *sub)
 {
        switch (sub->type) {
        case V4L2_EVENT_VSYNC:
similarity index 95%
rename from drivers/media/video/ivtv/ivtv-irq.c
rename to drivers/media/pci/ivtv/ivtv-irq.c
index 1b3b9578bf47657915b464e9b9513f48b481aa0e..19a7c9b990a393b93adb27818d069560f1027bda 100644 (file)
@@ -38,6 +38,34 @@ static const int ivtv_stream_map[] = {
        IVTV_ENC_STREAM_TYPE_VBI,
 };
 
+static void ivtv_pcm_work_handler(struct ivtv *itv)
+{
+       struct ivtv_stream *s = &itv->streams[IVTV_ENC_STREAM_TYPE_PCM];
+       struct ivtv_buffer *buf;
+
+       /* Pass the PCM data to ivtv-alsa */
+
+       while (1) {
+               /*
+                * Users should not be using both the ALSA and V4L2 PCM audio
+                * capture interfaces at the same time.  If the user is doing
+                * this, there maybe a buffer in q_io to grab, use, and put
+                * back in rotation.
+                */
+               buf = ivtv_dequeue(s, &s->q_io);
+               if (buf == NULL)
+                       buf = ivtv_dequeue(s, &s->q_full);
+               if (buf == NULL)
+                       break;
+
+               if (buf->readpos < buf->bytesused)
+                       itv->pcm_announce_callback(itv->alsa,
+                               (u8 *)(buf->buf + buf->readpos),
+                               (size_t)(buf->bytesused - buf->readpos));
+
+               ivtv_enqueue(s, buf, &s->q_free);
+       }
+}
 
 static void ivtv_pio_work_handler(struct ivtv *itv)
 {
@@ -83,6 +111,9 @@ void ivtv_irq_work_handler(struct kthread_work *work)
 
        if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_YUV, &itv->i_flags))
                ivtv_yuv_work_handler(itv);
+
+       if (test_and_clear_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags))
+               ivtv_pcm_work_handler(itv);
 }
 
 /* Determine the required DMA size, setup enough buffers in the predma queue and
@@ -293,7 +324,26 @@ static void dma_post(struct ivtv_stream *s)
                        return;
                }
        }
+
        ivtv_queue_move(s, &s->q_dma, NULL, &s->q_full, s->q_dma.bytesused);
+
+       if (s->type == IVTV_ENC_STREAM_TYPE_PCM &&
+           itv->pcm_announce_callback != NULL) {
+               /*
+                * Set up the work handler to pass the data to ivtv-alsa.
+                *
+                * We just use q_full and let the work handler race with users
+                * making ivtv-fileops.c calls on the PCM device node.
+                *
+                * Users should not be using both the ALSA and V4L2 PCM audio
+                * capture interfaces at the same time.  If the user does this,
+                * fragments of data will just go out each interface as they
+                * race for PCM data.
+                */
+               set_bit(IVTV_F_I_WORK_HANDLER_PCM, &itv->i_flags);
+               set_bit(IVTV_F_I_HAVE_WORK, &itv->i_flags);
+       }
+
        if (s->fh)
                wake_up(&s->waitq);
 }
similarity index 95%
rename from drivers/media/video/ivtv/ivtv-streams.c
rename to drivers/media/pci/ivtv/ivtv-streams.c
index 87990c5f0910331d9f692fa7cbd828ada8325a77..70dad588a677ca45b9b08ee8d4ab6d967add0185 100644 (file)
@@ -65,6 +65,14 @@ static const struct v4l2_file_operations ivtv_v4l2_dec_fops = {
        .poll = ivtv_v4l2_dec_poll,
 };
 
+static const struct v4l2_file_operations ivtv_v4l2_radio_fops = {
+       .owner = THIS_MODULE,
+       .open = ivtv_v4l2_open,
+       .unlocked_ioctl = video_ioctl2,
+       .release = ivtv_v4l2_close,
+       .poll = ivtv_v4l2_enc_poll,
+};
+
 #define IVTV_V4L2_DEC_MPG_OFFSET  16   /* offset from 0 to register decoder mpg v4l2 minors on */
 #define IVTV_V4L2_ENC_PCM_OFFSET  24   /* offset from 0 to register pcm v4l2 minors on */
 #define IVTV_V4L2_ENC_YUV_OFFSET  32   /* offset from 0 to register yuv v4l2 minors on */
@@ -77,14 +85,13 @@ static struct {
        int vfl_type;
        int num_offset;
        int dma, pio;
-       enum v4l2_buf_type buf_type;
        u32 v4l2_caps;
        const struct v4l2_file_operations *fops;
 } ivtv_stream_info[] = {
        {       /* IVTV_ENC_STREAM_TYPE_MPG */
                "encoder MPG",
                VFL_TYPE_GRABBER, 0,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE, 0,
                V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
                        V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_enc_fops
@@ -92,7 +99,7 @@ static struct {
        {       /* IVTV_ENC_STREAM_TYPE_YUV */
                "encoder YUV",
                VFL_TYPE_GRABBER, IVTV_V4L2_ENC_YUV_OFFSET,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VIDEO_CAPTURE,
+               PCI_DMA_FROMDEVICE, 0,
                V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_TUNER |
                        V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_enc_fops
@@ -100,7 +107,7 @@ static struct {
        {       /* IVTV_ENC_STREAM_TYPE_VBI */
                "encoder VBI",
                VFL_TYPE_VBI, 0,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_VBI_CAPTURE,
+               PCI_DMA_FROMDEVICE, 0,
                V4L2_CAP_VBI_CAPTURE | V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_TUNER |
                        V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_enc_fops
@@ -108,42 +115,42 @@ static struct {
        {       /* IVTV_ENC_STREAM_TYPE_PCM */
                "encoder PCM",
                VFL_TYPE_GRABBER, IVTV_V4L2_ENC_PCM_OFFSET,
-               PCI_DMA_FROMDEVICE, 0, V4L2_BUF_TYPE_PRIVATE,
+               PCI_DMA_FROMDEVICE, 0,
                V4L2_CAP_TUNER | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_enc_fops
        },
        {       /* IVTV_ENC_STREAM_TYPE_RAD */
                "encoder radio",
                VFL_TYPE_RADIO, 0,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_PRIVATE,
+               PCI_DMA_NONE, 1,
                V4L2_CAP_RADIO | V4L2_CAP_TUNER,
-               &ivtv_v4l2_enc_fops
+               &ivtv_v4l2_radio_fops
        },
        {       /* IVTV_DEC_STREAM_TYPE_MPG */
                "decoder MPG",
                VFL_TYPE_GRABBER, IVTV_V4L2_DEC_MPG_OFFSET,
-               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               PCI_DMA_TODEVICE, 0,
                V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_dec_fops
        },
        {       /* IVTV_DEC_STREAM_TYPE_VBI */
                "decoder VBI",
                VFL_TYPE_VBI, IVTV_V4L2_DEC_VBI_OFFSET,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_CAPTURE,
+               PCI_DMA_NONE, 1,
                V4L2_CAP_SLICED_VBI_CAPTURE | V4L2_CAP_READWRITE,
                &ivtv_v4l2_enc_fops
        },
        {       /* IVTV_DEC_STREAM_TYPE_VOUT */
                "decoder VOUT",
                VFL_TYPE_VBI, IVTV_V4L2_DEC_VOUT_OFFSET,
-               PCI_DMA_NONE, 1, V4L2_BUF_TYPE_VBI_OUTPUT,
+               PCI_DMA_NONE, 1,
                V4L2_CAP_SLICED_VBI_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_dec_fops
        },
        {       /* IVTV_DEC_STREAM_TYPE_YUV */
                "decoder YUV",
                VFL_TYPE_GRABBER, IVTV_V4L2_DEC_YUV_OFFSET,
-               PCI_DMA_TODEVICE, 0, V4L2_BUF_TYPE_VIDEO_OUTPUT,
+               PCI_DMA_TODEVICE, 0,
                V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_AUDIO | V4L2_CAP_READWRITE,
                &ivtv_v4l2_dec_fops
        }
@@ -223,15 +230,27 @@ static int ivtv_prep_dev(struct ivtv *itv, int type)
 
        s->vdev->num = num;
        s->vdev->v4l2_dev = &itv->v4l2_dev;
+       if (ivtv_stream_info[type].v4l2_caps &
+                       (V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_SLICED_VBI_OUTPUT))
+               s->vdev->vfl_dir = VFL_DIR_TX;
        s->vdev->fops = ivtv_stream_info[type].fops;
        s->vdev->ctrl_handler = itv->v4l2_dev.ctrl_handler;
        s->vdev->release = video_device_release;
        s->vdev->tvnorms = V4L2_STD_ALL;
        s->vdev->lock = &itv->serialize_lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &s->vdev->flags);
+       if (s->type == IVTV_DEC_STREAM_TYPE_VBI) {
+               v4l2_disable_ioctl(s->vdev, VIDIOC_S_AUDIO);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_G_AUDIO);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMAUDIO);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_ENUMINPUT);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_S_INPUT);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_G_INPUT);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_S_FREQUENCY);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_G_FREQUENCY);
+               v4l2_disable_ioctl(s->vdev, VIDIOC_S_TUNER);
+               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;
@@ -633,6 +652,7 @@ int ivtv_start_v4l2_encode_stream(struct ivtv_stream *s)
        atomic_inc(&itv->capturing);
        return 0;
 }
+EXPORT_SYMBOL(ivtv_start_v4l2_encode_stream);
 
 static int ivtv_setup_v4l2_decode_stream(struct ivtv_stream *s)
 {
@@ -889,6 +909,7 @@ int ivtv_stop_v4l2_encode_stream(struct ivtv_stream *s, int gop_end)
 
        return 0;
 }
+EXPORT_SYMBOL(ivtv_stop_v4l2_encode_stream);
 
 int ivtv_stop_v4l2_decode_stream(struct ivtv_stream *s, int flags, u64 pts)
 {
similarity index 62%
rename from drivers/media/dvb/mantis/Kconfig
rename to drivers/media/pci/mantis/Kconfig
index a13a50503134bbb1c9531b6140308ed8c6f83265..d3cc21633b94b7257257c0b8636eafa37ce9f45b 100644 (file)
@@ -10,15 +10,15 @@ config MANTIS_CORE
 config DVB_MANTIS
        tristate "MANTIS based cards"
        depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-       select DVB_MB86A16 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       select DVB_TDA665x if !DVB_FE_CUSTOMISE
-       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
+       select DVB_MB86A16 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA665x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_PLL
        help
          Support for PCI cards based on the Mantis PCI bridge.
@@ -29,7 +29,7 @@ config DVB_MANTIS
 config DVB_HOPPER
        tristate "HOPPER based cards"
        depends on MANTIS_CORE && DVB_CORE && PCI && I2C
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
        select DVB_PLL
        help
          Support for PCI cards based on the Hopper  PCI bridge.
similarity index 88%
rename from drivers/media/dvb/mantis/Makefile
rename to drivers/media/pci/mantis/Makefile
index ec8116dcb368cea9f43bebe1bc1e28f8f64915c0..f715051e4453bfd6a5319146d84913f5c982fe54 100644 (file)
@@ -25,4 +25,4 @@ obj-$(CONFIG_MANTIS_CORE)     += mantis_core.o
 obj-$(CONFIG_DVB_MANTIS)       += mantis.o
 obj-$(CONFIG_DVB_HOPPER)       += hopper.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
similarity index 99%
rename from drivers/media/dvb/mantis/mantis_cards.c
rename to drivers/media/pci/mantis/mantis_cards.c
index 095cf3a994e2d958620e2cbd5f93eb5b2d7e2cbd..0207d1f064e080ea2739a8c1a47d6d5a95c6dbcd 100644 (file)
@@ -275,7 +275,7 @@ static struct pci_device_id mantis_pci_table[] = {
        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2033_DVB_C, &vp2033_config),
        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_2040_DVB_C, &vp2040_config),
        MAKE_ENTRY(TECHNISAT, CABLESTAR_HD2, &vp2040_config),
-       MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2033_config),
+       MAKE_ENTRY(TERRATEC, CINERGY_C, &vp2040_config),
        MAKE_ENTRY(TWINHAN_TECHNOLOGIES, MANTIS_VP_3030_DVB_T, &vp3030_config),
        { }
 };
similarity index 99%
rename from drivers/media/dvb/mantis/mantis_core.c
rename to drivers/media/pci/mantis/mantis_core.c
index 22524a8e6f61ec735773bab8d8a7f610b7319ec1..684d9061fe2aced0c817a6c1191c1226be5aa3d5 100644 (file)
@@ -121,7 +121,7 @@ static void mantis_load_config(struct mantis_pci *mantis)
                mantis->hwconfig = &vp2033_mantis_config;
                break;
        case MANTIS_VP_2040_DVB_C:      /* VP-2040 */
-       case TERRATEC_CINERGY_C_PCI:    /* VP-2040 clone */
+       case CINERGY_C: /* VP-2040 clone */
        case TECHNISAT_CABLESTAR_HD2:
                mantis->hwconfig = &vp2040_mantis_config;
                break;
similarity index 98%
rename from drivers/media/dvb/mantis/mantis_dvb.c
rename to drivers/media/pci/mantis/mantis_dvb.c
index e5180e45d3100e72d8b0bb26758beccdca5a4b6d..5d15c6b74d9be621bb5cb8fecfae9ad50512804f 100644 (file)
@@ -248,8 +248,10 @@ int __devinit mantis_dvb_init(struct mantis_pci *mantis)
 err5:
        tasklet_kill(&mantis->tasklet);
        dvb_net_release(&mantis->dvbnet);
-       dvb_unregister_frontend(mantis->fe);
-       dvb_frontend_detach(mantis->fe);
+       if (mantis->fe) {
+               dvb_unregister_frontend(mantis->fe);
+               dvb_frontend_detach(mantis->fe);
+       }
 err4:
        mantis->demux.dmx.remove_frontend(&mantis->demux.dmx, &mantis->fe_mem);
 
diff --git a/drivers/media/pci/meye/Kconfig b/drivers/media/pci/meye/Kconfig
new file mode 100644 (file)
index 0000000..b4bf848
--- /dev/null
@@ -0,0 +1,13 @@
+config VIDEO_MEYE
+       tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
+       depends on PCI && SONY_LAPTOP && VIDEO_V4L2
+       ---help---
+         This is the video4linux driver for the Motion Eye camera found
+         in the Vaio Picturebook laptops. Please read the material in
+         <file:Documentation/video4linux/meye.txt> for more information.
+
+         If you say Y or M here, you need to say Y or M to "Sony Laptop
+         Extras" in the misc device section.
+
+         To compile this driver as a module, choose M here: the
+         module will be called meye.
diff --git a/drivers/media/pci/meye/Makefile b/drivers/media/pci/meye/Makefile
new file mode 100644 (file)
index 0000000..4938851
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_VIDEO_MEYE) += meye.o
diff --git a/drivers/media/pci/ngene/Kconfig b/drivers/media/pci/ngene/Kconfig
new file mode 100644 (file)
index 0000000..637d506
--- /dev/null
@@ -0,0 +1,13 @@
+config DVB_NGENE
+       tristate "Micronas nGene support"
+       depends on DVB_CORE && PCI && I2C
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2131 if MEDIA_SUBDRV_AUTOSELECT
+       ---help---
+         Support for Micronas PCI express cards with nGene bridge.
+
similarity index 63%
rename from drivers/media/dvb/ngene/Makefile
rename to drivers/media/pci/ngene/Makefile
index 13ebeffb705ffeee530c91e5859ef22e1512b66f..5c0b5d6b9d69b773f93b9d133f874ef75143fcb7 100644 (file)
@@ -6,9 +6,9 @@ ngene-objs := ngene-core.o ngene-i2c.o ngene-cards.o ngene-dvb.o
 
 obj-$(CONFIG_DVB_NGENE) += ngene.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
 
 # For the staging CI driver cxd2099
 ccflags-y += -Idrivers/staging/media/cxd2099/
similarity index 71%
rename from drivers/media/dvb/ngene/ngene-cards.c
rename to drivers/media/pci/ngene/ngene-cards.c
index 72ee8de0226025618ecd733716fa30f494eb646b..a6cd6959ad192a6207d96add36c69d6691ed3291 100644 (file)
@@ -42,6 +42,8 @@
 #include "mt2131.h"
 #include "tda18271c2dd.h"
 #include "drxk.h"
+#include "drxd.h"
+#include "dvb-pll.h"
 
 
 /****************************************************************************/
@@ -313,6 +315,235 @@ static int demod_attach_lg330x(struct ngene_channel *chan)
        return (chan->fe) ? 0 : -ENODEV;
 }
 
+static int demod_attach_drxd(struct ngene_channel *chan)
+{
+       struct drxd_config *feconf;
+
+       feconf = chan->dev->card_info->fe_config[chan->number];
+
+       chan->fe = dvb_attach(drxd_attach, feconf, chan,
+                       &chan->i2c_adapter, &chan->dev->pci_dev->dev);
+       if (!chan->fe) {
+               pr_err("No DRXD found!\n");
+               return -ENODEV;
+       }
+
+       if (!dvb_attach(dvb_pll_attach, chan->fe, feconf->pll_address,
+                       &chan->i2c_adapter,
+                       feconf->pll_type)) {
+               pr_err("No pll(%d) found!\n", feconf->pll_type);
+               return -ENODEV;
+       }
+       return 0;
+}
+
+/****************************************************************************/
+/* EEPROM TAGS **************************************************************/
+/****************************************************************************/
+
+#define MICNG_EE_START      0x0100
+#define MICNG_EE_END        0x0FF0
+
+#define MICNG_EETAG_END0    0x0000
+#define MICNG_EETAG_END1    0xFFFF
+
+/* 0x0001 - 0x000F reserved for housekeeping */
+/* 0xFFFF - 0xFFFE reserved for housekeeping */
+
+/* Micronas assigned tags
+   EEProm tags for hardware support */
+
+#define MICNG_EETAG_DRXD1_OSCDEVIATION  0x1000  /* 2 Bytes data */
+#define MICNG_EETAG_DRXD2_OSCDEVIATION  0x1001  /* 2 Bytes data */
+
+#define MICNG_EETAG_MT2060_1_1STIF      0x1100  /* 2 Bytes data */
+#define MICNG_EETAG_MT2060_2_1STIF      0x1101  /* 2 Bytes data */
+
+/* Tag range for OEMs */
+
+#define MICNG_EETAG_OEM_FIRST  0xC000
+#define MICNG_EETAG_OEM_LAST   0xFFEF
+
+static int i2c_write_eeprom(struct i2c_adapter *adapter,
+                           u8 adr, u16 reg, u8 data)
+{
+       u8 m[3] = {(reg >> 8), (reg & 0xff), data};
+       struct i2c_msg msg = {.addr = adr, .flags = 0, .buf = m,
+                             .len = sizeof(m)};
+
+       if (i2c_transfer(adapter, &msg, 1) != 1) {
+               pr_err(DEVICE_NAME ": Error writing EEPROM!\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+static int i2c_read_eeprom(struct i2c_adapter *adapter,
+                          u8 adr, u16 reg, u8 *data, int len)
+{
+       u8 msg[2] = {(reg >> 8), (reg & 0xff)};
+       struct i2c_msg msgs[2] = {{.addr = adr, .flags = 0,
+                                  .buf = msg, .len = 2 },
+                                 {.addr = adr, .flags = I2C_M_RD,
+                                  .buf = data, .len = len} };
+
+       if (i2c_transfer(adapter, msgs, 2) != 2) {
+               pr_err(DEVICE_NAME ": Error reading EEPROM\n");
+               return -EIO;
+       }
+       return 0;
+}
+
+static int ReadEEProm(struct i2c_adapter *adapter,
+                     u16 Tag, u32 MaxLen, u8 *data, u32 *pLength)
+{
+       int status = 0;
+       u16 Addr = MICNG_EE_START, Length, tag = 0;
+       u8  EETag[3];
+
+       while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+               if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+                       return -1;
+               tag = (EETag[0] << 8) | EETag[1];
+               if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+                       return -1;
+               if (tag == Tag)
+                       break;
+               Addr += sizeof(u16) + 1 + EETag[2];
+       }
+       if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+               pr_err(DEVICE_NAME
+                      ": Reached EOEE @ Tag = %04x Length = %3d\n",
+                      tag, EETag[2]);
+               return -1;
+       }
+       Length = EETag[2];
+       if (Length > MaxLen)
+               Length = (u16) MaxLen;
+       if (Length > 0) {
+               Addr += sizeof(u16) + 1;
+               status = i2c_read_eeprom(adapter, 0x50, Addr, data, Length);
+               if (!status) {
+                       *pLength = EETag[2];
+                       if (Length < EETag[2])
+                               ; /*status=STATUS_BUFFER_OVERFLOW; */
+               }
+       }
+       return status;
+}
+
+static int WriteEEProm(struct i2c_adapter *adapter,
+                      u16 Tag, u32 Length, u8 *data)
+{
+       int status = 0;
+       u16 Addr = MICNG_EE_START;
+       u8 EETag[3];
+       u16 tag = 0;
+       int retry, i;
+
+       while (Addr + sizeof(u16) + 1 < MICNG_EE_END) {
+               if (i2c_read_eeprom(adapter, 0x50, Addr, EETag, sizeof(EETag)))
+                       return -1;
+               tag = (EETag[0] << 8) | EETag[1];
+               if (tag == MICNG_EETAG_END0 || tag == MICNG_EETAG_END1)
+                       return -1;
+               if (tag == Tag)
+                       break;
+               Addr += sizeof(u16) + 1 + EETag[2];
+       }
+       if (Addr + sizeof(u16) + 1 + EETag[2] > MICNG_EE_END) {
+               pr_err(DEVICE_NAME
+                      ": Reached EOEE @ Tag = %04x Length = %3d\n",
+                      tag, EETag[2]);
+               return -1;
+       }
+
+       if (Length > EETag[2])
+               return -EINVAL;
+       /* Note: We write the data one byte at a time to avoid
+          issues with page sizes. (which are different for
+          each manufacture and eeprom size)
+        */
+       Addr += sizeof(u16) + 1;
+       for (i = 0; i < Length; i++, Addr++) {
+               status = i2c_write_eeprom(adapter, 0x50, Addr, data[i]);
+
+               if (status)
+                       break;
+
+               /* Poll for finishing write cycle */
+               retry = 10;
+               while (retry) {
+                       u8 Tmp;
+
+                       msleep(50);
+                       status = i2c_read_eeprom(adapter, 0x50, Addr, &Tmp, 1);
+                       if (status)
+                               break;
+                       if (Tmp != data[i])
+                               pr_err(DEVICE_NAME
+                                      "eeprom write error\n");
+                       retry -= 1;
+               }
+               if (status) {
+                       pr_err(DEVICE_NAME
+                              ": Timeout polling eeprom\n");
+                       break;
+               }
+       }
+       return status;
+}
+
+static int eeprom_read_ushort(struct i2c_adapter *adapter, u16 tag, u16 *data)
+{
+       int stat;
+       u8 buf[2];
+       u32 len = 0;
+
+       stat = ReadEEProm(adapter, tag, 2, buf, &len);
+       if (stat)
+               return stat;
+       if (len != 2)
+               return -EINVAL;
+
+       *data = (buf[0] << 8) | buf[1];
+       return 0;
+}
+
+static int eeprom_write_ushort(struct i2c_adapter *adapter, u16 tag, u16 data)
+{
+       int stat;
+       u8 buf[2];
+
+       buf[0] = data >> 8;
+       buf[1] = data & 0xff;
+       stat = WriteEEProm(adapter, tag, 2, buf);
+       if (stat)
+               return stat;
+       return 0;
+}
+
+static s16 osc_deviation(void *priv, s16 deviation, int flag)
+{
+       struct ngene_channel *chan = priv;
+       struct i2c_adapter *adap = &chan->i2c_adapter;
+       u16 data = 0;
+
+       if (flag) {
+               data = (u16) deviation;
+               pr_info(DEVICE_NAME ": write deviation %d\n",
+                      deviation);
+               eeprom_write_ushort(adap, 0x1000 + chan->number, data);
+       } else {
+               if (eeprom_read_ushort(adap, 0x1000 + chan->number, &data))
+                       data = 0;
+               pr_info(DEVICE_NAME ": read deviation %d\n",
+                      (s16) data);
+       }
+
+       return (s16) data;
+}
+
 /****************************************************************************/
 /* Switch control (I2C gates, etc.) *****************************************/
 /****************************************************************************/
@@ -464,6 +695,37 @@ static struct ngene_info ngene_info_m780 = {
        .fw_version     = 15,
 };
 
+static struct drxd_config fe_terratec_dvbt_0 = {
+       .index          = 0,
+       .demod_address  = 0x70,
+       .demod_revision = 0xa2,
+       .demoda_address = 0x00,
+       .pll_address    = 0x60,
+       .pll_type       = DVB_PLL_THOMSON_DTT7520X,
+       .clock          = 20000,
+       .osc_deviation  = osc_deviation,
+};
+
+static struct drxd_config fe_terratec_dvbt_1 = {
+       .index          = 1,
+       .demod_address  = 0x71,
+       .demod_revision = 0xa2,
+       .demoda_address = 0x00,
+       .pll_address    = 0x60,
+       .pll_type       = DVB_PLL_THOMSON_DTT7520X,
+       .clock          = 20000,
+       .osc_deviation  = osc_deviation,
+};
+
+static struct ngene_info ngene_info_terratec = {
+       .type           = NGENE_TERRATEC,
+       .name           = "Terratec Integra/Cinergy2400i Dual DVB-T",
+       .io_type        = {NGENE_IO_TSIN, NGENE_IO_TSIN},
+       .demod_attach   = {demod_attach_drxd, demod_attach_drxd},
+       .fe_config      = {&fe_terratec_dvbt_0, &fe_terratec_dvbt_1},
+       .i2c_access     = 1,
+};
+
 /****************************************************************************/
 
 
@@ -488,6 +750,7 @@ static const struct pci_device_id ngene_id_tbl[] __devinitdata = {
        NGENE_ID(0x18c3, 0xdd10, ngene_info_duoFlex),
        NGENE_ID(0x18c3, 0xdd20, ngene_info_duoFlex),
        NGENE_ID(0x1461, 0x062e, ngene_info_m780),
+       NGENE_ID(0x153b, 0x1167, ngene_info_terratec),
        {0}
 };
 MODULE_DEVICE_TABLE(pci, ngene_id_tbl);
similarity index 98%
rename from drivers/media/dvb/ngene/ngene-core.c
rename to drivers/media/pci/ngene/ngene-core.c
index 39857384af1072d6295938ab1ca504404f5c6208..c8e0d5b99d4c0d106bd02078ab1b678176d57b0d 100644 (file)
@@ -258,22 +258,16 @@ static void dump_command_io(struct ngene *dev)
        u8 buf[8], *b;
 
        ngcpyfrom(buf, HOST_TO_NGENE, 8);
-       printk(KERN_ERR "host_to_ngene (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               HOST_TO_NGENE, buf[0], buf[1], buf[2], buf[3],
-               buf[4], buf[5], buf[6], buf[7]);
+       printk(KERN_ERR "host_to_ngene (%04x): %*ph\n", HOST_TO_NGENE, 8, buf);
 
        ngcpyfrom(buf, NGENE_TO_HOST, 8);
-       printk(KERN_ERR "ngene_to_host (%04x): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               NGENE_TO_HOST, buf[0], buf[1], buf[2], buf[3],
-               buf[4], buf[5], buf[6], buf[7]);
+       printk(KERN_ERR "ngene_to_host (%04x): %*ph\n", NGENE_TO_HOST, 8, buf);
 
        b = dev->hosttongene;
-       printk(KERN_ERR "dev->hosttongene (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+       printk(KERN_ERR "dev->hosttongene (%p): %*ph\n", b, 8, b);
 
        b = dev->ngenetohost;
-       printk(KERN_ERR "dev->ngenetohost (%p): %02x %02x %02x %02x %02x %02x %02x %02x\n",
-               b, b[0], b[1], b[2], b[3], b[4], b[5], b[6], b[7]);
+       printk(KERN_ERR "dev->ngenetohost (%p): %*ph\n", b, 8, b);
 }
 
 static int ngene_command_mutex(struct ngene *dev, struct ngene_command *com)
diff --git a/drivers/media/pci/pluto2/Makefile b/drivers/media/pci/pluto2/Makefile
new file mode 100644 (file)
index 0000000..524bf84
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_PLUTO2) += pluto2.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
similarity index 56%
rename from drivers/media/dvb/pt1/Makefile
rename to drivers/media/pci/pt1/Makefile
index d80d8e8e7c572b7218bd1103e669ab50ed352f97..98e391295afeb676e72c702c77cd18229a96f2c2 100644 (file)
@@ -2,4 +2,4 @@ earth-pt1-objs := pt1.o va1j5jf8007s.o va1j5jf8007t.o
 
 obj-$(CONFIG_DVB_PT1) += earth-pt1.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/dvb-core -Idrivers/media/dvb-frontends
similarity index 98%
rename from drivers/media/dvb/pt1/va1j5jf8007s.c
rename to drivers/media/pci/pt1/va1j5jf8007s.c
index d980dfb21e5e1a2e78887ff51a9e2123c313a3dd..1b637b74ef589161fd1c195428bf90198c08b1df 100644 (file)
@@ -329,8 +329,8 @@ va1j5jf8007s_set_ts_id(struct va1j5jf8007s_state *state)
        u8 buf[3];
        struct i2c_msg msg;
 
-       ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
-       if (!ts_id)
+       ts_id = state->fe.dtv_property_cache.stream_id;
+       if (!ts_id || ts_id == NO_STREAM_ID_FILTER)
                return 0;
 
        buf[0] = 0x8f;
@@ -356,8 +356,8 @@ va1j5jf8007s_check_ts_id(struct va1j5jf8007s_state *state, int *lock)
        struct i2c_msg msgs[2];
        u32 ts_id;
 
-       ts_id = state->fe.dtv_property_cache.isdbs_ts_id;
-       if (!ts_id) {
+       ts_id = state->fe.dtv_property_cache.stream_id;
+       if (!ts_id || ts_id == NO_STREAM_ID_FILTER) {
                *lock = 1;
                return 0;
        }
@@ -587,7 +587,8 @@ static struct dvb_frontend_ops va1j5jf8007s_ops = {
                .frequency_stepsize = 1000,
                .caps = FE_CAN_INVERSION_AUTO | FE_CAN_FEC_AUTO |
                        FE_CAN_QAM_AUTO | FE_CAN_TRANSMISSION_MODE_AUTO |
-                       FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO,
+                       FE_CAN_GUARD_INTERVAL_AUTO | FE_CAN_HIERARCHY_AUTO |
+                       FE_CAN_MULTISTREAM,
        },
 
        .read_snr = va1j5jf8007s_read_snr,
similarity index 56%
rename from drivers/media/video/saa7134/Kconfig
rename to drivers/media/pci/saa7134/Kconfig
index 39fc0187a747c22bb9b2dbee2ff298bfc8974787..15b90d6e9130a79608933308c1773584a30fdb80 100644 (file)
@@ -5,7 +5,7 @@ config VIDEO_SAA7134
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select CRC32
-       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA6588 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This is a video4linux driver for Philips SAA713x based
          TV cards.
@@ -37,25 +37,25 @@ config VIDEO_SAA7134_DVB
        tristate "DVB/ATSC Support for saa7134 based TV cards"
        depends on VIDEO_SAA7134 && DVB_CORE
        select VIDEOBUF_DVB
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_MT352 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_NXT200X if !DVB_FE_CUSTOMISE
-       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-       select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       select DVB_ISL6421 if !DVB_FE_CUSTOMISE
-       select DVB_ISL6405 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select DVB_ZL10036 if !DVB_FE_CUSTOMISE
-       select DVB_MT312 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT3305 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_ZL10039 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_NXT200X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6421 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6405 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10036 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This adds support for DVB cards based on the
          Philips saa7134 chip.
similarity index 54%
rename from drivers/media/video/saa7134/Makefile
rename to drivers/media/pci/saa7134/Makefile
index da3899329f52bd9cad6e83d24643f84e4b4a24e0..35375480ed4d30cb2a57e2c82e1f16c3a23999e6 100644 (file)
@@ -1,5 +1,5 @@
 
-saa7134-y :=   saa7134-cards.o saa7134-core.o saa7134-i2c.o
+saa7134-y +=   saa7134-cards.o saa7134-core.o saa7134-i2c.o
 saa7134-y +=   saa7134-ts.o saa7134-tvaudio.o saa7134-vbi.o
 saa7134-y +=   saa7134-video.o
 saa7134-$(CONFIG_VIDEO_SAA7134_RC) += saa7134-input.o
@@ -10,7 +10,7 @@ obj-$(CONFIG_VIDEO_SAA7134_ALSA) += saa7134-alsa.o
 
 obj-$(CONFIG_VIDEO_SAA7134_DVB) += saa7134-dvb.o
 
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
+ccflags-y += -I$(srctree)/drivers/media/i2c
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
similarity index 99%
rename from drivers/media/video/saa7134/saa7134-dvb.c
rename to drivers/media/pci/saa7134/saa7134-dvb.c
index cc7f3d6ee966f955cbaac74dfa3670d453e7c963..b209de40a4f8d69373eb8600f140c613a48310b2 100644 (file)
@@ -1796,10 +1796,10 @@ static int dvb_init(struct saa7134_dev *dev)
                        dvb_attach(tda829x_attach, fe0->dvb.frontend,
                                   &dev->i2c_adap, 0x4b,
                                   &tda829x_no_probe);
+                       fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl;
                        dvb_attach(tda18271_attach, fe0->dvb.frontend,
                                   0x60, &dev->i2c_adap,
                                   &kworld_tda18271_config);
-                       fe0->dvb.frontend->ops.i2c_gate_ctrl = kworld_sbtvd_gate_ctrl;
                }
 
                /* mb86a20s need to use the I2C gateway */
@@ -1849,7 +1849,7 @@ static int dvb_init(struct saa7134_dev *dev)
 
        /* register everything else */
        ret = videobuf_dvb_register_bus(&dev->frontends, THIS_MODULE, dev,
-                                       &dev->pci->dev, adapter_nr, 0, NULL);
+                                       &dev->pci->dev, adapter_nr, 0);
 
        /* this sequence is necessary to make the tda1004x load its firmware
         * and to enter analog mode of hybrid boards
similarity index 99%
rename from drivers/media/video/saa7134/saa7134-input.c
rename to drivers/media/pci/saa7134/saa7134-input.c
index 05c6e217d8a7fc8d39c691cc5c4fc171e1022491..0f78f5e537e22723a26d1a8036e69ed3e5cdd5e3 100644 (file)
@@ -446,11 +446,8 @@ static void saa7134_input_timer(unsigned long data)
 static void ir_raw_decode_timer_end(unsigned long data)
 {
        struct saa7134_dev *dev = (struct saa7134_dev *)data;
-       struct saa7134_card_ir *ir = dev->remote;
 
        ir_raw_event_handle(dev->remote->dev);
-
-       ir->active = false;
 }
 
 static int __saa7134_ir_start(void *priv)
@@ -501,7 +498,6 @@ static int __saa7134_ir_start(void *priv)
        }
 
        ir->running = true;
-       ir->active = false;
 
        if (ir->polling) {
                setup_timer(&ir->timer, saa7134_input_timer,
@@ -532,7 +528,6 @@ static void __saa7134_ir_stop(void *priv)
        if (ir->polling || ir->raw_decode)
                del_timer_sync(&ir->timer);
 
-       ir->active = false;
        ir->running = false;
 
        return;
@@ -1035,10 +1030,11 @@ static int saa7134_raw_decode_irq(struct saa7134_dev *dev)
         * the event. This time is enough for NEC protocol. May need adjustments
         * to work with other protocols.
         */
-       if (!ir->active) {
+       smp_mb();
+
+       if (!timer_pending(&ir->timer)) {
                timeout = jiffies + msecs_to_jiffies(15);
                mod_timer(&ir->timer, timeout);
-               ir->active = true;
        }
 
        return 1;
similarity index 98%
rename from drivers/media/video/saa7134/saa7134-video.c
rename to drivers/media/pci/saa7134/saa7134-video.c
index 6de10b1e72519b86724e518d5b32d9fb53580a4c..22f8758d047f247084814db5e70a75a3b6edd6a6 100644 (file)
@@ -1953,11 +1953,12 @@ static int saa7134_g_crop(struct file *file, void *f, struct v4l2_crop *crop)
        return 0;
 }
 
-static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
+static int saa7134_s_crop(struct file *file, void *f, const struct v4l2_crop *crop)
 {
        struct saa7134_fh *fh = f;
        struct saa7134_dev *dev = fh->dev;
        struct v4l2_rect *b = &dev->crop_bounds;
+       struct v4l2_rect *c = &dev->crop_current;
 
        if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE &&
            crop->type != V4L2_BUF_TYPE_VIDEO_OVERLAY)
@@ -1972,21 +1973,20 @@ static int saa7134_s_crop(struct file *file, void *f, struct v4l2_crop *crop)
        if (res_locked(fh->dev, RESOURCE_VIDEO))
                return -EBUSY;
 
-       if (crop->c.top < b->top)
-               crop->c.top = b->top;
-       if (crop->c.top > b->top + b->height)
-               crop->c.top = b->top + b->height;
-       if (crop->c.height > b->top - crop->c.top + b->height)
-               crop->c.height = b->top - crop->c.top + b->height;
-
-       if (crop->c.left < b->left)
-               crop->c.left = b->left;
-       if (crop->c.left > b->left + b->width)
-               crop->c.left = b->left + b->width;
-       if (crop->c.width > b->left - crop->c.left + b->width)
-               crop->c.width = b->left - crop->c.left + b->width;
-
-       dev->crop_current = crop->c;
+       *c = crop->c;
+       if (c->top < b->top)
+               c->top = b->top;
+       if (c->top > b->top + b->height)
+               c->top = b->top + b->height;
+       if (c->height > b->top - c->top + b->height)
+               c->height = b->top - c->top + b->height;
+
+       if (c->left < b->left)
+               c->left = b->left;
+       if (c->left > b->left + b->width)
+               c->left = b->left + b->width;
+       if (c->width > b->left - c->left + b->width)
+               c->width = b->left - c->left + b->width;
        return 0;
 }
 
@@ -2089,7 +2089,7 @@ static int saa7134_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static int saa7134_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int saa7134_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
        return 0;
 }
@@ -2158,7 +2158,7 @@ static int saa7134_g_fbuf(struct file *file, void *f,
 }
 
 static int saa7134_s_fbuf(struct file *file, void *f,
-                                       struct v4l2_framebuffer *fb)
+                                       const struct v4l2_framebuffer *fb)
 {
        struct saa7134_fh *fh = f;
        struct saa7134_dev *dev = fh->dev;
@@ -2373,7 +2373,7 @@ static int radio_g_audio(struct file *file, void *priv,
 }
 
 static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
+                                       const struct v4l2_audio *a)
 {
        return 0;
 }
similarity index 99%
rename from drivers/media/video/saa7134/saa7134.h
rename to drivers/media/pci/saa7134/saa7134.h
index 89c8333736a28706a0c0e6ce42ef597921643f45..c24b6512bd8f8976f514c8a609f2238eaa2b9f45 100644 (file)
@@ -130,7 +130,6 @@ struct saa7134_card_ir {
        u32                     mask_keycode, mask_keydown, mask_keyup;
 
        bool                    running;
-       bool                    active;
 
        struct timer_list       timer;
 
diff --git a/drivers/media/pci/saa7146/Kconfig b/drivers/media/pci/saa7146/Kconfig
new file mode 100644 (file)
index 0000000..da88b77
--- /dev/null
@@ -0,0 +1,38 @@
+config VIDEO_HEXIUM_GEMINI
+       tristate "Hexium Gemini frame grabber"
+       depends on PCI && VIDEO_V4L2 && I2C
+       select VIDEO_SAA7146_VV
+       ---help---
+         This is a video4linux driver for the Hexium Gemini frame
+         grabber card by Hexium. Please note that the Gemini Dual
+         card is *not* fully supported.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hexium_gemini.
+
+config VIDEO_HEXIUM_ORION
+       tristate "Hexium HV-PCI6 and Orion frame grabber"
+       depends on PCI && VIDEO_V4L2 && I2C
+       select VIDEO_SAA7146_VV
+       ---help---
+         This is a video4linux driver for the Hexium HV-PCI6 and
+         Orion frame grabber cards by Hexium.
+
+         To compile this driver as a module, choose M here: the
+         module will be called hexium_orion.
+
+config VIDEO_MXB
+       tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
+       depends on PCI && VIDEO_V4L2 && I2C
+       select VIDEO_SAA7146_VV
+       select VIDEO_TUNER
+       select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TDA9840 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TEA6415C if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TEA6420 if MEDIA_SUBDRV_AUTOSELECT
+       ---help---
+         This is a video4linux driver for the 'Multimedia eXtension Board'
+         TV card by Siemens-Nixdorf.
+
+         To compile this driver as a module, choose M here: the
+         module will be called mxb.
diff --git a/drivers/media/pci/saa7146/Makefile b/drivers/media/pci/saa7146/Makefile
new file mode 100644 (file)
index 0000000..f3566a9
--- /dev/null
@@ -0,0 +1,5 @@
+obj-$(CONFIG_VIDEO_MXB) += mxb.o
+obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
+obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
+
+ccflags-y += -I$(srctree)/drivers/media/i2c
similarity index 99%
rename from drivers/media/video/mxb.c
rename to drivers/media/pci/saa7146/mxb.c
index b520a45cb3f328e0ec7785759a662ece47cfbc7a..91369daad72285005c14701c9dd0052d2e6adece 100644 (file)
@@ -646,7 +646,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
        struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
        struct mxb *mxb = (struct mxb *)dev->ext_priv;
similarity index 62%
rename from drivers/media/video/saa7164/Kconfig
rename to drivers/media/pci/saa7164/Kconfig
index 3532637251721a6b5cd05bd2bf7f1979f52911a8..a53db7d1c96e8b5a83dcc1d0997f6ebf18c8cb8c 100644 (file)
@@ -1,14 +1,14 @@
 config VIDEO_SAA7164
        tristate "NXP SAA7164 support"
-       depends on DVB_CORE && PCI && I2C
+       depends on DVB_CORE && VIDEO_DEV && PCI && I2C
        select I2C_ALGOBIT
        select FW_LOADER
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEOBUF_DVB
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This is a video4linux driver for NXP SAA7164 based
          TV cards.
similarity index 57%
rename from drivers/media/video/saa7164/Makefile
rename to drivers/media/pci/saa7164/Makefile
index 068443af30c8066e29c184d84788c9301ec592b2..ba0e33a1ee2488869544a06f15e57e2ef83a52a5 100644 (file)
@@ -4,9 +4,9 @@ saa7164-objs    := saa7164-cards.o saa7164-core.o saa7164-i2c.o saa7164-dvb.o \
 
 obj-$(CONFIG_VIDEO_SAA7164) += saa7164.o
 
-ccflags-y += -I$(srctree)/drivers/media/video
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
+ccflags-y += -I$(srctree)/drivers/media/i2c
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
 
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
similarity index 98%
rename from drivers/media/video/saa7164/saa7164-api.c
rename to drivers/media/pci/saa7164/saa7164-api.c
index c8799fdaae67d074e0bdbe64ea2bac4f752edb2f..eff7135cf0e8999beb790f0c406f0d7fdd1d772e 100644 (file)
@@ -670,7 +670,8 @@ int saa7164_api_set_dif(struct saa7164_port *port, u8 reg, u8 val)
        if (ret != SAA_OK)
                printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
 #if 0
-       saa7164_dumphex16(dev, buf, 16);
+       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf, 16,
+                      false);
 #endif
        return ret == SAA_OK ? 0 : -EIO;
 }
@@ -1352,7 +1353,8 @@ int saa7164_api_enum_subdevs(struct saa7164_dev *dev)
        }
 
        if (saa_debug & DBGLVL_API)
-               saa7164_dumphex16(dev, buf, (buflen/16)*16);
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
+                              buflen & ~15, false);
 
        saa7164_api_dump_subdevs(dev, buf, buflen);
 
@@ -1403,7 +1405,8 @@ int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
        dprintk(DBGLVL_API, "%s() len = %d bytes\n", __func__, len);
 
        if (saa_debug & DBGLVL_I2C)
-               saa7164_dumphex16(dev, buf, 2 * 16);
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1, buf,
+                              32, false);
 
        ret = saa7164_cmd_send(bus->dev, unitid, GET_CUR,
                EXU_REGISTER_ACCESS_CONTROL, len, &buf);
@@ -1411,7 +1414,8 @@ int saa7164_api_i2c_read(struct saa7164_i2c *bus, u8 addr, u32 reglen, u8 *reg,
                printk(KERN_ERR "%s() error, ret(2) = 0x%x\n", __func__, ret);
        else {
                if (saa_debug & DBGLVL_I2C)
-                       saa7164_dumphex16(dev, buf, sizeof(buf));
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      buf, sizeof(buf), false);
                memcpy(data, (buf + 2 * sizeof(u32) + reglen), datalen);
        }
 
@@ -1471,7 +1475,8 @@ int saa7164_api_i2c_write(struct saa7164_i2c *bus, u8 addr, u32 datalen,
        memcpy((buf + 2 * sizeof(u32)), data, datalen);
 
        if (saa_debug & DBGLVL_I2C)
-               saa7164_dumphex16(dev, buf, sizeof(buf));
+               print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                              buf, sizeof(buf), false);
 
        ret = saa7164_cmd_send(bus->dev, unitid, SET_CUR,
                EXU_REGISTER_ACCESS_CONTROL, len, &buf);
similarity index 96%
rename from drivers/media/video/saa7164/saa7164-core.c
rename to drivers/media/pci/saa7164/saa7164-core.c
index 3b7d7b4e303448187f6b74ee51b802d82c89ac0c..2c9ad878bef3dedab9c91a19019d7443d151affb 100644 (file)
@@ -92,28 +92,6 @@ LIST_HEAD(saa7164_devlist);
 
 #define INT_SIZE 16
 
-void saa7164_dumphex16FF(struct saa7164_dev *dev, u8 *buf, int len)
-{
-       int i;
-       u8 tmp[16];
-       memset(&tmp[0], 0xff, sizeof(tmp));
-
-       printk(KERN_INFO "--------------------> "
-               "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
-
-       for (i = 0; i < len; i += 16) {
-               if (memcmp(&tmp, buf + i, sizeof(tmp)) != 0) {
-                       printk(KERN_INFO "         [0x%08x] "
-                               "%02x %02x %02x %02x %02x %02x %02x %02x "
-                               "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
-                       *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
-                       *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
-                       *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
-                       *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
-               }
-       }
-}
-
 static void saa7164_pack_verifier(struct saa7164_buffer *buf)
 {
        u8 *p = (u8 *)buf->cpu;
@@ -125,7 +103,8 @@ static void saa7164_pack_verifier(struct saa7164_buffer *buf)
                        (*(p + i + 2) != 0x01) || (*(p + i + 3) != 0xBA)) {
                        printk(KERN_ERR "No pack at 0x%x\n", i);
 #if 0
-                       saa7164_dumphex16FF(buf->port->dev, (p + i), 32);
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      p + 1, 32, false);
 #endif
                }
        }
@@ -316,7 +295,8 @@ static void saa7164_work_enchandler_helper(struct saa7164_port *port, int bufnr)
                                                printk(KERN_ERR "%s() buf %p guard buffer breach\n",
                                                        __func__, buf);
 #if 0
-                                               saa7164_dumphex16FF(dev, (p + buf->actual_size) - 32 , 64);
+                       print_hex_dump(KERN_INFO, "", DUMP_PREFIX_OFFSET, 16, 1,
+                                      p + buf->actual_size - 32, 64, false);
 #endif
                                }
                        }
@@ -776,24 +756,6 @@ u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev)
        return reg;
 }
 
-/* TODO: Debugging func, remove */
-void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len)
-{
-       int i;
-
-       printk(KERN_INFO "--------------------> "
-               "00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f\n");
-
-       for (i = 0; i < len; i += 16)
-               printk(KERN_INFO "         [0x%08x] "
-                       "%02x %02x %02x %02x %02x %02x %02x %02x "
-                       "%02x %02x %02x %02x %02x %02x %02x %02x\n", i,
-               *(buf+i+0), *(buf+i+1), *(buf+i+2), *(buf+i+3),
-               *(buf+i+4), *(buf+i+5), *(buf+i+6), *(buf+i+7),
-               *(buf+i+8), *(buf+i+9), *(buf+i+10), *(buf+i+11),
-               *(buf+i+12), *(buf+i+13), *(buf+i+14), *(buf+i+15));
-}
-
 /* TODO: Debugging func, remove */
 void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr)
 {
similarity index 99%
rename from drivers/media/video/saa7164/saa7164.h
rename to drivers/media/pci/saa7164/saa7164.h
index 35219b9b0fbcc05844dac644aa82a268a5213fde..437284e747c973d5a3025eb1c39e989313891a08 100644 (file)
@@ -484,7 +484,6 @@ extern unsigned int vbi_buffers;
 /* ----------------------------------------------------------- */
 /* saa7164-core.c                                              */
 void saa7164_dumpregs(struct saa7164_dev *dev, u32 addr);
-void saa7164_dumphex16(struct saa7164_dev *dev, u8 *buf, int len);
 void saa7164_getfirmwarestatus(struct saa7164_dev *dev);
 u32 saa7164_getcurrentfirmwareversion(struct saa7164_dev *dev);
 void saa7164_histogram_update(struct saa7164_histogram *hg, u32 val);
diff --git a/drivers/media/pci/sta2x11/Kconfig b/drivers/media/pci/sta2x11/Kconfig
new file mode 100644 (file)
index 0000000..6749f67
--- /dev/null
@@ -0,0 +1,12 @@
+config STA2X11_VIP
+       tristate "STA2X11 VIP Video For Linux"
+       depends on STA2X11
+       select VIDEO_ADV7180 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEOBUF_DMA_CONTIG
+       depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS
+       help
+         Say Y for support for STA2X11 VIP (Video Input Port) capture
+         device.
+
+         To compile this driver as a module, choose M here: the
+         module will be called sta2x11_vip.
diff --git a/drivers/media/pci/sta2x11/Makefile b/drivers/media/pci/sta2x11/Makefile
new file mode 100644 (file)
index 0000000..d6c471d
--- /dev/null
@@ -0,0 +1 @@
+obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o
similarity index 66%
rename from drivers/media/dvb/ttpci/Kconfig
rename to drivers/media/pci/ttpci/Kconfig
index 9d83ced69dd6b9b2ace991cf2eca21565721b70d..314e417addaed8cc1cc25fd5e59b75a7fa7aaf06 100644 (file)
@@ -9,14 +9,14 @@ config DVB_AV7110
        select TTPCI_EEPROM
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
-       select DVB_VES1820 if !DVB_FE_CUSTOMISE
-       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-       select DVB_SP8870 if !DVB_FE_CUSTOMISE
-       select DVB_STV0297 if !DVB_FE_CUSTOMISE
-       select DVB_L64781 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_SP8870 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for SAA7146 and AV7110 based DVB cards as produced
          by Fujitsu-Siemens, Technotrend, Hauppauge and others.
@@ -63,19 +63,19 @@ config DVB_BUDGET_CORE
 config DVB_BUDGET
        tristate "Budget cards"
        depends on DVB_BUDGET_CORE && I2C
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-       select DVB_VES1820 if !DVB_FE_CUSTOMISE
-       select DVB_L64781 if !DVB_FE_CUSTOMISE
-       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1420 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10086 if !DVB_FE_CUSTOMISE
-       select DVB_TDA826X if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_ISL6423 if !DVB_FE_CUSTOMISE
-       select DVB_STV090x if !DVB_FE_CUSTOMISE
-       select DVB_STV6110x if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_L64781 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1420 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for simple SAA7146 based DVB cards (so called Budget-
          or Nova-PCI cards) without onboard MPEG2 decoder, and without
@@ -89,16 +89,16 @@ config DVB_BUDGET
 config DVB_BUDGET_CI
        tristate "Budget cards with onboard CI connector"
        depends on DVB_BUDGET_CORE && I2C
-       select DVB_STV0297 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_STB6100 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STV0288 if !DVB_FE_CUSTOMISE
-       select DVB_STB6000 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA827X if !MEDIA_TUNER_CUSTOMISE
+       select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT
        depends on RC_CORE
        help
          Support for simple SAA7146 based DVB cards
@@ -118,14 +118,14 @@ config DVB_BUDGET_AV
        depends on DVB_BUDGET_CORE && I2C
        select VIDEO_SAA7146_VV
        depends on VIDEO_DEV    # dependencies of VIDEO_SAA7146_VV
-       select DVB_PLL if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_TDA10021 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select DVB_STB0899 if !DVB_FE_CUSTOMISE
-       select DVB_TDA8261 if !DVB_FE_CUSTOMISE
-       select DVB_TUA6100 if !DVB_FE_CUSTOMISE
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10021 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA8261 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUA6100 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for simple SAA7146 based DVB cards
          (so called Budget- or Nova-PCI cards) without onboard
@@ -140,9 +140,9 @@ config DVB_BUDGET_PATCH
        tristate "AV7110 cards with Budget Patch"
        depends on DVB_BUDGET_CORE && I2C
        depends on DVB_AV7110
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_VES1X93 if !DVB_FE_CUSTOMISE
-       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_VES1X93 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for Budget Patch (full TS) modification on
          SAA7146+AV7110 based cards (DVB-S cards). This
similarity index 82%
rename from drivers/media/dvb/ttpci/Makefile
rename to drivers/media/pci/ttpci/Makefile
index f6e869372e303f3f7dfac8b497e2c0e76a40be6c..98905963ff085c0b0e265b7bf26ae0d892aa6a83 100644 (file)
@@ -17,5 +17,5 @@ obj-$(CONFIG_DVB_BUDGET_CI) += budget-ci.o
 obj-$(CONFIG_DVB_BUDGET_PATCH) += budget-patch.o
 obj-$(CONFIG_DVB_AV7110) += dvb-ttpci.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/ -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners
similarity index 99%
rename from drivers/media/dvb/ttpci/av7110_v4l.c
rename to drivers/media/pci/ttpci/av7110_v4l.c
index 1b2d15140a1d938f63269b1d94c224e36197b976..730e906ea912d12d810be017aa885372c476af86 100644 (file)
@@ -526,7 +526,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
        struct saa7146_dev *dev = ((struct saa7146_fh *)fh)->dev;
        struct av7110 *av7110 = (struct av7110 *)dev->ext_priv;
similarity index 91%
rename from drivers/media/dvb/ttpci/budget.c
rename to drivers/media/pci/ttpci/budget.c
index b21bcce667088a2d0f09cf66cab7d9985a72427b..7e6e43ae5c5151a3b5a8411e884594552c0f64c4 100644 (file)
@@ -50,6 +50,8 @@
 #include "stv6110x.h"
 #include "stv090x.h"
 #include "isl6423.h"
+#include "lnbh24.h"
+
 
 static int diseqc_method;
 module_param(diseqc_method, int, 0444);
@@ -679,6 +681,62 @@ static void frontend_init(struct budget *budget)
                        }
                }
                break;
+
+       case 0x1020: { /* Omicom S2 */
+                       struct stv6110x_devctl *ctl;
+                       saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTLO);
+                       msleep(50);
+                       saa7146_setgpio(budget->dev, 2, SAA7146_GPIO_OUTHI);
+                       msleep(250);
+
+                       budget->dvb_frontend = dvb_attach(stv090x_attach,
+                                                         &tt1600_stv090x_config,
+                                                         &budget->i2c_adap,
+                                                         STV090x_DEMODULATOR_0);
+
+                       if (budget->dvb_frontend) {
+                               printk(KERN_INFO "budget: Omicom S2 detected\n");
+
+                               ctl = dvb_attach(stv6110x_attach,
+                                                budget->dvb_frontend,
+                                                &tt1600_stv6110x_config,
+                                                &budget->i2c_adap);
+
+                               if (ctl) {
+                                       tt1600_stv090x_config.tuner_init          = ctl->tuner_init;
+                                       tt1600_stv090x_config.tuner_sleep         = ctl->tuner_sleep;
+                                       tt1600_stv090x_config.tuner_set_mode      = ctl->tuner_set_mode;
+                                       tt1600_stv090x_config.tuner_set_frequency = ctl->tuner_set_frequency;
+                                       tt1600_stv090x_config.tuner_get_frequency = ctl->tuner_get_frequency;
+                                       tt1600_stv090x_config.tuner_set_bandwidth = ctl->tuner_set_bandwidth;
+                                       tt1600_stv090x_config.tuner_get_bandwidth = ctl->tuner_get_bandwidth;
+                                       tt1600_stv090x_config.tuner_set_bbgain    = ctl->tuner_set_bbgain;
+                                       tt1600_stv090x_config.tuner_get_bbgain    = ctl->tuner_get_bbgain;
+                                       tt1600_stv090x_config.tuner_set_refclk    = ctl->tuner_set_refclk;
+                                       tt1600_stv090x_config.tuner_get_status    = ctl->tuner_get_status;
+
+                                       /* call the init function once to initialize
+                                          tuner's clock output divider and demod's
+                                          master clock */
+                                       if (budget->dvb_frontend->ops.init)
+                                               budget->dvb_frontend->ops.init(budget->dvb_frontend);
+
+                                       if (dvb_attach(lnbh24_attach,
+                                                       budget->dvb_frontend,
+                                                       &budget->i2c_adap,
+                                                       LNBH24_PCL | LNBH24_TTX,
+                                                       LNBH24_TEN, 0x14>>1) == NULL) {
+                                               printk(KERN_ERR
+                                               "No LNBH24 found!\n");
+                                               goto error_out;
+                                       }
+                               } else {
+                                       printk(KERN_ERR "%s: No STV6110(A) Silicon Tuner found!\n", __func__);
+                                       goto error_out;
+                               }
+                       }
+               }
+               break;
        }
 
        if (budget->dvb_frontend == NULL) {
@@ -759,6 +817,7 @@ MAKE_BUDGET_INFO(fsacs0, "Fujitsu Siemens Activy Budget-S PCI (rev GR/grundig fr
 MAKE_BUDGET_INFO(fsacs1, "Fujitsu Siemens Activy Budget-S PCI (rev AL/alps frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsact,         "Fujitsu Siemens Activy Budget-T PCI (rev GR/Grundig frontend)", BUDGET_FS_ACTIVY);
 MAKE_BUDGET_INFO(fsact1, "Fujitsu Siemens Activy Budget-T PCI (rev AL/ALPS TDHD1-204A)", BUDGET_FS_ACTIVY);
+MAKE_BUDGET_INFO(omicom, "Omicom S2 PCI", BUDGET_TT);
 
 static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(ttbs,  0x13c2, 0x1003),
@@ -772,6 +831,7 @@ static struct pci_device_id pci_tbl[] = {
        MAKE_EXTENSION_PCI(fsacs0,0x1131, 0x4f61),
        MAKE_EXTENSION_PCI(fsact1, 0x1131, 0x5f60),
        MAKE_EXTENSION_PCI(fsact, 0x1131, 0x5f61),
+       MAKE_EXTENSION_PCI(omicom, 0x14c4, 0x1020),
        {
                .vendor    = 0,
        }
similarity index 71%
rename from drivers/media/video/zoran/Kconfig
rename to drivers/media/pci/zoran/Kconfig
index fd4120e4c104490d9cbb0f6bda4971b049e673a5..26ca8702e33f3449d1b03bd441fb1b139804b753 100644 (file)
@@ -14,8 +14,8 @@ config VIDEO_ZORAN
 config VIDEO_ZORAN_DC30
        tristate "Pinnacle/Miro DC30(+) support"
        depends on VIDEO_ZORAN
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_VPX3220 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_VPX3220 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for the Pinnacle/Miro DC30(+) MJPEG capture/playback
          card. This also supports really old DC10 cards based on the
@@ -32,16 +32,16 @@ config VIDEO_ZORAN_ZR36060
 config VIDEO_ZORAN_BUZ
        tristate "Iomega Buz support"
        depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_SAA7185 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_SAA7185 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for the Iomega Buz MJPEG capture/playback card.
 
 config VIDEO_ZORAN_DC10
        tristate "Pinnacle/Miro DC10(+) support"
        depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA7110 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7175 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA7110 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_ADV7175 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for the Pinnacle/Miro DC10(+) MJPEG capture/playback
          card.
@@ -49,8 +49,8 @@ config VIDEO_ZORAN_DC10
 config VIDEO_ZORAN_LML33
        tristate "Linux Media Labs LML33 support"
        depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_BT819 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_BT819 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for the Linux Media Labs LML33 MJPEG capture/playback
          card.
@@ -58,17 +58,17 @@ config VIDEO_ZORAN_LML33
 config VIDEO_ZORAN_LML33R10
        tristate "Linux Media Labs LML33R10 support"
        depends on VIDEO_ZORAN_ZR36060
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_ADV7170 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_ADV7170 if MEDIA_SUBDRV_AUTOSELECT
        help
          support for the Linux Media Labs LML33R10 MJPEG capture/playback
          card.
 
 config VIDEO_ZORAN_AVS6EYES
-       tristate "AverMedia 6 Eyes support (EXPERIMENTAL)"
-       depends on VIDEO_ZORAN_ZR36060 && EXPERIMENTAL
-       select VIDEO_BT856 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_BT866 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_KS0127 if VIDEO_HELPER_CHIPS_AUTO
+       tristate "AverMedia 6 Eyes support"
+       depends on VIDEO_ZORAN_ZR36060
+       select VIDEO_BT856 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_BT866 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_KS0127 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for the AverMedia 6 Eyes video surveillance card.
similarity index 99%
rename from drivers/media/video/zoran/zoran_card.c
rename to drivers/media/pci/zoran/zoran_card.c
index c3602d6cd48e839f9fa1cadbad9e8ab9e4e9bcc6..fffc54b452c8aa8f510928eaa40c7e99171f8d3f 100644 (file)
@@ -1055,6 +1055,10 @@ zr36057_init (struct zoran *zr)
        memcpy(zr->video_dev, &zoran_template, sizeof(zoran_template));
        zr->video_dev->parent = &zr->pci_dev->dev;
        strcpy(zr->video_dev->name, ZR_DEVNAME(zr));
+       /* It's not a mem2mem device, but you can both capture and output from
+          one and the same device. This should really be split up into two
+          device nodes, but that's a job for another day. */
+       zr->video_dev->vfl_dir = VFL_DIR_M2M;
        err = video_register_device(zr->video_dev, VFL_TYPE_GRABBER, video_nr[zr->id]);
        if (err < 0)
                goto exit_free;
similarity index 99%
rename from drivers/media/video/zoran/zoran_driver.c
rename to drivers/media/pci/zoran/zoran_driver.c
index c6ccdeb6d8d6e50bb0db8c624c97e7b19ca9b7ac..53f12c7466b0b971218c2c1c6d769fa0d3f32461 100644 (file)
@@ -1978,7 +1978,7 @@ static int zoran_g_fbuf(struct file *file, void *__fh,
 }
 
 static int zoran_s_fbuf(struct file *file, void *__fh,
-               struct v4l2_framebuffer *fb)
+               const struct v4l2_framebuffer *fb)
 {
        struct zoran_fh *fh = __fh;
        struct zoran *zr = fh->zr;
@@ -2598,7 +2598,7 @@ gcrop_unlock_and_return:
        return res;
 }
 
-static int zoran_s_crop(struct file *file, void *__fh, struct v4l2_crop *crop)
+static int zoran_s_crop(struct file *file, void *__fh, const struct v4l2_crop *crop)
 {
        struct zoran_fh *fh = __fh;
        struct zoran *zr = fh->zr;
@@ -2674,7 +2674,7 @@ static int zoran_g_jpegcomp(struct file *file, void *__fh,
 }
 
 static int zoran_s_jpegcomp(struct file *file, void *__fh,
-                                       struct v4l2_jpegcompression *params)
+                                       const struct v4l2_jpegcompression *params)
 {
        struct zoran_fh *fh = __fh;
        struct zoran *zr = fh->zr;
@@ -2701,7 +2701,7 @@ static int zoran_s_jpegcomp(struct file *file, void *__fh,
        if (!fh->buffers.allocated)
                fh->buffers.buffer_size =
                        zoran_v4l2_calc_bufsize(&fh->jpg_settings);
-       fh->jpg_settings.jpg_comp = *params = settings.jpg_comp;
+       fh->jpg_settings.jpg_comp = settings.jpg_comp;
 sjpegc_unlock_and_return:
        mutex_unlock(&zr->resource_lock);
 
diff --git a/drivers/media/platform/Kconfig b/drivers/media/platform/Kconfig
new file mode 100644 (file)
index 0000000..f588d62
--- /dev/null
@@ -0,0 +1,223 @@
+#
+# Platform drivers
+#      All drivers here are currently for webcam support
+
+menuconfig V4L_PLATFORM_DRIVERS
+       bool "V4L platform devices"
+       depends on MEDIA_CAMERA_SUPPORT
+       default n
+       ---help---
+         Say Y here to enable support for platform-specific V4L drivers.
+
+if V4L_PLATFORM_DRIVERS
+
+source "drivers/media/platform/marvell-ccic/Kconfig"
+
+config VIDEO_VIA_CAMERA
+       tristate "VIAFB camera controller support"
+       depends on FB_VIA
+       select VIDEOBUF_DMA_SG
+       select VIDEO_OV7670
+       help
+          Driver support for the integrated camera controller in VIA
+          Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
+          with ov7670 sensors.
+
+#
+# Platform multimedia device configuration
+#
+
+source "drivers/media/platform/davinci/Kconfig"
+
+source "drivers/media/platform/omap/Kconfig"
+
+source "drivers/media/platform/blackfin/Kconfig"
+
+config VIDEO_SH_VOU
+       tristate "SuperH VOU video output driver"
+       depends on MEDIA_CAMERA_SUPPORT
+       depends on VIDEO_DEV && ARCH_SHMOBILE
+       select VIDEOBUF_DMA_CONTIG
+       help
+         Support for the Video Output Unit (VOU) on SuperH SoCs.
+
+config VIDEO_VIU
+       tristate "Freescale VIU Video Driver"
+       depends on VIDEO_V4L2 && PPC_MPC512x
+       select VIDEOBUF_DMA_CONTIG
+       default y
+       ---help---
+         Support for Freescale VIU video driver. This device captures
+         video data, or overlays video on DIU frame buffer.
+
+         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
+         In doubt, say N.
+
+config VIDEO_TIMBERDALE
+       tristate "Support for timberdale Video In/LogiWIN"
+       depends on VIDEO_V4L2 && I2C && DMADEVICES
+       select DMA_ENGINE
+       select TIMB_DMA
+       select VIDEO_ADV7180
+       select VIDEOBUF_DMA_CONTIG
+       ---help---
+         Add support for the Video In peripherial of the timberdale FPGA.
+
+config VIDEO_VINO
+       tristate "SGI Vino Video For Linux"
+       depends on I2C && SGI_IP22 && VIDEO_V4L2
+       select VIDEO_SAA7191 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to build in support for the Vino video input system found
+         on SGI Indy machines.
+
+config VIDEO_M32R_AR
+       tristate "AR devices"
+       depends on M32R && VIDEO_V4L2
+       ---help---
+         This is a video4linux driver for the Renesas AR (Artificial Retina)
+         camera module.
+
+config VIDEO_M32R_AR_M64278
+       tristate "AR device with color module M64278(VGA)"
+       depends on PLAT_M32700UT
+       select VIDEO_M32R_AR
+       ---help---
+         This is a video4linux driver for the Renesas AR (Artificial
+         Retina) with M64278E-800 camera module.
+         This module supports VGA(640x480 pixels) resolutions.
+
+         To compile this driver as a module, choose M here: the
+         module will be called arv.
+
+config VIDEO_OMAP2
+       tristate "OMAP2 Camera Capture Interface driver"
+       depends on VIDEO_DEV && ARCH_OMAP2
+       select VIDEOBUF_DMA_SG
+       ---help---
+         This is a v4l2 driver for the TI OMAP2 camera capture interface
+
+config VIDEO_OMAP3
+       tristate "OMAP 3 Camera support (EXPERIMENTAL)"
+       depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
+       ---help---
+         Driver for an OMAP 3 camera controller.
+
+config VIDEO_OMAP3_DEBUG
+       bool "OMAP 3 Camera debug messages"
+       depends on VIDEO_OMAP3
+       ---help---
+         Enable debug messages on OMAP 3 camera controller driver.
+
+source "drivers/media/platform/soc_camera/Kconfig"
+source "drivers/media/platform/s5p-fimc/Kconfig"
+source "drivers/media/platform/s5p-tv/Kconfig"
+
+endif # V4L_PLATFORM_DRIVERS
+
+menuconfig V4L_MEM2MEM_DRIVERS
+       bool "Memory-to-memory multimedia devices"
+       depends on VIDEO_V4L2
+       depends on MEDIA_CAMERA_SUPPORT
+       default n
+       ---help---
+         Say Y here to enable selecting drivers for V4L devices that
+         use system memory for both source and destination buffers, as opposed
+         to capture and output drivers, which use memory buffers for just
+         one of those.
+
+if V4L_MEM2MEM_DRIVERS
+
+config VIDEO_CODA
+       tristate "Chips&Media Coda multi-standard codec IP"
+       depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_MXC
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       select IRAM_ALLOC if SOC_IMX53
+       ---help---
+          Coda is a range of video codec IPs that supports
+          H.264, MPEG-4, and other video formats.
+
+config VIDEO_MEM2MEM_DEINTERLACE
+       tristate "Deinterlace support"
+       depends on VIDEO_DEV && VIDEO_V4L2 && DMA_ENGINE
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+           Generic deinterlacing V4L2 driver.
+
+config VIDEO_SAMSUNG_S5P_G2D
+       tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       default n
+       ---help---
+         This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D
+         2d graphics accelerator.
+
+config VIDEO_SAMSUNG_S5P_JPEG
+       tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       ---help---
+         This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
+
+config VIDEO_SAMSUNG_S5P_MFC
+       tristate "Samsung S5P MFC 5.1 Video Codec"
+       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
+       select VIDEOBUF2_DMA_CONTIG
+       default n
+       help
+           MFC 5.1 driver for V4L2.
+
+config VIDEO_MX2_EMMAPRP
+       tristate "MX2 eMMa-PrP support"
+       depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+           MX2X chips have a PrP that can be used to process buffers from
+           memory to memory. Operations include resizing and format
+           conversion.
+
+config VIDEO_SAMSUNG_EXYNOS_GSC
+       tristate "Samsung Exynos G-Scaler driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && ARCH_EXYNOS5
+       select VIDEOBUF2_DMA_CONTIG
+       select V4L2_MEM2MEM_DEV
+       help
+         This is a v4l2 driver for Samsung EXYNOS5 SoC G-Scaler.
+
+endif # V4L_MEM2MEM_DRIVERS
+
+menuconfig V4L_TEST_DRIVERS
+       bool "Media test drivers"
+       depends on MEDIA_CAMERA_SUPPORT
+
+if V4L_TEST_DRIVERS
+config VIDEO_VIVI
+       tristate "Virtual Video Driver"
+       depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
+       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
+       select FONT_8x16
+       select VIDEOBUF2_VMALLOC
+       default n
+       ---help---
+         Enables a virtual video driver. This device shows a color bar
+         and a timestamp, as a real device would generate by using V4L2
+         api.
+         Say Y here if you want to test video apps or debug V4L devices.
+         In doubt, say N.
+
+config VIDEO_MEM2MEM_TESTDEV
+       tristate "Virtual test device for mem2mem framework"
+       depends on VIDEO_DEV && VIDEO_V4L2
+       select VIDEOBUF2_VMALLOC
+       select V4L2_MEM2MEM_DEV
+       default n
+       ---help---
+         This is a virtual test device for the memory-to-memory driver
+         framework.
+endif #V4L_TEST_DRIVERS
diff --git a/drivers/media/platform/Makefile b/drivers/media/platform/Makefile
new file mode 100644 (file)
index 0000000..baaa550
--- /dev/null
@@ -0,0 +1,50 @@
+#
+# Makefile for the video capture/playback device drivers.
+#
+
+omap2cam-objs  :=      omap24xxcam.o omap24xxcam-dma.o
+
+obj-$(CONFIG_VIDEO_VINO) += indycam.o
+obj-$(CONFIG_VIDEO_VINO) += vino.o
+
+obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
+obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
+
+obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
+obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
+obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
+
+obj-$(CONFIG_VIDEO_OMAP2)              += omap2cam.o
+obj-$(CONFIG_VIDEO_OMAP3)      += omap3isp/
+
+obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
+obj-$(CONFIG_VIDEO_VIVI) += vivi.o
+
+obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
+
+obj-$(CONFIG_VIDEO_MX2_EMMAPRP)                += mx2_emmaprp.o
+obj-$(CONFIG_VIDEO_CODA)               += coda.o
+
+obj-$(CONFIG_VIDEO_MEM2MEM_DEINTERLACE)        += m2m-deinterlace.o
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)   += s5p-jpeg/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)    += s5p-mfc/
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)     += s5p-tv/
+
+obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)    += s5p-g2d/
+obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc/
+
+obj-$(CONFIG_BLACKFIN)                  += blackfin/
+
+obj-$(CONFIG_ARCH_DAVINCI)             += davinci/
+
+obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
+
+obj-$(CONFIG_SOC_CAMERA)               += soc_camera/
+
+obj-y  += davinci/
+
+obj-$(CONFIG_ARCH_OMAP)        += omap/
+
+ccflags-y += -I$(srctree)/drivers/media/i2c
similarity index 98%
rename from drivers/media/video/blackfin/bfin_capture.c
rename to drivers/media/platform/blackfin/bfin_capture.c
index 0aba45e34f70e57aee9128d721d6949f08c97018..cb2eb26850b179738b49975ea47d82cada2d0d11 100644 (file)
@@ -235,8 +235,13 @@ static int bcap_release(struct file *file)
 static int bcap_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       int ret;
 
-       return vb2_mmap(&bcap_dev->buffer_queue, vma);
+       if (mutex_lock_interruptible(&bcap_dev->mutex))
+               return -ERESTARTSYS;
+       ret = vb2_mmap(&bcap_dev->buffer_queue, vma);
+       mutex_unlock(&bcap_dev->mutex);
+       return ret;
 }
 
 #ifndef CONFIG_MMU
@@ -259,8 +264,12 @@ static unsigned long bcap_get_unmapped_area(struct file *file,
 static unsigned int bcap_poll(struct file *file, poll_table *wait)
 {
        struct bcap_device *bcap_dev = video_drvdata(file);
+       unsigned int res;
 
-       return vb2_poll(&bcap_dev->buffer_queue, file, wait);
+       mutex_lock(&bcap_dev->mutex);
+       res = vb2_poll(&bcap_dev->buffer_queue, file, wait);
+       mutex_unlock(&bcap_dev->mutex);
+       return res;
 }
 
 static int bcap_queue_setup(struct vb2_queue *vq,
@@ -942,10 +951,6 @@ static int __devinit bcap_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&bcap_dev->dma_queue);
 
        vfd->lock = &bcap_dev->mutex;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
 
        /* register video device */
        ret = video_register_device(bcap_dev->video_dev, VFL_TYPE_GRABBER, -1);
@@ -963,6 +968,7 @@ static int __devinit bcap_probe(struct platform_device *pdev)
        if (!i2c_adap) {
                v4l2_err(&bcap_dev->v4l2_dev,
                                "Unable to find i2c adapter\n");
+               ret = -ENODEV;
                goto err_unreg_vdev;
 
        }
diff --git a/drivers/media/platform/coda.c b/drivers/media/platform/coda.c
new file mode 100644 (file)
index 0000000..cd04ae2
--- /dev/null
@@ -0,0 +1,2049 @@
+/*
+ * Coda multi-standard codec IP
+ *
+ * Copyright (C) 2012 Vista Silicon S.L.
+ *    Javier Martin, <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#include <linux/clk.h>
+#include <linux/delay.h>
+#include <linux/firmware.h>
+#include <linux/interrupt.h>
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/slab.h>
+#include <linux/videodev2.h>
+#include <linux/of.h>
+
+#include <mach/iram.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/videobuf2-core.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "coda.h"
+
+#define CODA_NAME              "coda"
+
+#define CODA_MAX_INSTANCES     4
+
+#define CODA_FMO_BUF_SIZE      32
+#define CODADX6_WORK_BUF_SIZE  (288 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
+#define CODA7_WORK_BUF_SIZE    (512 * 1024 + CODA_FMO_BUF_SIZE * 8 * 1024)
+#define CODA_PARA_BUF_SIZE     (10 * 1024)
+#define CODA_ISRAM_SIZE        (2048 * 2)
+#define CODA7_IRAM_SIZE                0x14000 /* 81920 bytes */
+
+#define CODA_MAX_FRAMEBUFFERS  2
+
+#define MAX_W          720
+#define MAX_H          576
+#define CODA_MAX_FRAME_SIZE    0x90000
+#define FMO_SLICE_SAVE_BUF_SIZE         (32)
+#define CODA_DEFAULT_GAMMA             4096
+
+#define MIN_W 176
+#define MIN_H 144
+#define MAX_W 720
+#define MAX_H 576
+
+#define S_ALIGN                1 /* multiple of 2 */
+#define W_ALIGN                1 /* multiple of 2 */
+#define H_ALIGN                1 /* multiple of 2 */
+
+#define fh_to_ctx(__fh)        container_of(__fh, struct coda_ctx, fh)
+
+static int coda_debug;
+module_param(coda_debug, int, 0);
+MODULE_PARM_DESC(coda_debug, "Debug level (0-1)");
+
+enum {
+       V4L2_M2M_SRC = 0,
+       V4L2_M2M_DST = 1,
+};
+
+enum coda_fmt_type {
+       CODA_FMT_ENC,
+       CODA_FMT_RAW,
+};
+
+enum coda_inst_type {
+       CODA_INST_ENCODER,
+       CODA_INST_DECODER,
+};
+
+enum coda_product {
+       CODA_DX6 = 0xf001,
+       CODA_7541 = 0xf012,
+};
+
+struct coda_fmt {
+       char *name;
+       u32 fourcc;
+       enum coda_fmt_type type;
+};
+
+struct coda_devtype {
+       char                    *firmware;
+       enum coda_product       product;
+       struct coda_fmt         *formats;
+       unsigned int            num_formats;
+       size_t                  workbuf_size;
+};
+
+/* Per-queue, driver-specific private data */
+struct coda_q_data {
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            sizeimage;
+       struct coda_fmt *fmt;
+};
+
+struct coda_aux_buf {
+       void                    *vaddr;
+       dma_addr_t              paddr;
+       u32                     size;
+};
+
+struct coda_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     vfd;
+       struct platform_device  *plat_dev;
+       const struct coda_devtype *devtype;
+
+       void __iomem            *regs_base;
+       struct clk              *clk_per;
+       struct clk              *clk_ahb;
+
+       struct coda_aux_buf     codebuf;
+       struct coda_aux_buf     workbuf;
+       long unsigned int       iram_paddr;
+
+       spinlock_t              irqlock;
+       struct mutex            dev_mutex;
+       struct v4l2_m2m_dev     *m2m_dev;
+       struct vb2_alloc_ctx    *alloc_ctx;
+       struct list_head        instances;
+       unsigned long           instance_mask;
+       struct delayed_work     timeout;
+       struct completion       done;
+};
+
+struct coda_params {
+       u8                      rot_mode;
+       u8                      h264_intra_qp;
+       u8                      h264_inter_qp;
+       u8                      mpeg4_intra_qp;
+       u8                      mpeg4_inter_qp;
+       u8                      gop_size;
+       int                     codec_mode;
+       enum v4l2_mpeg_video_multi_slice_mode slice_mode;
+       u32                     framerate;
+       u16                     bitrate;
+       u32                     slice_max_bits;
+       u32                     slice_max_mb;
+};
+
+struct coda_ctx {
+       struct coda_dev                 *dev;
+       struct list_head                list;
+       int                             aborting;
+       int                             rawstreamon;
+       int                             compstreamon;
+       u32                             isequence;
+       struct coda_q_data              q_data[2];
+       enum coda_inst_type             inst_type;
+       enum v4l2_colorspace            colorspace;
+       struct coda_params              params;
+       struct v4l2_m2m_ctx             *m2m_ctx;
+       struct v4l2_ctrl_handler        ctrls;
+       struct v4l2_fh                  fh;
+       int                             gopcounter;
+       char                            vpu_header[3][64];
+       int                             vpu_header_size[3];
+       struct coda_aux_buf             parabuf;
+       struct coda_aux_buf             internal_frames[CODA_MAX_FRAMEBUFFERS];
+       int                             num_internal_frames;
+       int                             idx;
+};
+
+static inline void coda_write(struct coda_dev *dev, u32 data, u32 reg)
+{
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+                "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
+       writel(data, dev->regs_base + reg);
+}
+
+static inline unsigned int coda_read(struct coda_dev *dev, u32 reg)
+{
+       u32 data;
+       data = readl(dev->regs_base + reg);
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+                "%s: data=0x%x, reg=0x%x\n", __func__, data, reg);
+       return data;
+}
+
+static inline unsigned long coda_isbusy(struct coda_dev *dev)
+{
+       return coda_read(dev, CODA_REG_BIT_BUSY);
+}
+
+static inline int coda_is_initialized(struct coda_dev *dev)
+{
+       return (coda_read(dev, CODA_REG_BIT_CUR_PC) != 0);
+}
+
+static int coda_wait_timeout(struct coda_dev *dev)
+{
+       unsigned long timeout = jiffies + msecs_to_jiffies(1000);
+
+       while (coda_isbusy(dev)) {
+               if (time_after(jiffies, timeout))
+                       return -ETIMEDOUT;
+       }
+       return 0;
+}
+
+static void coda_command_async(struct coda_ctx *ctx, int cmd)
+{
+       struct coda_dev *dev = ctx->dev;
+       coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+
+       coda_write(dev, ctx->idx, CODA_REG_BIT_RUN_INDEX);
+       coda_write(dev, ctx->params.codec_mode, CODA_REG_BIT_RUN_COD_STD);
+       coda_write(dev, cmd, CODA_REG_BIT_RUN_COMMAND);
+}
+
+static int coda_command_sync(struct coda_ctx *ctx, int cmd)
+{
+       struct coda_dev *dev = ctx->dev;
+
+       coda_command_async(ctx, cmd);
+       return coda_wait_timeout(dev);
+}
+
+static struct coda_q_data *get_q_data(struct coda_ctx *ctx,
+                                        enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return &(ctx->q_data[V4L2_M2M_SRC]);
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &(ctx->q_data[V4L2_M2M_DST]);
+       default:
+               BUG();
+       }
+       return NULL;
+}
+
+/*
+ * Add one array of supported formats for each version of Coda:
+ *  i.MX27 -> codadx6
+ *  i.MX51 -> coda7
+ *  i.MX6  -> coda960
+ */
+static struct coda_fmt codadx6_formats[] = {
+       {
+               .name = "YUV 4:2:0 Planar",
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .type = CODA_FMT_RAW,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .type = CODA_FMT_ENC,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .type = CODA_FMT_ENC,
+       },
+};
+
+static struct coda_fmt coda7_formats[] = {
+       {
+               .name = "YUV 4:2:0 Planar",
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .type = CODA_FMT_RAW,
+       },
+       {
+               .name = "H264 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_H264,
+               .type = CODA_FMT_ENC,
+       },
+       {
+               .name = "MPEG4 Encoded Stream",
+               .fourcc = V4L2_PIX_FMT_MPEG4,
+               .type = CODA_FMT_ENC,
+       },
+};
+
+static struct coda_fmt *find_format(struct coda_dev *dev, struct v4l2_format *f)
+{
+       struct coda_fmt *formats = dev->devtype->formats;
+       int num_formats = dev->devtype->num_formats;
+       unsigned int k;
+
+       for (k = 0; k < num_formats; k++) {
+               if (formats[k].fourcc == f->fmt.pix.pixelformat)
+                       break;
+       }
+
+       if (k == num_formats)
+               return NULL;
+
+       return &formats[k];
+}
+
+/*
+ * V4L2 ioctl() operations.
+ */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strlcpy(cap->driver, CODA_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, CODA_NAME, sizeof(cap->card));
+       strlcpy(cap->bus_info, CODA_NAME, sizeof(cap->bus_info));
+       /*
+        * This is only a mem-to-mem video device. The capture and output
+        * device capability flags are left only for backward compatibility
+        * and are scheduled for removal.
+        */
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+                          V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int enum_fmt(void *priv, struct v4l2_fmtdesc *f,
+                       enum coda_fmt_type type)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+       struct coda_dev *dev = ctx->dev;
+       struct coda_fmt *formats = dev->devtype->formats;
+       struct coda_fmt *fmt;
+       int num_formats = dev->devtype->num_formats;
+       int i, num = 0;
+
+       for (i = 0; i < num_formats; i++) {
+               if (formats[i].type == type) {
+                       if (num == f->index)
+                               break;
+                       ++num;
+               }
+       }
+
+       if (i < num_formats) {
+               fmt = &formats[i];
+               strlcpy(f->description, fmt->name, sizeof(f->description));
+               f->pixelformat = fmt->fourcc;
+               return 0;
+       }
+
+       /* Format not found */
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(priv, f, CODA_FMT_ENC);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(priv, f, CODA_FMT_RAW);
+}
+
+static int vidioc_g_fmt(struct file *file, void *priv, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct coda_q_data *q_data;
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+
+       f->fmt.pix.field        = V4L2_FIELD_NONE;
+       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
+       f->fmt.pix.width        = q_data->width;
+       f->fmt.pix.height       = q_data->height;
+       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420)
+               f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2);
+       else /* encoded formats h.264/mpeg4 */
+               f->fmt.pix.bytesperline = 0;
+
+       f->fmt.pix.sizeimage    = q_data->sizeimage;
+       f->fmt.pix.colorspace   = ctx->colorspace;
+
+       return 0;
+}
+
+static int vidioc_try_fmt(struct coda_dev *dev, struct v4l2_format *f)
+{
+       enum v4l2_field field;
+
+       field = f->fmt.pix.field;
+       if (field == V4L2_FIELD_ANY)
+               field = V4L2_FIELD_NONE;
+       else if (V4L2_FIELD_NONE != field)
+               return -EINVAL;
+
+       /* V4L2 specification suggests the driver corrects the format struct
+        * if any of the dimensions is unsupported */
+       f->fmt.pix.field = field;
+
+       if (f->fmt.pix.pixelformat == V4L2_PIX_FMT_YUV420) {
+               v4l_bound_align_image(&f->fmt.pix.width, MIN_W, MAX_W,
+                                     W_ALIGN, &f->fmt.pix.height,
+                                     MIN_H, MAX_H, H_ALIGN, S_ALIGN);
+               f->fmt.pix.bytesperline = round_up(f->fmt.pix.width, 2);
+               f->fmt.pix.sizeimage = f->fmt.pix.width *
+                                       f->fmt.pix.height * 3 / 2;
+       } else { /*encoded formats h.264/mpeg4 */
+               f->fmt.pix.bytesperline = 0;
+               f->fmt.pix.sizeimage = CODA_MAX_FRAME_SIZE;
+       }
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       int ret;
+       struct coda_fmt *fmt;
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       fmt = find_format(ctx->dev, f);
+       /*
+        * Since decoding support is not implemented yet do not allow
+        * CODA_FMT_RAW formats in the capture interface.
+        */
+       if (!fmt || !(fmt->type == CODA_FMT_ENC))
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_H264;
+
+       f->fmt.pix.colorspace = ctx->colorspace;
+
+       ret = vidioc_try_fmt(ctx->dev, f);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+       struct coda_fmt *fmt;
+       int ret;
+
+       fmt = find_format(ctx->dev, f);
+       /*
+        * Since decoding support is not implemented yet do not allow
+        * CODA_FMT formats in the capture interface.
+        */
+       if (!fmt || !(fmt->type == CODA_FMT_RAW))
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+       if (!f->fmt.pix.colorspace)
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+       ret = vidioc_try_fmt(ctx->dev, f);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+static int vidioc_s_fmt(struct coda_ctx *ctx, struct v4l2_format *f)
+{
+       struct coda_q_data *q_data;
+       struct vb2_queue *vq;
+       int ret;
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(ctx, f->type);
+       if (!q_data)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       ret = vidioc_try_fmt(ctx->dev, f);
+       if (ret)
+               return ret;
+
+       q_data->fmt = find_format(ctx->dev, f);
+       q_data->width = f->fmt.pix.width;
+       q_data->height = f->fmt.pix.height;
+       q_data->sizeimage = f->fmt.pix.sizeimage;
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+               "Setting format for type %d, wxh: %dx%d, fmt: %d\n",
+               f->type, q_data->width, q_data->height, q_data->fmt->fourcc);
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+
+       return vidioc_s_fmt(fh_to_ctx(priv), f);
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+       int ret;
+
+       ret = vidioc_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       ret = vidioc_s_fmt(ctx, f);
+       if (ret)
+               ctx->colorspace = f->fmt.pix.colorspace;
+
+       return ret;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *buf)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct coda_ctx *ctx = fh_to_ctx(priv);
+
+       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+static const struct v4l2_ioctl_ops coda_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
+
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out   = vidioc_g_fmt,
+       .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
+
+       .vidioc_reqbufs         = vidioc_reqbufs,
+       .vidioc_querybuf        = vidioc_querybuf,
+
+       .vidioc_qbuf            = vidioc_qbuf,
+       .vidioc_dqbuf           = vidioc_dqbuf,
+
+       .vidioc_streamon        = vidioc_streamon,
+       .vidioc_streamoff       = vidioc_streamoff,
+};
+
+/*
+ * Mem-to-mem operations.
+ */
+static void coda_device_run(void *m2m_priv)
+{
+       struct coda_ctx *ctx = m2m_priv;
+       struct coda_q_data *q_data_src, *q_data_dst;
+       struct vb2_buffer *src_buf, *dst_buf;
+       struct coda_dev *dev = ctx->dev;
+       int force_ipicture;
+       int quant_param = 0;
+       u32 picture_y, picture_cb, picture_cr;
+       u32 pic_stream_buffer_addr, pic_stream_buffer_size;
+       u32 dst_fourcc;
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       dst_fourcc = q_data_dst->fmt->fourcc;
+
+       src_buf->v4l2_buf.sequence = ctx->isequence;
+       dst_buf->v4l2_buf.sequence = ctx->isequence;
+       ctx->isequence++;
+
+       /*
+        * Workaround coda firmware BUG that only marks the first
+        * frame as IDR. This is a problem for some decoders that can't
+        * recover when a frame is lost.
+        */
+       if (src_buf->v4l2_buf.sequence % ctx->params.gop_size) {
+               src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_PFRAME;
+               src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_KEYFRAME;
+       } else {
+               src_buf->v4l2_buf.flags |= V4L2_BUF_FLAG_KEYFRAME;
+               src_buf->v4l2_buf.flags &= ~V4L2_BUF_FLAG_PFRAME;
+       }
+
+       /*
+        * Copy headers at the beginning of the first frame for H.264 only.
+        * In MPEG4 they are already copied by the coda.
+        */
+       if (src_buf->v4l2_buf.sequence == 0) {
+               pic_stream_buffer_addr =
+                       vb2_dma_contig_plane_dma_addr(dst_buf, 0) +
+                       ctx->vpu_header_size[0] +
+                       ctx->vpu_header_size[1] +
+                       ctx->vpu_header_size[2];
+               pic_stream_buffer_size = CODA_MAX_FRAME_SIZE -
+                       ctx->vpu_header_size[0] -
+                       ctx->vpu_header_size[1] -
+                       ctx->vpu_header_size[2];
+               memcpy(vb2_plane_vaddr(dst_buf, 0),
+                      &ctx->vpu_header[0][0], ctx->vpu_header_size[0]);
+               memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0],
+                      &ctx->vpu_header[1][0], ctx->vpu_header_size[1]);
+               memcpy(vb2_plane_vaddr(dst_buf, 0) + ctx->vpu_header_size[0] +
+                       ctx->vpu_header_size[1], &ctx->vpu_header[2][0],
+                       ctx->vpu_header_size[2]);
+       } else {
+               pic_stream_buffer_addr =
+                       vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+               pic_stream_buffer_size = CODA_MAX_FRAME_SIZE;
+       }
+
+       if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
+               force_ipicture = 1;
+               switch (dst_fourcc) {
+               case V4L2_PIX_FMT_H264:
+                       quant_param = ctx->params.h264_intra_qp;
+                       break;
+               case V4L2_PIX_FMT_MPEG4:
+                       quant_param = ctx->params.mpeg4_intra_qp;
+                       break;
+               default:
+                       v4l2_warn(&ctx->dev->v4l2_dev,
+                               "cannot set intra qp, fmt not supported\n");
+                       break;
+               }
+       } else {
+               force_ipicture = 0;
+               switch (dst_fourcc) {
+               case V4L2_PIX_FMT_H264:
+                       quant_param = ctx->params.h264_inter_qp;
+                       break;
+               case V4L2_PIX_FMT_MPEG4:
+                       quant_param = ctx->params.mpeg4_inter_qp;
+                       break;
+               default:
+                       v4l2_warn(&ctx->dev->v4l2_dev,
+                               "cannot set inter qp, fmt not supported\n");
+                       break;
+               }
+       }
+
+       /* submit */
+       coda_write(dev, CODA_ROT_MIR_ENABLE | ctx->params.rot_mode, CODA_CMD_ENC_PIC_ROT_MODE);
+       coda_write(dev, quant_param, CODA_CMD_ENC_PIC_QS);
+
+
+       picture_y = vb2_dma_contig_plane_dma_addr(src_buf, 0);
+       picture_cb = picture_y + q_data_src->width * q_data_src->height;
+       picture_cr = picture_cb + q_data_src->width / 2 *
+                       q_data_src->height / 2;
+
+       coda_write(dev, picture_y, CODA_CMD_ENC_PIC_SRC_ADDR_Y);
+       coda_write(dev, picture_cb, CODA_CMD_ENC_PIC_SRC_ADDR_CB);
+       coda_write(dev, picture_cr, CODA_CMD_ENC_PIC_SRC_ADDR_CR);
+       coda_write(dev, force_ipicture << 1 & 0x2,
+                  CODA_CMD_ENC_PIC_OPTION);
+
+       coda_write(dev, pic_stream_buffer_addr, CODA_CMD_ENC_PIC_BB_START);
+       coda_write(dev, pic_stream_buffer_size / 1024,
+                  CODA_CMD_ENC_PIC_BB_SIZE);
+
+       if (dev->devtype->product == CODA_7541) {
+               coda_write(dev, CODA7_USE_BIT_ENABLE | CODA7_USE_HOST_BIT_ENABLE |
+                               CODA7_USE_ME_ENABLE | CODA7_USE_HOST_ME_ENABLE,
+                               CODA7_REG_BIT_AXI_SRAM_USE);
+       }
+
+       /* 1 second timeout in case CODA locks up */
+       schedule_delayed_work(&dev->timeout, HZ);
+
+       INIT_COMPLETION(dev->done);
+       coda_command_async(ctx, CODA_COMMAND_PIC_RUN);
+}
+
+static int coda_job_ready(void *m2m_priv)
+{
+       struct coda_ctx *ctx = m2m_priv;
+
+       /*
+        * For both 'P' and 'key' frame cases 1 picture
+        * and 1 frame are needed.
+        */
+       if (!v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) ||
+               !v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx)) {
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                        "not ready: not enough video buffers.\n");
+               return 0;
+       }
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                       "job ready\n");
+       return 1;
+}
+
+static void coda_job_abort(void *priv)
+{
+       struct coda_ctx *ctx = priv;
+       struct coda_dev *dev = ctx->dev;
+
+       ctx->aborting = 1;
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                "Aborting task\n");
+
+       v4l2_m2m_job_finish(dev->m2m_dev, ctx->m2m_ctx);
+}
+
+static void coda_lock(void *m2m_priv)
+{
+       struct coda_ctx *ctx = m2m_priv;
+       struct coda_dev *pcdev = ctx->dev;
+       mutex_lock(&pcdev->dev_mutex);
+}
+
+static void coda_unlock(void *m2m_priv)
+{
+       struct coda_ctx *ctx = m2m_priv;
+       struct coda_dev *pcdev = ctx->dev;
+       mutex_unlock(&pcdev->dev_mutex);
+}
+
+static struct v4l2_m2m_ops coda_m2m_ops = {
+       .device_run     = coda_device_run,
+       .job_ready      = coda_job_ready,
+       .job_abort      = coda_job_abort,
+       .lock           = coda_lock,
+       .unlock         = coda_unlock,
+};
+
+static void set_default_params(struct coda_ctx *ctx)
+{
+       struct coda_dev *dev = ctx->dev;
+
+       ctx->params.codec_mode = CODA_MODE_INVALID;
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+       ctx->params.framerate = 30;
+       ctx->aborting = 0;
+
+       /* Default formats for output and input queues */
+       ctx->q_data[V4L2_M2M_SRC].fmt = &dev->devtype->formats[0];
+       ctx->q_data[V4L2_M2M_DST].fmt = &dev->devtype->formats[1];
+       ctx->q_data[V4L2_M2M_SRC].width = MAX_W;
+       ctx->q_data[V4L2_M2M_SRC].height = MAX_H;
+       ctx->q_data[V4L2_M2M_SRC].sizeimage = (MAX_W * MAX_H * 3) / 2;
+       ctx->q_data[V4L2_M2M_DST].width = MAX_W;
+       ctx->q_data[V4L2_M2M_DST].height = MAX_H;
+       ctx->q_data[V4L2_M2M_DST].sizeimage = CODA_MAX_FRAME_SIZE;
+}
+
+/*
+ * Queue operations
+ */
+static int coda_queue_setup(struct vb2_queue *vq,
+                               const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(vq);
+       struct coda_q_data *q_data;
+       unsigned int size;
+
+       q_data = get_q_data(ctx, vq->type);
+       size = q_data->sizeimage;
+
+       *nplanes = 1;
+       sizes[0] = size;
+
+       alloc_ctxs[0] = ctx->dev->alloc_ctx;
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                "get %d buffer(s) of size %d each.\n", *nbuffers, size);
+
+       return 0;
+}
+
+static int coda_buf_prepare(struct vb2_buffer *vb)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct coda_q_data *q_data;
+
+       q_data = get_q_data(ctx, vb->vb2_queue->type);
+
+       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+               v4l2_warn(&ctx->dev->v4l2_dev,
+                         "%s data will not fit into plane (%lu < %lu)\n",
+                         __func__, vb2_plane_size(vb, 0),
+                         (long)q_data->sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+       return 0;
+}
+
+static void coda_buf_queue(struct vb2_buffer *vb)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+static void coda_wait_prepare(struct vb2_queue *q)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(q);
+       coda_unlock(ctx);
+}
+
+static void coda_wait_finish(struct vb2_queue *q)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(q);
+       coda_lock(ctx);
+}
+
+static void coda_free_framebuffers(struct coda_ctx *ctx)
+{
+       int i;
+
+       for (i = 0; i < CODA_MAX_FRAMEBUFFERS; i++) {
+               if (ctx->internal_frames[i].vaddr) {
+                       dma_free_coherent(&ctx->dev->plat_dev->dev,
+                               ctx->internal_frames[i].size,
+                               ctx->internal_frames[i].vaddr,
+                               ctx->internal_frames[i].paddr);
+                       ctx->internal_frames[i].vaddr = NULL;
+               }
+       }
+}
+
+static int coda_alloc_framebuffers(struct coda_ctx *ctx, struct coda_q_data *q_data, u32 fourcc)
+{
+       struct coda_dev *dev = ctx->dev;
+
+       int height = q_data->height;
+       int width = q_data->width;
+       u32 *p;
+       int i;
+
+       /* Allocate frame buffers */
+       ctx->num_internal_frames = CODA_MAX_FRAMEBUFFERS;
+       for (i = 0; i < ctx->num_internal_frames; i++) {
+               ctx->internal_frames[i].size = q_data->sizeimage;
+               if (fourcc == V4L2_PIX_FMT_H264 && dev->devtype->product != CODA_DX6)
+                       ctx->internal_frames[i].size += width / 2 * height / 2;
+               ctx->internal_frames[i].vaddr = dma_alloc_coherent(
+                               &dev->plat_dev->dev, ctx->internal_frames[i].size,
+                               &ctx->internal_frames[i].paddr, GFP_KERNEL);
+               if (!ctx->internal_frames[i].vaddr) {
+                       coda_free_framebuffers(ctx);
+                       return -ENOMEM;
+               }
+       }
+
+       /* Register frame buffers in the parameter buffer */
+       p = ctx->parabuf.vaddr;
+
+       if (dev->devtype->product == CODA_DX6) {
+               for (i = 0; i < ctx->num_internal_frames; i++) {
+                       p[i * 3] = ctx->internal_frames[i].paddr; /* Y */
+                       p[i * 3 + 1] = p[i * 3] + width * height; /* Cb */
+                       p[i * 3 + 2] = p[i * 3 + 1] + width / 2 * height / 2; /* Cr */
+               }
+       } else {
+               for (i = 0; i < ctx->num_internal_frames; i += 2) {
+                       p[i * 3 + 1] = ctx->internal_frames[i].paddr; /* Y */
+                       p[i * 3] = p[i * 3 + 1] + width * height; /* Cb */
+                       p[i * 3 + 3] = p[i * 3] + (width / 2) * (height / 2); /* Cr */
+
+                       if (fourcc == V4L2_PIX_FMT_H264)
+                               p[96 + i + 1] = p[i * 3 + 3] + (width / 2) * (height / 2);
+
+                       if (i + 1 < ctx->num_internal_frames) {
+                               p[i * 3 + 2] = ctx->internal_frames[i+1].paddr; /* Y */
+                               p[i * 3 + 5] = p[i * 3 + 2] + width * height ; /* Cb */
+                               p[i * 3 + 4] = p[i * 3 + 5] + (width / 2) * (height / 2); /* Cr */
+
+                               if (fourcc == V4L2_PIX_FMT_H264)
+                                       p[96 + i] = p[i * 3 + 4] + (width / 2) * (height / 2);
+                       }
+               }
+       }
+
+       return 0;
+}
+
+static int coda_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(q);
+       struct v4l2_device *v4l2_dev = &ctx->dev->v4l2_dev;
+       u32 bitstream_buf, bitstream_size;
+       struct coda_dev *dev = ctx->dev;
+       struct coda_q_data *q_data_src, *q_data_dst;
+       struct vb2_buffer *buf;
+       u32 dst_fourcc;
+       u32 value;
+       int ret;
+
+       if (count < 1)
+               return -EINVAL;
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               ctx->rawstreamon = 1;
+       else
+               ctx->compstreamon = 1;
+
+       /* Don't start the coda unless both queues are on */
+       if (!(ctx->rawstreamon & ctx->compstreamon))
+               return 0;
+
+       if (coda_isbusy(dev))
+               if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0)
+                       return -EBUSY;
+
+       ctx->gopcounter = ctx->params.gop_size - 1;
+
+       q_data_src = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       bitstream_buf = vb2_dma_contig_plane_dma_addr(buf, 0);
+       q_data_dst = get_q_data(ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       bitstream_size = q_data_dst->sizeimage;
+       dst_fourcc = q_data_dst->fmt->fourcc;
+
+       /* Find out whether coda must encode or decode */
+       if (q_data_src->fmt->type == CODA_FMT_RAW &&
+           q_data_dst->fmt->type == CODA_FMT_ENC) {
+               ctx->inst_type = CODA_INST_ENCODER;
+       } else if (q_data_src->fmt->type == CODA_FMT_ENC &&
+                  q_data_dst->fmt->type == CODA_FMT_RAW) {
+               ctx->inst_type = CODA_INST_DECODER;
+               v4l2_err(v4l2_dev, "decoding not supported.\n");
+               return -EINVAL;
+       } else {
+               v4l2_err(v4l2_dev, "couldn't tell instance type.\n");
+               return -EINVAL;
+       }
+
+       if (!coda_is_initialized(dev)) {
+               v4l2_err(v4l2_dev, "coda is not initialized.\n");
+               return -EFAULT;
+       }
+       coda_write(dev, ctx->parabuf.paddr, CODA_REG_BIT_PARA_BUF_ADDR);
+       coda_write(dev, bitstream_buf, CODA_REG_BIT_RD_PTR(ctx->idx));
+       coda_write(dev, bitstream_buf, CODA_REG_BIT_WR_PTR(ctx->idx));
+       switch (dev->devtype->product) {
+       case CODA_DX6:
+               coda_write(dev, CODADX6_STREAM_BUF_DYNALLOC_EN |
+                       CODADX6_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+               break;
+       default:
+               coda_write(dev, CODA7_STREAM_BUF_DYNALLOC_EN |
+                       CODA7_STREAM_BUF_PIC_RESET, CODA_REG_BIT_STREAM_CTRL);
+       }
+
+       if (dev->devtype->product == CODA_DX6) {
+               /* Configure the coda */
+               coda_write(dev, dev->iram_paddr, CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR);
+       }
+
+       /* Could set rotation here if needed */
+       switch (dev->devtype->product) {
+       case CODA_DX6:
+               value = (q_data_src->width & CODADX6_PICWIDTH_MASK) << CODADX6_PICWIDTH_OFFSET;
+               break;
+       default:
+               value = (q_data_src->width & CODA7_PICWIDTH_MASK) << CODA7_PICWIDTH_OFFSET;
+       }
+       value |= (q_data_src->height & CODA_PICHEIGHT_MASK) << CODA_PICHEIGHT_OFFSET;
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_SRC_SIZE);
+       coda_write(dev, ctx->params.framerate,
+                  CODA_CMD_ENC_SEQ_SRC_F_RATE);
+
+       switch (dst_fourcc) {
+       case V4L2_PIX_FMT_MPEG4:
+               if (dev->devtype->product == CODA_DX6)
+                       ctx->params.codec_mode = CODADX6_MODE_ENCODE_MP4;
+               else
+                       ctx->params.codec_mode = CODA7_MODE_ENCODE_MP4;
+
+               coda_write(dev, CODA_STD_MPEG4, CODA_CMD_ENC_SEQ_COD_STD);
+               coda_write(dev, 0, CODA_CMD_ENC_SEQ_MP4_PARA);
+               break;
+       case V4L2_PIX_FMT_H264:
+               if (dev->devtype->product == CODA_DX6)
+                       ctx->params.codec_mode = CODADX6_MODE_ENCODE_H264;
+               else
+                       ctx->params.codec_mode = CODA7_MODE_ENCODE_H264;
+
+               coda_write(dev, CODA_STD_H264, CODA_CMD_ENC_SEQ_COD_STD);
+               coda_write(dev, 0, CODA_CMD_ENC_SEQ_264_PARA);
+               break;
+       default:
+               v4l2_err(v4l2_dev,
+                        "dst format (0x%08x) invalid.\n", dst_fourcc);
+               return -EINVAL;
+       }
+
+       switch (ctx->params.slice_mode) {
+       case V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE:
+               value = 0;
+               break;
+       case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB:
+               value  = (ctx->params.slice_max_mb & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
+               value |= (1 & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET;
+               value |=  1 & CODA_SLICING_MODE_MASK;
+               break;
+       case V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES:
+               value  = (ctx->params.slice_max_bits & CODA_SLICING_SIZE_MASK) << CODA_SLICING_SIZE_OFFSET;
+               value |= (0 & CODA_SLICING_UNIT_MASK) << CODA_SLICING_UNIT_OFFSET;
+               value |=  1 & CODA_SLICING_MODE_MASK;
+               break;
+       }
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_SLICE_MODE);
+       value = ctx->params.gop_size & CODA_GOP_SIZE_MASK;
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_GOP_SIZE);
+
+       if (ctx->params.bitrate) {
+               /* Rate control enabled */
+               value = (ctx->params.bitrate & CODA_RATECONTROL_BITRATE_MASK) << CODA_RATECONTROL_BITRATE_OFFSET;
+               value |=  1 & CODA_RATECONTROL_ENABLE_MASK;
+       } else {
+               value = 0;
+       }
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_PARA);
+
+       coda_write(dev, 0, CODA_CMD_ENC_SEQ_RC_BUF_SIZE);
+       coda_write(dev, 0, CODA_CMD_ENC_SEQ_INTRA_REFRESH);
+
+       coda_write(dev, bitstream_buf, CODA_CMD_ENC_SEQ_BB_START);
+       coda_write(dev, bitstream_size / 1024, CODA_CMD_ENC_SEQ_BB_SIZE);
+
+       /* set default gamma */
+       value = (CODA_DEFAULT_GAMMA & CODA_GAMMA_MASK) << CODA_GAMMA_OFFSET;
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_RC_GAMMA);
+
+       value  = (CODA_DEFAULT_GAMMA > 0) << CODA_OPTION_GAMMA_OFFSET;
+       value |= (0 & CODA_OPTION_SLICEREPORT_MASK) << CODA_OPTION_SLICEREPORT_OFFSET;
+       coda_write(dev, value, CODA_CMD_ENC_SEQ_OPTION);
+
+       if (dst_fourcc == V4L2_PIX_FMT_H264) {
+               value  = (FMO_SLICE_SAVE_BUF_SIZE << 7);
+               value |= (0 & CODA_FMOPARAM_TYPE_MASK) << CODA_FMOPARAM_TYPE_OFFSET;
+               value |=  0 & CODA_FMOPARAM_SLICENUM_MASK;
+               if (dev->devtype->product == CODA_DX6) {
+                       coda_write(dev, value, CODADX6_CMD_ENC_SEQ_FMO);
+               } else {
+                       coda_write(dev, dev->iram_paddr, CODA7_CMD_ENC_SEQ_SEARCH_BASE);
+                       coda_write(dev, 48 * 1024, CODA7_CMD_ENC_SEQ_SEARCH_SIZE);
+               }
+       }
+
+       if (coda_command_sync(ctx, CODA_COMMAND_SEQ_INIT)) {
+               v4l2_err(v4l2_dev, "CODA_COMMAND_SEQ_INIT timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       if (coda_read(dev, CODA_RET_ENC_SEQ_SUCCESS) == 0)
+               return -EFAULT;
+
+       ret = coda_alloc_framebuffers(ctx, q_data_src, dst_fourcc);
+       if (ret < 0)
+               return ret;
+
+       coda_write(dev, ctx->num_internal_frames, CODA_CMD_SET_FRAME_BUF_NUM);
+       coda_write(dev, round_up(q_data_src->width, 8), CODA_CMD_SET_FRAME_BUF_STRIDE);
+       if (dev->devtype->product != CODA_DX6) {
+               coda_write(dev, round_up(q_data_src->width, 8), CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE);
+               coda_write(dev, dev->iram_paddr + 48 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR);
+               coda_write(dev, dev->iram_paddr + 53 * 1024, CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR);
+               coda_write(dev, dev->iram_paddr + 58 * 1024, CODA7_CMD_SET_FRAME_AXI_BIT_ADDR);
+               coda_write(dev, dev->iram_paddr + 68 * 1024, CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR);
+               coda_write(dev, 0x0, CODA7_CMD_SET_FRAME_AXI_OVL_ADDR);
+       }
+       if (coda_command_sync(ctx, CODA_COMMAND_SET_FRAME_BUF)) {
+               v4l2_err(v4l2_dev, "CODA_COMMAND_SET_FRAME_BUF timeout\n");
+               return -ETIMEDOUT;
+       }
+
+       /* Save stream headers */
+       buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       switch (dst_fourcc) {
+       case V4L2_PIX_FMT_H264:
+               /*
+                * Get SPS in the first frame and copy it to an
+                * intermediate buffer.
+                */
+               coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START);
+               coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE);
+               coda_write(dev, CODA_HEADER_H264_SPS, CODA_CMD_ENC_HEADER_CODE);
+               if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) {
+                       v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
+                       return -ETIMEDOUT;
+               }
+               ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+                               coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+               memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0),
+                      ctx->vpu_header_size[0]);
+
+               /*
+                * Get PPS in the first frame and copy it to an
+                * intermediate buffer.
+                */
+               coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START);
+               coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE);
+               coda_write(dev, CODA_HEADER_H264_PPS, CODA_CMD_ENC_HEADER_CODE);
+               if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) {
+                       v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
+                       return -ETIMEDOUT;
+               }
+               ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+                               coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+               memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0),
+                      ctx->vpu_header_size[1]);
+               ctx->vpu_header_size[2] = 0;
+               break;
+       case V4L2_PIX_FMT_MPEG4:
+               /*
+                * Get VOS in the first frame and copy it to an
+                * intermediate buffer
+                */
+               coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START);
+               coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE);
+               coda_write(dev, CODA_HEADER_MP4V_VOS, CODA_CMD_ENC_HEADER_CODE);
+               if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) {
+                       v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER timeout\n");
+                       return -ETIMEDOUT;
+               }
+               ctx->vpu_header_size[0] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+                               coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+               memcpy(&ctx->vpu_header[0][0], vb2_plane_vaddr(buf, 0),
+                      ctx->vpu_header_size[0]);
+
+               coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START);
+               coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE);
+               coda_write(dev, CODA_HEADER_MP4V_VIS, CODA_CMD_ENC_HEADER_CODE);
+               if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) {
+                       v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n");
+                       return -ETIMEDOUT;
+               }
+               ctx->vpu_header_size[1] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+                               coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+               memcpy(&ctx->vpu_header[1][0], vb2_plane_vaddr(buf, 0),
+                      ctx->vpu_header_size[1]);
+
+               coda_write(dev, vb2_dma_contig_plane_dma_addr(buf, 0), CODA_CMD_ENC_HEADER_BB_START);
+               coda_write(dev, bitstream_size, CODA_CMD_ENC_HEADER_BB_SIZE);
+               coda_write(dev, CODA_HEADER_MP4V_VOL, CODA_CMD_ENC_HEADER_CODE);
+               if (coda_command_sync(ctx, CODA_COMMAND_ENCODE_HEADER)) {
+                       v4l2_err(v4l2_dev, "CODA_COMMAND_ENCODE_HEADER failed\n");
+                       return -ETIMEDOUT;
+               }
+               ctx->vpu_header_size[2] = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx)) -
+                               coda_read(dev, CODA_CMD_ENC_HEADER_BB_START);
+               memcpy(&ctx->vpu_header[2][0], vb2_plane_vaddr(buf, 0),
+                      ctx->vpu_header_size[2]);
+               break;
+       default:
+               /* No more formats need to save headers at the moment */
+               break;
+       }
+
+       return 0;
+}
+
+static int coda_stop_streaming(struct vb2_queue *q)
+{
+       struct coda_ctx *ctx = vb2_get_drv_priv(q);
+       struct coda_dev *dev = ctx->dev;
+
+       if (q->type == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                        "%s: output\n", __func__);
+               ctx->rawstreamon = 0;
+       } else {
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                        "%s: capture\n", __func__);
+               ctx->compstreamon = 0;
+       }
+
+       /* Don't stop the coda unless both queues are off */
+       if (ctx->rawstreamon || ctx->compstreamon)
+               return 0;
+
+       if (coda_isbusy(dev)) {
+               if (wait_for_completion_interruptible_timeout(&dev->done, HZ) <= 0) {
+                       v4l2_warn(&dev->v4l2_dev,
+                                 "%s: timeout, sending SEQ_END anyway\n", __func__);
+               }
+       }
+
+       cancel_delayed_work(&dev->timeout);
+
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+                "%s: sent command 'SEQ_END' to coda\n", __func__);
+       if (coda_command_sync(ctx, CODA_COMMAND_SEQ_END)) {
+               v4l2_err(&dev->v4l2_dev,
+                        "CODA_COMMAND_SEQ_END failed\n");
+               return -ETIMEDOUT;
+       }
+
+       coda_free_framebuffers(ctx);
+
+       return 0;
+}
+
+static struct vb2_ops coda_qops = {
+       .queue_setup            = coda_queue_setup,
+       .buf_prepare            = coda_buf_prepare,
+       .buf_queue              = coda_buf_queue,
+       .wait_prepare           = coda_wait_prepare,
+       .wait_finish            = coda_wait_finish,
+       .start_streaming        = coda_start_streaming,
+       .stop_streaming         = coda_stop_streaming,
+};
+
+static int coda_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct coda_ctx *ctx =
+                       container_of(ctrl->handler, struct coda_ctx, ctrls);
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                "s_ctrl: id = %d, val = %d\n", ctrl->id, ctrl->val);
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               if (ctrl->val)
+                       ctx->params.rot_mode |= CODA_MIR_HOR;
+               else
+                       ctx->params.rot_mode &= ~CODA_MIR_HOR;
+               break;
+       case V4L2_CID_VFLIP:
+               if (ctrl->val)
+                       ctx->params.rot_mode |= CODA_MIR_VER;
+               else
+                       ctx->params.rot_mode &= ~CODA_MIR_VER;
+               break;
+       case V4L2_CID_MPEG_VIDEO_BITRATE:
+               ctx->params.bitrate = ctrl->val / 1000;
+               break;
+       case V4L2_CID_MPEG_VIDEO_GOP_SIZE:
+               ctx->params.gop_size = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP:
+               ctx->params.h264_intra_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP:
+               ctx->params.h264_inter_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP:
+               ctx->params.mpeg4_intra_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP:
+               ctx->params.mpeg4_inter_qp = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE:
+               ctx->params.slice_mode = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB:
+               ctx->params.slice_max_mb = ctrl->val;
+               break;
+       case V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES:
+               ctx->params.slice_max_bits = ctrl->val * 8;
+               break;
+       case V4L2_CID_MPEG_VIDEO_HEADER_MODE:
+               break;
+       default:
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                       "Invalid control, id=%d, val=%d\n",
+                       ctrl->id, ctrl->val);
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
+static struct v4l2_ctrl_ops coda_ctrl_ops = {
+       .s_ctrl = coda_s_ctrl,
+};
+
+static int coda_ctrls_setup(struct coda_ctx *ctx)
+{
+       v4l2_ctrl_handler_init(&ctx->ctrls, 9);
+
+       v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_HFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_VFLIP, 0, 1, 1, 0);
+       v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_BITRATE, 0, 32767000, 1, 0);
+       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_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP, 1, 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,
+               V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP, 1, 31, 1, 2);
+       v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE,
+               V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES, 0x0,
+               V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE);
+       v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB, 1, 0x3fffffff, 1, 1);
+       v4l2_ctrl_new_std(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES, 1, 0x3fffffff, 1, 500);
+       v4l2_ctrl_new_std_menu(&ctx->ctrls, &coda_ctrl_ops,
+               V4L2_CID_MPEG_VIDEO_HEADER_MODE,
+               V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME,
+               (1 << V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE),
+               V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME);
+
+       if (ctx->ctrls.error) {
+               v4l2_err(&ctx->dev->v4l2_dev, "control initialization error (%d)",
+                       ctx->ctrls.error);
+               return -EINVAL;
+       }
+
+       return v4l2_ctrl_handler_setup(&ctx->ctrls);
+}
+
+static int coda_queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct coda_ctx *ctx = priv;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &coda_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &coda_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+
+       return vb2_queue_init(dst_vq);
+}
+
+static int coda_next_free_instance(struct coda_dev *dev)
+{
+       return ffz(dev->instance_mask);
+}
+
+static int coda_open(struct file *file)
+{
+       struct coda_dev *dev = video_drvdata(file);
+       struct coda_ctx *ctx = NULL;
+       int ret = 0;
+       int idx;
+
+       idx = coda_next_free_instance(dev);
+       if (idx >= CODA_MAX_INSTANCES)
+               return -EBUSY;
+       set_bit(idx, &dev->instance_mask);
+
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       v4l2_fh_init(&ctx->fh, video_devdata(file));
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+       ctx->dev = dev;
+       ctx->idx = idx;
+
+       set_default_params(ctx);
+       ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx,
+                                        &coda_queue_init);
+       if (IS_ERR(ctx->m2m_ctx)) {
+               int ret = PTR_ERR(ctx->m2m_ctx);
+
+               v4l2_err(&dev->v4l2_dev, "%s return error (%d)\n",
+                        __func__, ret);
+               goto err;
+       }
+       ret = coda_ctrls_setup(ctx);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "failed to setup coda controls\n");
+               goto err;
+       }
+
+       ctx->fh.ctrl_handler = &ctx->ctrls;
+
+       ctx->parabuf.vaddr = dma_alloc_coherent(&dev->plat_dev->dev,
+                       CODA_PARA_BUF_SIZE, &ctx->parabuf.paddr, GFP_KERNEL);
+       if (!ctx->parabuf.vaddr) {
+               v4l2_err(&dev->v4l2_dev, "failed to allocate parabuf");
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       coda_lock(ctx);
+       list_add(&ctx->list, &dev->instances);
+       coda_unlock(ctx);
+
+       clk_prepare_enable(dev->clk_per);
+       clk_prepare_enable(dev->clk_ahb);
+
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Created instance %d (%p)\n",
+                ctx->idx, ctx);
+
+       return 0;
+
+err:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+       return ret;
+}
+
+static int coda_release(struct file *file)
+{
+       struct coda_dev *dev = video_drvdata(file);
+       struct coda_ctx *ctx = fh_to_ctx(file->private_data);
+
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev, "Releasing instance %p\n",
+                ctx);
+
+       coda_lock(ctx);
+       list_del(&ctx->list);
+       coda_unlock(ctx);
+
+       dma_free_coherent(&dev->plat_dev->dev, CODA_PARA_BUF_SIZE,
+               ctx->parabuf.vaddr, ctx->parabuf.paddr);
+       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       v4l2_ctrl_handler_free(&ctx->ctrls);
+       clk_disable_unprepare(dev->clk_per);
+       clk_disable_unprepare(dev->clk_ahb);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       clear_bit(ctx->idx, &dev->instance_mask);
+       kfree(ctx);
+
+       return 0;
+}
+
+static unsigned int coda_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct coda_ctx *ctx = fh_to_ctx(file->private_data);
+       int ret;
+
+       coda_lock(ctx);
+       ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       coda_unlock(ctx);
+       return ret;
+}
+
+static int coda_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct coda_ctx *ctx = fh_to_ctx(file->private_data);
+
+       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations coda_fops = {
+       .owner          = THIS_MODULE,
+       .open           = coda_open,
+       .release        = coda_release,
+       .poll           = coda_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = coda_mmap,
+};
+
+static irqreturn_t coda_irq_handler(int irq, void *data)
+{
+       struct vb2_buffer *src_buf, *dst_buf;
+       struct coda_dev *dev = data;
+       u32 wr_ptr, start_ptr;
+       struct coda_ctx *ctx;
+
+       __cancel_delayed_work(&dev->timeout);
+
+       /* read status register to attend the IRQ */
+       coda_read(dev, CODA_REG_BIT_INT_STATUS);
+       coda_write(dev, CODA_REG_BIT_INT_CLEAR_SET,
+                     CODA_REG_BIT_INT_CLEAR);
+
+       ctx = v4l2_m2m_get_curr_priv(dev->m2m_dev);
+       if (ctx == NULL) {
+               v4l2_err(&dev->v4l2_dev, "Instance released before the end of transaction\n");
+               return IRQ_HANDLED;
+       }
+
+       if (ctx->aborting) {
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                        "task has been aborted\n");
+               return IRQ_HANDLED;
+       }
+
+       if (coda_isbusy(ctx->dev)) {
+               v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev,
+                        "coda is still busy!!!!\n");
+               return IRQ_NONE;
+       }
+
+       complete(&dev->done);
+
+       src_buf = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+       dst_buf = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+       /* Get results from the coda */
+       coda_read(dev, CODA_RET_ENC_PIC_TYPE);
+       start_ptr = coda_read(dev, CODA_CMD_ENC_PIC_BB_START);
+       wr_ptr = coda_read(dev, CODA_REG_BIT_WR_PTR(ctx->idx));
+       /* Calculate bytesused field */
+       if (dst_buf->v4l2_buf.sequence == 0) {
+               dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr) +
+                                               ctx->vpu_header_size[0] +
+                                               ctx->vpu_header_size[1] +
+                                               ctx->vpu_header_size[2];
+       } else {
+               dst_buf->v4l2_planes[0].bytesused = (wr_ptr - start_ptr);
+       }
+
+       v4l2_dbg(1, coda_debug, &ctx->dev->v4l2_dev, "frame size = %u\n",
+                wr_ptr - start_ptr);
+
+       coda_read(dev, CODA_RET_ENC_PIC_SLICE_NUM);
+       coda_read(dev, CODA_RET_ENC_PIC_FLAG);
+
+       if (src_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) {
+               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;
+       }
+
+       v4l2_m2m_buf_done(src_buf, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst_buf, VB2_BUF_STATE_DONE);
+
+       ctx->gopcounter--;
+       if (ctx->gopcounter < 0)
+               ctx->gopcounter = ctx->params.gop_size - 1;
+
+       v4l2_dbg(1, coda_debug, &dev->v4l2_dev,
+               "job finished: encoding frame (%d) (%s)\n",
+               dst_buf->v4l2_buf.sequence,
+               (dst_buf->v4l2_buf.flags & V4L2_BUF_FLAG_KEYFRAME) ?
+               "KEYFRAME" : "PFRAME");
+
+       v4l2_m2m_job_finish(ctx->dev->m2m_dev, ctx->m2m_ctx);
+
+       return IRQ_HANDLED;
+}
+
+static void coda_timeout(struct work_struct *work)
+{
+       struct coda_ctx *ctx;
+       struct coda_dev *dev = container_of(to_delayed_work(work),
+                                           struct coda_dev, timeout);
+
+       if (completion_done(&dev->done))
+               return;
+
+       complete(&dev->done);
+
+       v4l2_err(&dev->v4l2_dev, "CODA PIC_RUN timeout, stopping all streams\n");
+
+       mutex_lock(&dev->dev_mutex);
+       list_for_each_entry(ctx, &dev->instances, list) {
+               v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_OUTPUT);
+               v4l2_m2m_streamoff(NULL, ctx->m2m_ctx, V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       }
+       mutex_unlock(&dev->dev_mutex);
+}
+
+static u32 coda_supported_firmwares[] = {
+       CODA_FIRMWARE_VERNUM(CODA_DX6, 2, 2, 5),
+       CODA_FIRMWARE_VERNUM(CODA_7541, 13, 4, 29),
+};
+
+static bool coda_firmware_supported(u32 vernum)
+{
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(coda_supported_firmwares); i++)
+               if (vernum == coda_supported_firmwares[i])
+                       return true;
+       return false;
+}
+
+static char *coda_product_name(int product)
+{
+       static char buf[9];
+
+       switch (product) {
+       case CODA_DX6:
+               return "CodaDx6";
+       case CODA_7541:
+               return "CODA7541";
+       default:
+               snprintf(buf, sizeof(buf), "(0x%04x)", product);
+               return buf;
+       }
+}
+
+static int coda_hw_init(struct coda_dev *dev)
+{
+       u16 product, major, minor, release;
+       u32 data;
+       u16 *p;
+       int i;
+
+       clk_prepare_enable(dev->clk_per);
+       clk_prepare_enable(dev->clk_ahb);
+
+       /*
+        * Copy the first CODA_ISRAM_SIZE in the internal SRAM.
+        * The 16-bit chars in the code buffer are in memory access
+        * order, re-sort them to CODA order for register download.
+        * Data in this SRAM survives a reboot.
+        */
+       p = (u16 *)dev->codebuf.vaddr;
+       if (dev->devtype->product == CODA_DX6) {
+               for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++)  {
+                       data = CODA_DOWN_ADDRESS_SET(i) |
+                               CODA_DOWN_DATA_SET(p[i ^ 1]);
+                       coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
+               }
+       } else {
+               for (i = 0; i < (CODA_ISRAM_SIZE / 2); i++) {
+                       data = CODA_DOWN_ADDRESS_SET(i) |
+                               CODA_DOWN_DATA_SET(p[round_down(i, 4) +
+                                                       3 - (i % 4)]);
+                       coda_write(dev, data, CODA_REG_BIT_CODE_DOWN);
+               }
+       }
+
+       /* Tell the BIT where to find everything it needs */
+       coda_write(dev, dev->workbuf.paddr,
+                     CODA_REG_BIT_WORK_BUF_ADDR);
+       coda_write(dev, dev->codebuf.paddr,
+                     CODA_REG_BIT_CODE_BUF_ADDR);
+       coda_write(dev, 0, CODA_REG_BIT_CODE_RUN);
+
+       /* Set default values */
+       switch (dev->devtype->product) {
+       case CODA_DX6:
+               coda_write(dev, CODADX6_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL);
+               break;
+       default:
+               coda_write(dev, CODA7_STREAM_BUF_PIC_FLUSH, CODA_REG_BIT_STREAM_CTRL);
+       }
+       coda_write(dev, 0, CODA_REG_BIT_FRAME_MEM_CTRL);
+
+       if (dev->devtype->product != CODA_DX6)
+               coda_write(dev, 0, CODA7_REG_BIT_AXI_SRAM_USE);
+
+       coda_write(dev, CODA_INT_INTERRUPT_ENABLE,
+                     CODA_REG_BIT_INT_ENABLE);
+
+       /* Reset VPU and start processor */
+       data = coda_read(dev, CODA_REG_BIT_CODE_RESET);
+       data |= CODA_REG_RESET_ENABLE;
+       coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
+       udelay(10);
+       data &= ~CODA_REG_RESET_ENABLE;
+       coda_write(dev, data, CODA_REG_BIT_CODE_RESET);
+       coda_write(dev, CODA_REG_RUN_ENABLE, CODA_REG_BIT_CODE_RUN);
+
+       /* Load firmware */
+       coda_write(dev, 0, CODA_CMD_FIRMWARE_VERNUM);
+       coda_write(dev, CODA_REG_BIT_BUSY_FLAG, CODA_REG_BIT_BUSY);
+       coda_write(dev, 0, CODA_REG_BIT_RUN_INDEX);
+       coda_write(dev, 0, CODA_REG_BIT_RUN_COD_STD);
+       coda_write(dev, CODA_COMMAND_FIRMWARE_GET, CODA_REG_BIT_RUN_COMMAND);
+       if (coda_wait_timeout(dev)) {
+               clk_disable_unprepare(dev->clk_per);
+               clk_disable_unprepare(dev->clk_ahb);
+               v4l2_err(&dev->v4l2_dev, "firmware get command error\n");
+               return -EIO;
+       }
+
+       /* Check we are compatible with the loaded firmware */
+       data = coda_read(dev, CODA_CMD_FIRMWARE_VERNUM);
+       product = CODA_FIRMWARE_PRODUCT(data);
+       major = CODA_FIRMWARE_MAJOR(data);
+       minor = CODA_FIRMWARE_MINOR(data);
+       release = CODA_FIRMWARE_RELEASE(data);
+
+       clk_disable_unprepare(dev->clk_per);
+       clk_disable_unprepare(dev->clk_ahb);
+
+       if (product != dev->devtype->product) {
+               v4l2_err(&dev->v4l2_dev, "Wrong firmware. Hw: %s, Fw: %s,"
+                        " Version: %u.%u.%u\n",
+                        coda_product_name(dev->devtype->product),
+                        coda_product_name(product), major, minor, release);
+               return -EINVAL;
+       }
+
+       v4l2_info(&dev->v4l2_dev, "Initialized %s.\n",
+                 coda_product_name(product));
+
+       if (coda_firmware_supported(data)) {
+               v4l2_info(&dev->v4l2_dev, "Firmware version: %u.%u.%u\n",
+                         major, minor, release);
+       } else {
+               v4l2_warn(&dev->v4l2_dev, "Unsupported firmware version: "
+                         "%u.%u.%u\n", major, minor, release);
+       }
+
+       return 0;
+}
+
+static void coda_fw_callback(const struct firmware *fw, void *context)
+{
+       struct coda_dev *dev = context;
+       struct platform_device *pdev = dev->plat_dev;
+       int ret;
+
+       if (!fw) {
+               v4l2_err(&dev->v4l2_dev, "firmware request failed\n");
+               return;
+       }
+
+       /* allocate auxiliary per-device code buffer for the BIT processor */
+       dev->codebuf.size = fw->size;
+       dev->codebuf.vaddr = dma_alloc_coherent(&pdev->dev, fw->size,
+                                                   &dev->codebuf.paddr,
+                                                   GFP_KERNEL);
+       if (!dev->codebuf.vaddr) {
+               dev_err(&pdev->dev, "failed to allocate code buffer\n");
+               return;
+       }
+
+       /* Copy the whole firmware image to the code buffer */
+       memcpy(dev->codebuf.vaddr, fw->data, fw->size);
+       release_firmware(fw);
+
+       ret = coda_hw_init(dev);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "HW initialization failed\n");
+               return;
+       }
+
+       dev->vfd.fops   = &coda_fops,
+       dev->vfd.ioctl_ops      = &coda_ioctl_ops;
+       dev->vfd.release        = video_device_release_empty,
+       dev->vfd.lock   = &dev->dev_mutex;
+       dev->vfd.v4l2_dev       = &dev->v4l2_dev;
+       dev->vfd.vfl_dir        = VFL_DIR_M2M;
+       snprintf(dev->vfd.name, sizeof(dev->vfd.name), "%s", CODA_NAME);
+       video_set_drvdata(&dev->vfd, dev);
+
+       dev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(dev->alloc_ctx)) {
+               v4l2_err(&dev->v4l2_dev, "Failed to alloc vb2 context\n");
+               return;
+       }
+
+       dev->m2m_dev = v4l2_m2m_init(&coda_m2m_ops);
+       if (IS_ERR(dev->m2m_dev)) {
+               v4l2_err(&dev->v4l2_dev, "Failed to init mem2mem device\n");
+               goto rel_ctx;
+       }
+
+       ret = video_register_device(&dev->vfd, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&dev->v4l2_dev, "Failed to register video device\n");
+               goto rel_m2m;
+       }
+       v4l2_info(&dev->v4l2_dev, "codec registered as /dev/video%d\n",
+                 dev->vfd.num);
+
+       return;
+
+rel_m2m:
+       v4l2_m2m_release(dev->m2m_dev);
+rel_ctx:
+       vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+}
+
+static int coda_firmware_request(struct coda_dev *dev)
+{
+       char *fw = dev->devtype->firmware;
+
+       dev_dbg(&dev->plat_dev->dev, "requesting firmware '%s' for %s\n", fw,
+               coda_product_name(dev->devtype->product));
+
+       return request_firmware_nowait(THIS_MODULE, true,
+               fw, &dev->plat_dev->dev, GFP_KERNEL, dev, coda_fw_callback);
+}
+
+enum coda_platform {
+       CODA_IMX27,
+       CODA_IMX53,
+};
+
+static const struct coda_devtype coda_devdata[] = {
+       [CODA_IMX27] = {
+               .firmware    = "v4l-codadx6-imx27.bin",
+               .product     = CODA_DX6,
+               .formats     = codadx6_formats,
+               .num_formats = ARRAY_SIZE(codadx6_formats),
+       },
+       [CODA_IMX53] = {
+               .firmware    = "v4l-coda7541-imx53.bin",
+               .product     = CODA_7541,
+               .formats     = coda7_formats,
+               .num_formats = ARRAY_SIZE(coda7_formats),
+       },
+};
+
+static struct platform_device_id coda_platform_ids[] = {
+       { .name = "coda-imx27", .driver_data = CODA_IMX27 },
+       { .name = "coda-imx53", .driver_data = CODA_7541 },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(platform, coda_platform_ids);
+
+#ifdef CONFIG_OF
+static const struct of_device_id coda_dt_ids[] = {
+       { .compatible = "fsl,imx27-vpu", .data = &coda_platform_ids[CODA_IMX27] },
+       { .compatible = "fsl,imx53-vpu", .data = &coda_devdata[CODA_IMX53] },
+       { /* sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, coda_dt_ids);
+#endif
+
+static int __devinit coda_probe(struct platform_device *pdev)
+{
+       const struct of_device_id *of_id =
+                       of_match_device(of_match_ptr(coda_dt_ids), &pdev->dev);
+       const struct platform_device_id *pdev_id;
+       struct coda_dev *dev;
+       struct resource *res;
+       int ret, irq;
+
+       dev = devm_kzalloc(&pdev->dev, sizeof *dev, GFP_KERNEL);
+       if (!dev) {
+               dev_err(&pdev->dev, "Not enough memory for %s\n",
+                       CODA_NAME);
+               return -ENOMEM;
+       }
+
+       spin_lock_init(&dev->irqlock);
+       INIT_LIST_HEAD(&dev->instances);
+       INIT_DELAYED_WORK(&dev->timeout, coda_timeout);
+       init_completion(&dev->done);
+       complete(&dev->done);
+
+       dev->plat_dev = pdev;
+       dev->clk_per = devm_clk_get(&pdev->dev, "per");
+       if (IS_ERR(dev->clk_per)) {
+               dev_err(&pdev->dev, "Could not get per clock\n");
+               return PTR_ERR(dev->clk_per);
+       }
+
+       dev->clk_ahb = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(dev->clk_ahb)) {
+               dev_err(&pdev->dev, "Could not get ahb clock\n");
+               return PTR_ERR(dev->clk_ahb);
+       }
+
+       /* Get  memory for physical registers */
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (res == NULL) {
+               dev_err(&pdev->dev, "failed to get memory region resource\n");
+               return -ENOENT;
+       }
+
+       if (devm_request_mem_region(&pdev->dev, res->start,
+                       resource_size(res), CODA_NAME) == NULL) {
+               dev_err(&pdev->dev, "failed to request memory region\n");
+               return -ENOENT;
+       }
+       dev->regs_base = devm_ioremap(&pdev->dev, res->start,
+                                     resource_size(res));
+       if (!dev->regs_base) {
+               dev_err(&pdev->dev, "failed to ioremap address region\n");
+               return -ENOENT;
+       }
+
+       /* IRQ */
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get irq resource\n");
+               return -ENOENT;
+       }
+
+       if (devm_request_irq(&pdev->dev, irq, coda_irq_handler,
+               0, CODA_NAME, dev) < 0) {
+               dev_err(&pdev->dev, "failed to request irq\n");
+               return -ENOENT;
+       }
+
+       ret = v4l2_device_register(&pdev->dev, &dev->v4l2_dev);
+       if (ret)
+               return ret;
+
+       mutex_init(&dev->dev_mutex);
+
+       pdev_id = of_id ? of_id->data : platform_get_device_id(pdev);
+
+       if (of_id) {
+               dev->devtype = of_id->data;
+       } else if (pdev_id) {
+               dev->devtype = &coda_devdata[pdev_id->driver_data];
+       } else {
+               v4l2_device_unregister(&dev->v4l2_dev);
+               return -EINVAL;
+       }
+
+       /* allocate auxiliary per-device buffers for the BIT processor */
+       switch (dev->devtype->product) {
+       case CODA_DX6:
+               dev->workbuf.size = CODADX6_WORK_BUF_SIZE;
+               break;
+       default:
+               dev->workbuf.size = CODA7_WORK_BUF_SIZE;
+       }
+       dev->workbuf.vaddr = dma_alloc_coherent(&pdev->dev, dev->workbuf.size,
+                                                   &dev->workbuf.paddr,
+                                                   GFP_KERNEL);
+       if (!dev->workbuf.vaddr) {
+               dev_err(&pdev->dev, "failed to allocate work buffer\n");
+               v4l2_device_unregister(&dev->v4l2_dev);
+               return -ENOMEM;
+       }
+
+       if (dev->devtype->product == CODA_DX6) {
+               dev->iram_paddr = 0xffff4c00;
+       } else {
+               void __iomem *iram_vaddr;
+
+               iram_vaddr = iram_alloc(CODA7_IRAM_SIZE,
+                                       &dev->iram_paddr);
+               if (!iram_vaddr) {
+                       dev_err(&pdev->dev, "unable to alloc iram\n");
+                       return -ENOMEM;
+               }
+       }
+
+       platform_set_drvdata(pdev, dev);
+
+       return coda_firmware_request(dev);
+}
+
+static int coda_remove(struct platform_device *pdev)
+{
+       struct coda_dev *dev = platform_get_drvdata(pdev);
+
+       video_unregister_device(&dev->vfd);
+       if (dev->m2m_dev)
+               v4l2_m2m_release(dev->m2m_dev);
+       if (dev->alloc_ctx)
+               vb2_dma_contig_cleanup_ctx(dev->alloc_ctx);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       if (dev->iram_paddr)
+               iram_free(dev->iram_paddr, CODA7_IRAM_SIZE);
+       if (dev->codebuf.vaddr)
+               dma_free_coherent(&pdev->dev, dev->codebuf.size,
+                                 &dev->codebuf.vaddr, dev->codebuf.paddr);
+       if (dev->workbuf.vaddr)
+               dma_free_coherent(&pdev->dev, dev->workbuf.size, &dev->workbuf.vaddr,
+                         dev->workbuf.paddr);
+       return 0;
+}
+
+static struct platform_driver coda_driver = {
+       .probe  = coda_probe,
+       .remove = __devexit_p(coda_remove),
+       .driver = {
+               .name   = CODA_NAME,
+               .owner  = THIS_MODULE,
+               .of_match_table = of_match_ptr(coda_dt_ids),
+       },
+       .id_table = coda_platform_ids,
+};
+
+module_platform_driver(coda_driver);
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com>");
+MODULE_DESCRIPTION("Coda multi-standard codec V4L2 driver");
diff --git a/drivers/media/platform/coda.h b/drivers/media/platform/coda.h
new file mode 100644 (file)
index 0000000..f3f5e43
--- /dev/null
@@ -0,0 +1,238 @@
+/*
+ * linux/drivers/media/platform/coda/coda_regs.h
+ *
+ * Copyright (C) 2012 Vista Silicon SL
+ *    Javier Martin <javier.martin@vista-silicon.com>
+ *    Xavier Duret
+ *
+ * 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 _REGS_CODA_H_
+#define _REGS_CODA_H_
+
+/* HW registers */
+#define CODA_REG_BIT_CODE_RUN                  0x000
+#define                CODA_REG_RUN_ENABLE             (1 << 0)
+#define CODA_REG_BIT_CODE_DOWN                 0x004
+#define                CODA_DOWN_ADDRESS_SET(x)        (((x) & 0xffff) << 16)
+#define                CODA_DOWN_DATA_SET(x)           ((x) & 0xffff)
+#define CODA_REG_BIT_HOST_IN_REQ               0x008
+#define CODA_REG_BIT_INT_CLEAR                 0x00c
+#define                CODA_REG_BIT_INT_CLEAR_SET      0x1
+#define CODA_REG_BIT_INT_STATUS                0x010
+#define CODA_REG_BIT_CODE_RESET                0x014
+#define                CODA_REG_RESET_ENABLE           (1 << 0)
+#define CODA_REG_BIT_CUR_PC                    0x018
+
+/* Static SW registers */
+#define CODA_REG_BIT_CODE_BUF_ADDR             0x100
+#define CODA_REG_BIT_WORK_BUF_ADDR             0x104
+#define CODA_REG_BIT_PARA_BUF_ADDR             0x108
+#define CODA_REG_BIT_STREAM_CTRL               0x10c
+#define                CODA7_STREAM_BUF_PIC_RESET      (1 << 4)
+#define                CODADX6_STREAM_BUF_PIC_RESET    (1 << 3)
+#define                CODA7_STREAM_BUF_PIC_FLUSH      (1 << 3)
+#define                CODADX6_STREAM_BUF_PIC_FLUSH    (1 << 2)
+#define                CODA7_STREAM_BUF_DYNALLOC_EN    (1 << 5)
+#define                CODADX6_STREAM_BUF_DYNALLOC_EN  (1 << 4)
+#define        CODA_STREAM_CHKDIS_OFFSET       (1 << 1)
+#define                CODA_STREAM_ENDIAN_SELECT       (1 << 0)
+#define CODA_REG_BIT_FRAME_MEM_CTRL            0x110
+#define                CODA_IMAGE_ENDIAN_SELECT        (1 << 0)
+#define CODA_REG_BIT_RD_PTR(x)                 (0x120 + 8 * (x))
+#define CODA_REG_BIT_WR_PTR(x)                 (0x124 + 8 * (x))
+#define CODADX6_REG_BIT_SEARCH_RAM_BASE_ADDR   0x140
+#define CODA7_REG_BIT_AXI_SRAM_USE             0x140
+#define                CODA7_USE_BIT_ENABLE            (1 << 0)
+#define                CODA7_USE_HOST_BIT_ENABLE       (1 << 7)
+#define                CODA7_USE_ME_ENABLE             (1 << 4)
+#define                CODA7_USE_HOST_ME_ENABLE        (1 << 11)
+#define CODA_REG_BIT_BUSY                      0x160
+#define                CODA_REG_BIT_BUSY_FLAG          1
+#define CODA_REG_BIT_RUN_COMMAND               0x164
+#define                CODA_COMMAND_SEQ_INIT           1
+#define                CODA_COMMAND_SEQ_END            2
+#define                CODA_COMMAND_PIC_RUN            3
+#define                CODA_COMMAND_SET_FRAME_BUF      4
+#define                CODA_COMMAND_ENCODE_HEADER      5
+#define                CODA_COMMAND_ENC_PARA_SET       6
+#define                CODA_COMMAND_DEC_PARA_SET       7
+#define                CODA_COMMAND_DEC_BUF_FLUSH      8
+#define                CODA_COMMAND_RC_CHANGE_PARAMETER 9
+#define                CODA_COMMAND_FIRMWARE_GET       0xf
+#define CODA_REG_BIT_RUN_INDEX                 0x168
+#define                CODA_INDEX_SET(x)               ((x) & 0x3)
+#define CODA_REG_BIT_RUN_COD_STD               0x16c
+#define                CODADX6_MODE_DECODE_MP4         0
+#define                CODADX6_MODE_ENCODE_MP4         1
+#define                CODADX6_MODE_DECODE_H264        2
+#define                CODADX6_MODE_ENCODE_H264        3
+#define                CODA7_MODE_DECODE_H264          0
+#define                CODA7_MODE_DECODE_VC1           1
+#define                CODA7_MODE_DECODE_MP2           2
+#define                CODA7_MODE_DECODE_MP4           3
+#define                CODA7_MODE_DECODE_DV3           3
+#define                CODA7_MODE_DECODE_RV            4
+#define                CODA7_MODE_DECODE_MJPG          5
+#define                CODA7_MODE_ENCODE_H264          8
+#define                CODA7_MODE_ENCODE_MP4           11
+#define                CODA7_MODE_ENCODE_MJPG          13
+#define        CODA_MODE_INVALID               0xffff
+#define CODA_REG_BIT_INT_ENABLE                0x170
+#define                CODA_INT_INTERRUPT_ENABLE       (1 << 3)
+
+/*
+ * Commands' mailbox:
+ * registers with offsets in the range 0x180-0x1d0
+ * have different meaning depending on the command being
+ * issued.
+ */
+
+/* Encoder Sequence Initialization */
+#define CODA_CMD_ENC_SEQ_BB_START                              0x180
+#define CODA_CMD_ENC_SEQ_BB_SIZE                               0x184
+#define CODA_CMD_ENC_SEQ_OPTION                                0x188
+#define                CODA_OPTION_GAMMA_OFFSET                        7
+#define                CODA_OPTION_GAMMA_MASK                          0x01
+#define                CODA_OPTION_LIMITQP_OFFSET                      6
+#define                CODA_OPTION_LIMITQP_MASK                        0x01
+#define                CODA_OPTION_RCINTRAQP_OFFSET                    5
+#define                CODA_OPTION_RCINTRAQP_MASK                      0x01
+#define                CODA_OPTION_FMO_OFFSET                          4
+#define                CODA_OPTION_FMO_MASK                            0x01
+#define                CODA_OPTION_SLICEREPORT_OFFSET                  1
+#define                CODA_OPTION_SLICEREPORT_MASK                    0x01
+#define CODA_CMD_ENC_SEQ_COD_STD                               0x18c
+#define                CODA_STD_MPEG4                                  0
+#define                CODA_STD_H263                                   1
+#define                CODA_STD_H264                                   2
+#define                CODA_STD_MJPG                                   3
+#define CODA_CMD_ENC_SEQ_SRC_SIZE                              0x190
+#define                CODA7_PICWIDTH_OFFSET                           16
+#define                CODA7_PICWIDTH_MASK                             0xffff
+#define                CODADX6_PICWIDTH_OFFSET                         10
+#define                CODADX6_PICWIDTH_MASK                           0x3ff
+#define                CODA_PICHEIGHT_OFFSET                           0
+#define                CODA_PICHEIGHT_MASK                             0x3ff
+#define CODA_CMD_ENC_SEQ_SRC_F_RATE                            0x194
+#define CODA_CMD_ENC_SEQ_MP4_PARA                              0x198
+#define                CODA_MP4PARAM_VERID_OFFSET                      6
+#define                CODA_MP4PARAM_VERID_MASK                        0x01
+#define                CODA_MP4PARAM_INTRADCVLCTHR_OFFSET              2
+#define                CODA_MP4PARAM_INTRADCVLCTHR_MASK                0x07
+#define                CODA_MP4PARAM_REVERSIBLEVLCENABLE_OFFSET        1
+#define                CODA_MP4PARAM_REVERSIBLEVLCENABLE_MASK          0x01
+#define                CODA_MP4PARAM_DATAPARTITIONENABLE_OFFSET        0
+#define                CODA_MP4PARAM_DATAPARTITIONENABLE_MASK          0x01
+#define CODA_CMD_ENC_SEQ_263_PARA                              0x19c
+#define                CODA_263PARAM_ANNEXJENABLE_OFFSET               2
+#define                CODA_263PARAM_ANNEXJENABLE_MASK         0x01
+#define                CODA_263PARAM_ANNEXKENABLE_OFFSET               1
+#define                CODA_263PARAM_ANNEXKENABLE_MASK         0x01
+#define                CODA_263PARAM_ANNEXTENABLE_OFFSET               0
+#define                CODA_263PARAM_ANNEXTENABLE_MASK         0x01
+#define CODA_CMD_ENC_SEQ_264_PARA                              0x1a0
+#define                CODA_264PARAM_DEBLKFILTEROFFSETBETA_OFFSET      12
+#define                CODA_264PARAM_DEBLKFILTEROFFSETBETA_MASK        0x0f
+#define                CODA_264PARAM_DEBLKFILTEROFFSETALPHA_OFFSET     8
+#define                CODA_264PARAM_DEBLKFILTEROFFSETALPHA_MASK       0x0f
+#define                CODA_264PARAM_DISABLEDEBLK_OFFSET               6
+#define                CODA_264PARAM_DISABLEDEBLK_MASK         0x01
+#define                CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_OFFSET   5
+#define                CODA_264PARAM_CONSTRAINEDINTRAPREDFLAG_MASK     0x01
+#define                CODA_264PARAM_CHROMAQPOFFSET_OFFSET             0
+#define                CODA_264PARAM_CHROMAQPOFFSET_MASK               0x1f
+#define CODA_CMD_ENC_SEQ_SLICE_MODE                            0x1a4
+#define                CODA_SLICING_SIZE_OFFSET                        2
+#define                CODA_SLICING_SIZE_MASK                          0x3fffffff
+#define                CODA_SLICING_UNIT_OFFSET                        1
+#define                CODA_SLICING_UNIT_MASK                          0x01
+#define                CODA_SLICING_MODE_OFFSET                        0
+#define                CODA_SLICING_MODE_MASK                          0x01
+#define CODA_CMD_ENC_SEQ_GOP_SIZE                              0x1a8
+#define                CODA_GOP_SIZE_OFFSET                            0
+#define                CODA_GOP_SIZE_MASK                              0x3f
+#define CODA_CMD_ENC_SEQ_RC_PARA                               0x1ac
+#define                CODA_RATECONTROL_AUTOSKIP_OFFSET                31
+#define                CODA_RATECONTROL_AUTOSKIP_MASK                  0x01
+#define                CODA_RATECONTROL_INITIALDELAY_OFFSET            16
+#define                CODA_RATECONTROL_INITIALDELAY_MASK              0x7f
+#define                CODA_RATECONTROL_BITRATE_OFFSET         1
+#define                CODA_RATECONTROL_BITRATE_MASK                   0x7f
+#define                CODA_RATECONTROL_ENABLE_OFFSET                  0
+#define                CODA_RATECONTROL_ENABLE_MASK                    0x01
+#define CODA_CMD_ENC_SEQ_RC_BUF_SIZE                           0x1b0
+#define CODA_CMD_ENC_SEQ_INTRA_REFRESH                         0x1b4
+#define CODADX6_CMD_ENC_SEQ_FMO                                        0x1b8
+#define                CODA_FMOPARAM_TYPE_OFFSET                       4
+#define                CODA_FMOPARAM_TYPE_MASK                         1
+#define                CODA_FMOPARAM_SLICENUM_OFFSET                   0
+#define                CODA_FMOPARAM_SLICENUM_MASK                     0x0f
+#define CODA7_CMD_ENC_SEQ_SEARCH_BASE                          0x1b8
+#define CODA7_CMD_ENC_SEQ_SEARCH_SIZE                          0x1bc
+#define CODA_CMD_ENC_SEQ_RC_QP_MAX                             0x1c8
+#define                CODA_QPMAX_OFFSET                               0
+#define                CODA_QPMAX_MASK                                 0x3f
+#define CODA_CMD_ENC_SEQ_RC_GAMMA                              0x1cc
+#define                CODA_GAMMA_OFFSET                               0
+#define                CODA_GAMMA_MASK                                 0xffff
+#define CODA_RET_ENC_SEQ_SUCCESS                               0x1c0
+
+/* Encoder Picture Run */
+#define CODA_CMD_ENC_PIC_SRC_ADDR_Y    0x180
+#define CODA_CMD_ENC_PIC_SRC_ADDR_CB   0x184
+#define CODA_CMD_ENC_PIC_SRC_ADDR_CR   0x188
+#define CODA_CMD_ENC_PIC_QS            0x18c
+#define CODA_CMD_ENC_PIC_ROT_MODE      0x190
+#define                CODA_ROT_MIR_ENABLE                             (1 << 4)
+#define                CODA_ROT_0                                      (0x0 << 0)
+#define                CODA_ROT_90                                     (0x1 << 0)
+#define                CODA_ROT_180                                    (0x2 << 0)
+#define                CODA_ROT_270                                    (0x3 << 0)
+#define                CODA_MIR_NONE                                   (0x0 << 2)
+#define                CODA_MIR_VER                                    (0x1 << 2)
+#define                CODA_MIR_HOR                                    (0x2 << 2)
+#define                CODA_MIR_VER_HOR                                (0x3 << 2)
+#define CODA_CMD_ENC_PIC_OPTION        0x194
+#define CODA_CMD_ENC_PIC_BB_START      0x198
+#define CODA_CMD_ENC_PIC_BB_SIZE       0x19c
+#define CODA_RET_ENC_PIC_TYPE          0x1c4
+#define CODA_RET_ENC_PIC_SLICE_NUM     0x1cc
+#define CODA_RET_ENC_PIC_FLAG          0x1d0
+
+/* Set Frame Buffer */
+#define CODA_CMD_SET_FRAME_BUF_NUM             0x180
+#define CODA_CMD_SET_FRAME_BUF_STRIDE          0x184
+#define CODA7_CMD_SET_FRAME_AXI_BIT_ADDR       0x190
+#define CODA7_CMD_SET_FRAME_AXI_IPACDC_ADDR    0x194
+#define CODA7_CMD_SET_FRAME_AXI_DBKY_ADDR      0x198
+#define CODA7_CMD_SET_FRAME_AXI_DBKC_ADDR      0x19c
+#define CODA7_CMD_SET_FRAME_AXI_OVL_ADDR       0x1a0
+#define CODA7_CMD_SET_FRAME_SOURCE_BUF_STRIDE  0x1a8
+
+/* Encoder Header */
+#define CODA_CMD_ENC_HEADER_CODE       0x180
+#define                CODA_GAMMA_OFFSET       0
+#define                CODA_HEADER_H264_SPS    0
+#define                CODA_HEADER_H264_PPS    1
+#define                CODA_HEADER_MP4V_VOL    0
+#define                CODA_HEADER_MP4V_VOS    1
+#define                CODA_HEADER_MP4V_VIS    2
+#define CODA_CMD_ENC_HEADER_BB_START   0x184
+#define CODA_CMD_ENC_HEADER_BB_SIZE    0x188
+
+/* Get Version */
+#define CODA_CMD_FIRMWARE_VERNUM               0x1c0
+#define                CODA_FIRMWARE_PRODUCT(x)        (((x) >> 16) & 0xffff)
+#define                CODA_FIRMWARE_MAJOR(x)          (((x) >> 12) & 0x0f)
+#define                CODA_FIRMWARE_MINOR(x)          (((x) >> 8) & 0x0f)
+#define                CODA_FIRMWARE_RELEASE(x)        ((x) & 0xff)
+#define                CODA_FIRMWARE_VERNUM(product, major, minor, release)    \
+                       ((product) << 16 | ((major) << 12) |            \
+                       ((minor) << 8) | (release))
+
+#endif
similarity index 97%
rename from drivers/media/video/davinci/Kconfig
rename to drivers/media/platform/davinci/Kconfig
index 52c5ca68cb3d38941acd97c1e00c7ae5f3048ba2..78e26d24f63754b857d923c727c628b3ee9e5596 100644 (file)
@@ -3,8 +3,8 @@ config VIDEO_DAVINCI_VPIF_DISPLAY
        depends on VIDEO_DEV && (MACH_DAVINCI_DM6467_EVM || MACH_DAVINCI_DA850_EVM)
        select VIDEOBUF2_DMA_CONTIG
        select VIDEO_DAVINCI_VPIF
-       select VIDEO_ADV7343 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_THS7303 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_ADV7343 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_THS7303 if MEDIA_SUBDRV_AUTOSELECT
        help
          Enables Davinci VPIF module used for display devices.
          This module is common for following DM6467/DA850/OMAPL138
similarity index 99%
rename from drivers/media/video/davinci/dm355_ccdc.c
rename to drivers/media/platform/davinci/dm355_ccdc.c
index 5b68847d40179fb43b988d7fe73966919158c1a7..ce0e4131c0672ba882c6a45b819ed7dfe2b960ae 100644 (file)
@@ -965,7 +965,7 @@ static struct ccdc_hw_device ccdc_hw_dev = {
        },
 };
 
-static int __init dm355_ccdc_probe(struct platform_device *pdev)
+static int __devinit dm355_ccdc_probe(struct platform_device *pdev)
 {
        void (*setup_pinmux)(void);
        struct resource *res;
similarity index 99%
rename from drivers/media/video/davinci/dm644x_ccdc.c
rename to drivers/media/platform/davinci/dm644x_ccdc.c
index 9303fe553b075899e09e529173373de77af5a871..ee7942b1996ed2fdb11f201891178d29c10317f3 100644 (file)
@@ -957,7 +957,7 @@ static struct ccdc_hw_device ccdc_hw_dev = {
        },
 };
 
-static int __init dm644x_ccdc_probe(struct platform_device *pdev)
+static int __devinit dm644x_ccdc_probe(struct platform_device *pdev)
 {
        struct resource *res;
        int status = 0;
similarity index 99%
rename from drivers/media/video/davinci/isif.c
rename to drivers/media/platform/davinci/isif.c
index 5278fe7d6d0c3638cd1eba5d6860fb0f94066361..b99d5423e3a8dc16d115c244e6e391f870924c79 100644 (file)
@@ -1032,7 +1032,7 @@ static struct ccdc_hw_device isif_hw_dev = {
        },
 };
 
-static int __init isif_probe(struct platform_device *pdev)
+static int __devinit isif_probe(struct platform_device *pdev)
 {
        void (*setup_pinmux)(void);
        struct resource *res;
similarity index 90%
rename from drivers/media/video/davinci/vpbe.c
rename to drivers/media/platform/davinci/vpbe.c
index c4a82a1a8a977f42431e47e5fba269173c48c272..9b623bc0a74439976afdb52297db2ac4c638d120 100644 (file)
@@ -174,26 +174,6 @@ static int vpbe_get_current_mode_info(struct vpbe_device *vpbe_dev,
        return 0;
 }
 
-static int vpbe_get_dv_preset_info(struct vpbe_device *vpbe_dev,
-                                  unsigned int dv_preset)
-{
-       struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct vpbe_enc_mode_info var;
-       int curr_output = vpbe_dev->current_out_index;
-       int i;
-
-       for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
-               var = cfg->outputs[curr_output].modes[i];
-               if ((var.timings_type & VPBE_ENC_DV_PRESET) &&
-                 (var.timings.dv_preset == dv_preset)) {
-                       vpbe_dev->current_timings = var;
-                       return 0;
-               }
-       }
-
-       return -EINVAL;
-}
-
 /* Get std by std id */
 static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
                             v4l2_std_id std_id)
@@ -206,7 +186,7 @@ static int vpbe_get_std_info(struct vpbe_device *vpbe_dev,
        for (i = 0; i < vpbe_dev->cfg->outputs[curr_output].num_modes; i++) {
                var = cfg->outputs[curr_output].modes[i];
                if ((var.timings_type & VPBE_ENC_STD) &&
-                 (var.timings.std_id & std_id)) {
+                 (var.std_id & std_id)) {
                        vpbe_dev->current_timings = var;
                        return 0;
                }
@@ -344,38 +324,42 @@ static unsigned int vpbe_get_output(struct vpbe_device *vpbe_dev)
 }
 
 /**
- * vpbe_s_dv_preset - Set the given preset timings in the encoder
+ * vpbe_s_dv_timings - Set the given preset timings in the encoder
  *
- * Sets the preset if supported by the current encoder. Return the status.
+ * Sets the timings if supported by the current encoder. Return the status.
  * 0 - success & -EINVAL on error
  */
-static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_s_dv_timings(struct vpbe_device *vpbe_dev,
+                   struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
+       struct vpbe_output *output = &cfg->outputs[out_index];
        int sd_index = vpbe_dev->current_sd_index;
-       int ret;
+       int ret, i;
 
 
        if (!(cfg->outputs[out_index].output.capabilities &
-           V4L2_OUT_CAP_PRESETS))
+           V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
-       ret = vpbe_get_dv_preset_info(vpbe_dev, dv_preset->preset);
-
-       if (ret)
-               return ret;
-
+       for (i = 0; i < output->num_modes; i++) {
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS &&
+                   !memcmp(&output->modes[i].dv_timings,
+                               dv_timings, sizeof(*dv_timings)))
+                       break;
+       }
+       if (i >= output->num_modes)
+               return -EINVAL;
+       vpbe_dev->current_timings = output->modes[i];
        mutex_lock(&vpbe_dev->lock);
 
-
        ret = v4l2_subdev_call(vpbe_dev->encoders[sd_index], video,
-                                       s_dv_preset, dv_preset);
+                                       s_dv_timings, dv_timings);
        if (!ret && (vpbe_dev->amp != NULL)) {
                /* Call amplifier subdevice */
                ret = v4l2_subdev_call(vpbe_dev->amp, video,
-                               s_dv_preset, dv_preset);
+                               s_dv_timings, dv_timings);
        }
        /* set the lcd controller output for the given mode */
        if (!ret) {
@@ -392,17 +376,17 @@ static int vpbe_s_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_g_dv_preset - Get the preset in the current encoder
+ * vpbe_g_dv_timings - Get the timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
-                    struct v4l2_dv_preset *dv_preset)
+static int vpbe_g_dv_timings(struct vpbe_device *vpbe_dev,
+                    struct v4l2_dv_timings *dv_timings)
 {
        if (vpbe_dev->current_timings.timings_type &
-         VPBE_ENC_DV_PRESET) {
-               dv_preset->preset = vpbe_dev->current_timings.timings.dv_preset;
+         VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
                return 0;
        }
 
@@ -410,13 +394,13 @@ static int vpbe_g_dv_preset(struct vpbe_device *vpbe_dev,
 }
 
 /**
- * vpbe_enum_dv_presets - Enumerate the dv presets in the current encoder
+ * vpbe_enum_dv_timings - Enumerate the dv timings in the current encoder
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
-static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
-                        struct v4l2_dv_enum_preset *preset_info)
+static int vpbe_enum_dv_timings(struct vpbe_device *vpbe_dev,
+                        struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_config *cfg = vpbe_dev->cfg;
        int out_index = vpbe_dev->current_out_index;
@@ -424,12 +408,12 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
        int j = 0;
        int i;
 
-       if (!(output->output.capabilities & V4L2_OUT_CAP_PRESETS))
+       if (!(output->output.capabilities & V4L2_OUT_CAP_DV_TIMINGS))
                return -EINVAL;
 
        for (i = 0; i < output->num_modes; i++) {
-               if (output->modes[i].timings_type == VPBE_ENC_DV_PRESET) {
-                       if (j == preset_info->index)
+               if (output->modes[i].timings_type == VPBE_ENC_CUSTOM_TIMINGS) {
+                       if (j == timings->index)
                                break;
                        j++;
                }
@@ -437,9 +421,8 @@ static int vpbe_enum_dv_presets(struct vpbe_device *vpbe_dev,
 
        if (i == output->num_modes)
                return -EINVAL;
-
-       return v4l_fill_dv_preset_info(output->modes[i].timings.dv_preset,
-                                       preset_info);
+       timings->timings = output->modes[i].dv_timings;
+       return 0;
 }
 
 /**
@@ -489,10 +472,10 @@ static int vpbe_s_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
  */
 static int vpbe_g_std(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id)
 {
-       struct vpbe_enc_mode_info cur_timings = vpbe_dev->current_timings;
+       struct vpbe_enc_mode_info *cur_timings = &vpbe_dev->current_timings;
 
-       if (cur_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = cur_timings.timings.std_id;
+       if (cur_timings->timings_type & VPBE_ENC_STD) {
+               *std_id = cur_timings->std_id;
                return 0;
        }
 
@@ -511,7 +494,7 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
 {
        struct vpbe_enc_mode_info *preset_mode = NULL;
        struct vpbe_config *cfg = vpbe_dev->cfg;
-       struct v4l2_dv_preset dv_preset;
+       struct v4l2_dv_timings dv_timings;
        struct osd_state *osd_device;
        int out_index = vpbe_dev->current_out_index;
        int ret = 0;
@@ -530,11 +513,12 @@ static int vpbe_set_mode(struct vpbe_device *vpbe_dev,
                         */
                        if (preset_mode->timings_type & VPBE_ENC_STD)
                                return vpbe_s_std(vpbe_dev,
-                                                &preset_mode->timings.std_id);
-                       if (preset_mode->timings_type & VPBE_ENC_DV_PRESET) {
-                               dv_preset.preset =
-                                       preset_mode->timings.dv_preset;
-                               return vpbe_s_dv_preset(vpbe_dev, &dv_preset);
+                                                &preset_mode->std_id);
+                       if (preset_mode->timings_type &
+                                               VPBE_ENC_CUSTOM_TIMINGS) {
+                               dv_timings =
+                                       preset_mode->dv_timings;
+                               return vpbe_s_dv_timings(vpbe_dev, &dv_timings);
                        }
                }
        }
@@ -810,9 +794,9 @@ static struct vpbe_device_ops vpbe_dev_ops = {
        .enum_outputs = vpbe_enum_outputs,
        .set_output = vpbe_set_output,
        .get_output = vpbe_get_output,
-       .s_dv_preset = vpbe_s_dv_preset,
-       .g_dv_preset = vpbe_g_dv_preset,
-       .enum_dv_presets = vpbe_enum_dv_presets,
+       .s_dv_timings = vpbe_s_dv_timings,
+       .g_dv_timings = vpbe_g_dv_timings,
+       .enum_dv_timings = vpbe_enum_dv_timings,
        .s_std = vpbe_s_std,
        .g_std = vpbe_g_std,
        .initialize = vpbe_initialize,
similarity index 95%
rename from drivers/media/video/davinci/vpbe_display.c
rename to drivers/media/platform/davinci/vpbe_display.c
index 6fe7034bea7c427e9da4503ea42b4b83991bb1ec..161c77650e2f88ea13fedd063c43ef306a734d67 100644 (file)
@@ -393,7 +393,7 @@ vpbe_disp_calculate_scale_factor(struct vpbe_display *disp_dev,
        int h_scale;
        int v_scale;
 
-       v4l2_std_id standard_id = vpbe_dev->current_timings.timings.std_id;
+       v4l2_std_id standard_id = vpbe_dev->current_timings.std_id;
 
        /*
         * Application initially set the image format. Current display
@@ -629,7 +629,7 @@ static int vpbe_display_querycap(struct file *file, void  *priv,
 }
 
 static int vpbe_display_s_crop(struct file *file, void *priv,
-                            struct v4l2_crop *crop)
+                            const struct v4l2_crop *crop)
 {
        struct vpbe_fh *fh = file->private_data;
        struct vpbe_layer *layer = fh->layer;
@@ -637,7 +637,7 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
        struct vpbe_device *vpbe_dev = disp_dev->vpbe_dev;
        struct osd_layer_config *cfg = &layer->layer_info.config;
        struct osd_state *osd_device = disp_dev->osd_device;
-       struct v4l2_rect *rect = &crop->c;
+       struct v4l2_rect rect = crop->c;
        int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev,
@@ -648,21 +648,21 @@ static int vpbe_display_s_crop(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       if (rect->top < 0)
-               rect->top = 0;
-       if (rect->left < 0)
-               rect->left = 0;
+       if (rect.top < 0)
+               rect.top = 0;
+       if (rect.left < 0)
+               rect.left = 0;
 
-       vpbe_disp_check_window_params(disp_dev, rect);
+       vpbe_disp_check_window_params(disp_dev, &rect);
 
        osd_device->ops.get_layer_config(osd_device,
                        layer->layer_info.id, cfg);
 
        vpbe_disp_calculate_scale_factor(disp_dev, layer,
-                                       rect->width,
-                                       rect->height);
-       vpbe_disp_adj_position(disp_dev, layer, rect->top,
-                                       rect->left);
+                                       rect.width,
+                                       rect.height);
+       vpbe_disp_adj_position(disp_dev, layer, rect.top,
+                                       rect.left);
        ret = osd_device->ops.set_layer_config(osd_device,
                                layer->layer_info.id, cfg);
        if (ret < 0) {
@@ -943,7 +943,7 @@ static int vpbe_display_g_std(struct file *file, void *priv,
 
        /* Get the standard from the current encoder */
        if (vpbe_dev->current_timings.timings_type & VPBE_ENC_STD) {
-               *std_id = vpbe_dev->current_timings.timings.std_id;
+               *std_id = vpbe_dev->current_timings.std_id;
                return 0;
        }
 
@@ -1029,29 +1029,29 @@ static int vpbe_display_g_output(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_enum_dv_presets - Enumerate the dv presets
+ * vpbe_display_enum_dv_timings - Enumerate the dv timings
  *
- * enum the preset in the current encoder. Return the status. 0 - success
+ * enum the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_enum_dv_presets(struct file *file, void *priv,
-                       struct v4l2_dv_enum_preset *preset)
+vpbe_display_enum_dv_timings(struct file *file, void *priv,
+                       struct v4l2_enum_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_ENUM_DV_TIMINGS\n");
 
        /* Enumerate outputs */
-       if (NULL == vpbe_dev->ops.enum_dv_presets)
+       if (NULL == vpbe_dev->ops.enum_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.enum_dv_presets(vpbe_dev, preset);
+       ret = vpbe_dev->ops.enum_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to enumerate dv presets info\n");
+                       "Failed to enumerate dv timings info\n");
                return -EINVAL;
        }
 
@@ -1059,21 +1059,21 @@ vpbe_display_enum_dv_presets(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_s_dv_preset - Set the dv presets
+ * vpbe_display_s_dv_timings - Set the dv timings
  *
- * Set the preset in the current encoder. Return the status. 0 - success
+ * Set the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_s_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *preset)
+vpbe_display_s_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
        int ret;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_S_DV_TIMINGS\n");
 
 
        /* If streaming is started, return error */
@@ -1083,13 +1083,13 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
        }
 
        /* Set the given standard in the encoder */
-       if (!vpbe_dev->ops.s_dv_preset)
+       if (!vpbe_dev->ops.s_dv_timings)
                return -EINVAL;
 
-       ret = vpbe_dev->ops.s_dv_preset(vpbe_dev, preset);
+       ret = vpbe_dev->ops.s_dv_timings(vpbe_dev, timings);
        if (ret) {
                v4l2_err(&vpbe_dev->v4l2_dev,
-                       "Failed to set the dv presets info\n");
+                       "Failed to set the dv timings info\n");
                return -EINVAL;
        }
        /* set the current norm to zero to be consistent. If STD is used
@@ -1101,26 +1101,25 @@ vpbe_display_s_dv_preset(struct file *file, void *priv,
 }
 
 /**
- * vpbe_display_g_dv_preset - Set the dv presets
+ * vpbe_display_g_dv_timings - Set the dv timings
  *
- * Get the preset in the current encoder. Return the status. 0 - success
+ * Get the timings in the current encoder. Return the status. 0 - success
  * -EINVAL on error
  */
 static int
-vpbe_display_g_dv_preset(struct file *file, void *priv,
-                               struct v4l2_dv_preset *dv_preset)
+vpbe_display_g_dv_timings(struct file *file, void *priv,
+                               struct v4l2_dv_timings *dv_timings)
 {
        struct vpbe_fh *fh = priv;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
 
-       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_PRESETS\n");
+       v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "VIDIOC_G_DV_TIMINGS\n");
 
        /* Get the given standard in the encoder */
 
        if (vpbe_dev->current_timings.timings_type &
-                               VPBE_ENC_DV_PRESET) {
-               dv_preset->preset =
-                       vpbe_dev->current_timings.timings.dv_preset;
+                               VPBE_ENC_CUSTOM_TIMINGS) {
+               *dv_timings = vpbe_dev->current_timings.dv_timings;
        } else {
                return -EINVAL;
        }
@@ -1376,10 +1375,15 @@ static int vpbe_display_mmap(struct file *filep, struct vm_area_struct *vma)
        struct vpbe_fh *fh = filep->private_data;
        struct vpbe_layer *layer = fh->layer;
        struct vpbe_device *vpbe_dev = fh->disp_dev->vpbe_dev;
+       int ret;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_mmap\n");
 
-       return videobuf_mmap_mapper(&layer->buffer_queue, vma);
+       if (mutex_lock_interruptible(&layer->opslock))
+               return -ERESTARTSYS;
+       ret = videobuf_mmap_mapper(&layer->buffer_queue, vma);
+       mutex_unlock(&layer->opslock);
+       return ret;
 }
 
 /* vpbe_display_poll(): It is used for select/poll system call
@@ -1392,8 +1396,11 @@ static unsigned int vpbe_display_poll(struct file *filep, poll_table *wait)
        unsigned int err = 0;
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_poll\n");
-       if (layer->started)
+       if (layer->started) {
+               mutex_lock(&layer->opslock);
                err = videobuf_poll_stream(filep, &layer->buffer_queue, wait);
+               mutex_unlock(&layer->opslock);
+       }
        return err;
 }
 
@@ -1428,10 +1435,12 @@ static int vpbe_display_open(struct file *file)
        fh->disp_dev = disp_dev;
 
        if (!layer->usrs) {
-
+               if (mutex_lock_interruptible(&layer->opslock))
+                       return -ERESTARTSYS;
                /* First claim the layer for this device */
                err = osd_device->ops.request_layer(osd_device,
                                                layer->layer_info.id);
+               mutex_unlock(&layer->opslock);
                if (err < 0) {
                        /* Couldn't get layer */
                        v4l2_err(&vpbe_dev->v4l2_dev,
@@ -1469,6 +1478,7 @@ static int vpbe_display_release(struct file *file)
 
        v4l2_dbg(1, debug, &vpbe_dev->v4l2_dev, "vpbe_display_release\n");
 
+       mutex_lock(&layer->opslock);
        /* if this instance is doing IO */
        if (fh->io_allowed) {
                /* Reset io_usrs member of layer object */
@@ -1503,6 +1513,7 @@ static int vpbe_display_release(struct file *file)
        /* Close the priority */
        v4l2_prio_close(&layer->prio, fh->prio);
        file->private_data = NULL;
+       mutex_unlock(&layer->opslock);
 
        /* Free memory allocated to file handle object */
        kfree(fh);
@@ -1560,9 +1571,9 @@ static const struct v4l2_ioctl_ops vpbe_ioctl_ops = {
        .vidioc_enum_output      = vpbe_display_enum_output,
        .vidioc_s_output         = vpbe_display_s_output,
        .vidioc_g_output         = vpbe_display_g_output,
-       .vidioc_s_dv_preset      = vpbe_display_s_dv_preset,
-       .vidioc_g_dv_preset      = vpbe_display_g_dv_preset,
-       .vidioc_enum_dv_presets  = vpbe_display_enum_dv_presets,
+       .vidioc_s_dv_timings     = vpbe_display_s_dv_timings,
+       .vidioc_g_dv_timings     = vpbe_display_g_dv_timings,
+       .vidioc_enum_dv_timings  = vpbe_display_enum_dv_timings,
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        .vidioc_g_register       = vpbe_display_g_register,
        .vidioc_s_register       = vpbe_display_s_register,
@@ -1620,18 +1631,14 @@ static __devinit int init_vpbe_layer(int i, struct vpbe_display *disp_dev,
        vbd->ioctl_ops  = &vpbe_ioctl_ops;
        vbd->minor      = -1;
        vbd->v4l2_dev   = &disp_dev->vpbe_dev->v4l2_dev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vbd->flags);
        vbd->lock       = &vpbe_display_layer->opslock;
+       vbd->vfl_dir    = VFL_DIR_TX;
 
        if (disp_dev->vpbe_dev->current_timings.timings_type &
                        VPBE_ENC_STD) {
                vbd->tvnorms = (V4L2_STD_525_60 | V4L2_STD_625_50);
                vbd->current_norm =
-                       disp_dev->vpbe_dev->
-                       current_timings.timings.std_id;
+                       disp_dev->vpbe_dev->current_timings.std_id;
        } else
                vbd->current_norm = 0;
 
similarity index 96%
rename from drivers/media/video/davinci/vpbe_venc.c
rename to drivers/media/platform/davinci/vpbe_venc.c
index 0302669622d6d6e2b409be2221d4d34f4d25a5e8..aed7369b962a7da5a5c7e6c826ce06944d12136c 100644 (file)
@@ -298,7 +298,7 @@ static int venc_set_480p59_94(struct v4l2_subdev *sd)
                return -EINVAL;
 
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_480P59_94) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -345,7 +345,7 @@ static int venc_set_576p50(struct v4l2_subdev *sd)
          (pdata->venc_type != VPBE_VERSION_2))
                return -EINVAL;
        /* Setup clock at VPSS & VENC for SD */
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_576P50) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 27000000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -385,7 +385,7 @@ static int venc_set_720p60_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_720P60) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -413,7 +413,7 @@ static int venc_set_1080i30_internal(struct v4l2_subdev *sd)
        struct venc_state *venc = to_state(sd);
        struct venc_platform_data *pdata = venc->pdata;
 
-       if (pdata->setup_clock(VPBE_ENC_DV_PRESET, V4L2_DV_1080P30) < 0)
+       if (pdata->setup_clock(VPBE_ENC_CUSTOM_TIMINGS, 74250000) < 0)
                return -EINVAL;
 
        venc_enabledigitaloutput(sd, 0);
@@ -446,26 +446,27 @@ static int venc_s_std_output(struct v4l2_subdev *sd, v4l2_std_id norm)
        return -EINVAL;
 }
 
-static int venc_s_dv_preset(struct v4l2_subdev *sd,
-                           struct v4l2_dv_preset *dv_preset)
+static int venc_s_dv_timings(struct v4l2_subdev *sd,
+                           struct v4l2_dv_timings *dv_timings)
 {
        struct venc_state *venc = to_state(sd);
+       u32 height = dv_timings->bt.height;
        int ret;
 
-       v4l2_dbg(debug, 1, sd, "venc_s_dv_preset\n");
+       v4l2_dbg(debug, 1, sd, "venc_s_dv_timings\n");
 
-       if (dv_preset->preset == V4L2_DV_576P50)
+       if (height == 576)
                return venc_set_576p50(sd);
-       else if (dv_preset->preset == V4L2_DV_480P59_94)
+       else if (height == 480)
                return venc_set_480p59_94(sd);
-       else if ((dv_preset->preset == V4L2_DV_720P60) &&
+       else if ((height == 720) &&
                        (venc->pdata->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 720p mode here */
                ret = venc_set_720p60_internal(sd);
                /* for DM365 VPBE, there is DAC inside */
                vdaccfg_write(sd, VDAC_CONFIG_HD_V2);
                return ret;
-       } else if ((dv_preset->preset == V4L2_DV_1080I30) &&
+       } else if ((height == 1080) &&
                (venc->pdata->venc_type == VPBE_VERSION_2)) {
                /* TBD setup internal 1080i mode here */
                ret = venc_set_1080i30_internal(sd);
@@ -518,7 +519,7 @@ static const struct v4l2_subdev_core_ops venc_core_ops = {
 static const struct v4l2_subdev_video_ops venc_video_ops = {
        .s_routing = venc_s_routing,
        .s_std_output = venc_s_std_output,
-       .s_dv_preset = venc_s_dv_preset,
+       .s_dv_timings = venc_s_dv_timings,
 };
 
 static const struct v4l2_subdev_ops venc_ops = {
similarity index 98%
rename from drivers/media/video/davinci/vpfe_capture.c
rename to drivers/media/platform/davinci/vpfe_capture.c
index 49a845fb804a006fb0951a4426d543f31ac986d0..8be492cd8ed46bf58a9cd79ce4d26ed8474404aa 100644 (file)
@@ -1131,11 +1131,11 @@ static int vpfe_s_input(struct file *file, void *priv, unsigned int index)
                ret = -EBUSY;
                goto unlock_out;
        }
-
-       if (vpfe_get_subdev_input_index(vpfe_dev,
-                                       &subdev_index,
-                                       &inp_index,
-                                       index) < 0) {
+       ret = vpfe_get_subdev_input_index(vpfe_dev,
+                                         &subdev_index,
+                                         &inp_index,
+                                         index);
+       if (ret < 0) {
                v4l2_err(&vpfe_dev->v4l2_dev, "invalid input index\n");
                goto unlock_out;
        }
@@ -1666,9 +1666,10 @@ static int vpfe_g_crop(struct file *file, void *priv,
 }
 
 static int vpfe_s_crop(struct file *file, void *priv,
-                            struct v4l2_crop *crop)
+                            const struct v4l2_crop *crop)
 {
        struct vpfe_device *vpfe_dev = video_drvdata(file);
+       struct v4l2_rect rect = crop->c;
        int ret = 0;
 
        v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev, "vpfe_s_crop\n");
@@ -1684,7 +1685,7 @@ static int vpfe_s_crop(struct file *file, void *priv,
        if (ret)
                return ret;
 
-       if (crop->c.top < 0 || crop->c.left < 0) {
+       if (rect.top < 0 || rect.left < 0) {
                v4l2_err(&vpfe_dev->v4l2_dev,
                        "doesn't support negative values for top & left\n");
                ret = -EINVAL;
@@ -1692,26 +1693,26 @@ static int vpfe_s_crop(struct file *file, void *priv,
        }
 
        /* adjust the width to 16 pixel boundary */
-       crop->c.width = ((crop->c.width + 15) & ~0xf);
+       rect.width = ((rect.width + 15) & ~0xf);
 
        /* make sure parameters are valid */
-       if ((crop->c.left + crop->c.width >
+       if ((rect.left + rect.width >
                vpfe_dev->std_info.active_pixels) ||
-           (crop->c.top + crop->c.height >
+           (rect.top + rect.height >
                vpfe_dev->std_info.active_lines)) {
                v4l2_err(&vpfe_dev->v4l2_dev, "Error in S_CROP params\n");
                ret = -EINVAL;
                goto unlock_out;
        }
-       ccdc_dev->hw_ops.set_image_window(&crop->c);
-       vpfe_dev->fmt.fmt.pix.width = crop->c.width;
-       vpfe_dev->fmt.fmt.pix.height = crop->c.height;
+       ccdc_dev->hw_ops.set_image_window(&rect);
+       vpfe_dev->fmt.fmt.pix.width = rect.width;
+       vpfe_dev->fmt.fmt.pix.height = rect.height;
        vpfe_dev->fmt.fmt.pix.bytesperline =
                ccdc_dev->hw_ops.get_line_length();
        vpfe_dev->fmt.fmt.pix.sizeimage =
                vpfe_dev->fmt.fmt.pix.bytesperline *
                vpfe_dev->fmt.fmt.pix.height;
-       vpfe_dev->crop = crop->c;
+       vpfe_dev->crop = rect;
 unlock_out:
        mutex_unlock(&vpfe_dev->lock);
        return ret;
@@ -1748,8 +1749,9 @@ static long vpfe_param_handler(struct file *file, void *priv,
                                        "Error setting parameters in CCDC\n");
                                goto unlock_out;
                        }
-                       if (vpfe_get_ccdc_image_format(vpfe_dev,
-                                                      &vpfe_dev->fmt) < 0) {
+                       ret = vpfe_get_ccdc_image_format(vpfe_dev,
+                                                        &vpfe_dev->fmt);
+                       if (ret < 0) {
                                v4l2_dbg(1, debug, &vpfe_dev->v4l2_dev,
                                        "Invalid image format at CCDC\n");
                                goto unlock_out;
@@ -1829,7 +1831,7 @@ static struct vpfe_device *vpfe_initialize(void)
  * itself to the V4L2 driver and initializes fields of each
  * device objects
  */
-static __init int vpfe_probe(struct platform_device *pdev)
+static __devinit int vpfe_probe(struct platform_device *pdev)
 {
        struct vpfe_subdev_info *sdinfo;
        struct vpfe_config *vpfe_cfg;
similarity index 96%
rename from drivers/media/video/davinci/vpif.c
rename to drivers/media/platform/davinci/vpif.c
index b3637aff8fee85be4eff1d5e23eeb5c6881efcdf..cff3c0ab501f6751c745fbdf9461a3dc745f837e 100644 (file)
@@ -25,6 +25,8 @@
 #include <linux/io.h>
 #include <linux/clk.h>
 #include <linux/err.h>
+#include <linux/v4l2-dv-timings.h>
+
 #include <mach/hardware.h>
 
 #include "vpif.h"
@@ -65,7 +67,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_480P59_94,
+               .dv_timings = V4L2_DV_BT_CEA_720X480P59_94,
        },
        {
                .name = "576p50",
@@ -82,7 +84,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_576P50,
+               .dv_timings = V4L2_DV_BT_CEA_720X576P50,
        },
        {
                .name = "720p50",
@@ -99,7 +101,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_720P50,
+               .dv_timings = V4L2_DV_BT_CEA_1280X720P50,
        },
        {
                .name = "720p60",
@@ -116,7 +118,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_720P60,
+               .dv_timings = V4L2_DV_BT_CEA_1280X720P60,
        },
        {
                .name = "1080I50",
@@ -136,7 +138,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_1080I50,
+               .dv_timings = V4L2_DV_BT_CEA_1920X1080I50,
        },
        {
                .name = "1080I60",
@@ -156,7 +158,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_1080I60,
+               .dv_timings = V4L2_DV_BT_CEA_1920X1080I60,
        },
        {
                .name = "1080p60",
@@ -173,7 +175,7 @@ const struct vpif_channel_config_params ch_params[] = {
                .capture_format = 0,
                .vbi_supported = 0,
                .hd_sd = 1,
-               .dv_preset = V4L2_DV_1080P60,
+               .dv_timings = V4L2_DV_BT_CEA_1920X1080P60,
        },
 
        /* SDTV formats */
@@ -417,7 +419,7 @@ int vpif_channel_getfid(u8 channel_id)
 }
 EXPORT_SYMBOL(vpif_channel_getfid);
 
-static int __init vpif_probe(struct platform_device *pdev)
+static int __devinit vpif_probe(struct platform_device *pdev)
 {
        int status = 0;
 
similarity index 99%
rename from drivers/media/video/davinci/vpif.h
rename to drivers/media/platform/davinci/vpif.h
index c2ce4d97c279cd8aaf24983da4ea29124a6f48ce..a1ab6a0f4e9e53406d2fb91027b0479f63a35767 100644 (file)
@@ -533,7 +533,7 @@ static inline void channel2_clipping_enable(int enable)
        }
 }
 
-/* function to enable clipping (for both active and blanking regions) on ch 2 */
+/* function to enable clipping (for both active and blanking regions) on ch 3 */
 static inline void channel3_clipping_enable(int enable)
 {
        if (enable) {
@@ -634,7 +634,7 @@ struct vpif_channel_config_params {
                                         * supports capturing vbi or not */
        u8 hd_sd;                       /* HDTV (1) or SDTV (0) format */
        v4l2_std_id stdid;              /* SDTV format */
-       u32 dv_preset;                  /* HDTV format */
+       struct v4l2_dv_timings dv_timings;      /* HDTV format */
 };
 
 extern const unsigned int vpif_ch_params_count;
similarity index 88%
rename from drivers/media/video/davinci/vpif_capture.c
rename to drivers/media/platform/davinci/vpif_capture.c
index 266025e5d81d424b90ceedd4a1de6fe9c1d016e8..fcabc023885d06c66b33db117d5c744f138a2e45 100644 (file)
@@ -311,12 +311,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* configure 1 or 2 channel mode */
-       ret = vpif_config_data->setup_input_channel_mode
-                                       (vpif->std_info.ycmux_mode);
-
-       if (ret < 0) {
-               vpif_dbg(1, debug, "can't set vpif channel mode\n");
-               return ret;
+       if (vpif_config_data->setup_input_channel_mode) {
+               ret = vpif_config_data->
+                       setup_input_channel_mode(vpif->std_info.ycmux_mode);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "can't set vpif channel mode\n");
+                       return ret;
+               }
        }
 
        /* Call vpif_set_params function to set the parameters and addresses */
@@ -339,6 +340,7 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
         * Set interrupt for both the fields in VPIF Register enable channel in
         * VPIF register
         */
+       channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
        if ((VPIF_CHANNEL0_VIDEO == ch->channel_id)) {
                channel0_intr_assert();
                channel0_intr_enable(1);
@@ -350,7 +352,6 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel1_intr_enable(1);
                enable_channel1(1);
        }
-       channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
 
        return 0;
 }
@@ -551,7 +552,8 @@ static int vpif_update_std_info(struct channel_obj *ch)
                        }
                } else {
                        vpif_dbg(2, debug, "HD format\n");
-                       if (config->dv_preset == vid_ch->dv_preset) {
+                       if (!memcmp(&config->dv_timings, &vid_ch->dv_timings,
+                               sizeof(vid_ch->dv_timings))) {
                                memcpy(std_info, config, sizeof(*config));
                                break;
                        }
@@ -820,10 +822,15 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
        struct vpif_fh *fh = filep->private_data;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+       int ret;
 
        vpif_dbg(2, debug, "vpif_mmap\n");
 
-       return vb2_mmap(&common->buffer_queue, vma);
+       if (mutex_lock_interruptible(&common->lock))
+               return -ERESTARTSYS;
+       ret = vb2_mmap(&common->buffer_queue, vma);
+       mutex_unlock(&common->lock);
+       return ret;
 }
 
 /**
@@ -836,12 +843,16 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
        struct vpif_fh *fh = filep->private_data;
        struct channel_obj *channel = fh->channel;
        struct common_obj *common = &(channel->common[VPIF_VIDEO_INDEX]);
+       unsigned int res = 0;
 
        vpif_dbg(2, debug, "vpif_poll\n");
 
-       if (common->started)
-               return vb2_poll(&common->buffer_queue, filep, wait);
-       return 0;
+       if (common->started) {
+               mutex_lock(&common->lock);
+               res = vb2_poll(&common->buffer_queue, filep, wait);
+               mutex_unlock(&common->lock);
+       }
+       return res;
 }
 
 /**
@@ -853,13 +864,11 @@ static unsigned int vpif_poll(struct file *filep, poll_table * wait)
  */
 static int vpif_open(struct file *filep)
 {
-       struct vpif_capture_config *config = vpif_dev->platform_data;
        struct video_device *vdev = video_devdata(filep);
        struct common_obj *common;
        struct video_obj *vid_ch;
        struct channel_obj *ch;
        struct vpif_fh *fh;
-       int i;
 
        vpif_dbg(2, debug, "vpif_open\n");
 
@@ -868,26 +877,6 @@ static int vpif_open(struct file *filep)
        vid_ch = &ch->video;
        common = &ch->common[VPIF_VIDEO_INDEX];
 
-       if (NULL == ch->curr_subdev_info) {
-               /**
-                * search through the sub device to see a registered
-                * sub device and make it as current sub device
-                */
-               for (i = 0; i < config->subdev_count; i++) {
-                       if (vpif_obj.sd[i]) {
-                               /* the sub device is registered */
-                               ch->curr_subdev_info = &config->subdev_info[i];
-                               /* make first input as the current input */
-                               vid_ch->input_idx = 0;
-                               break;
-                       }
-               }
-               if (i == config->subdev_count) {
-                       vpif_err("No sub device registered\n");
-                       return -ENOENT;
-               }
-       }
-
        /* Allocate memory for the file handle object */
        fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
        if (NULL == fh) {
@@ -895,6 +884,10 @@ static int vpif_open(struct file *filep)
                return -ENOMEM;
        }
 
+       if (mutex_lock_interruptible(&common->lock)) {
+               kfree(fh);
+               return -ERESTARTSYS;
+       }
        /* store pointer to fh in private_data member of filep */
        filep->private_data = fh;
        fh->channel = ch;
@@ -912,6 +905,7 @@ static int vpif_open(struct file *filep)
        /* Initialize priority of this instance to default priority */
        fh->prio = V4L2_PRIORITY_UNSET;
        v4l2_prio_open(&ch->prio, &fh->prio);
+       mutex_unlock(&common->lock);
        return 0;
 }
 
@@ -932,6 +926,7 @@ static int vpif_release(struct file *filep)
 
        common = &ch->common[VPIF_VIDEO_INDEX];
 
+       mutex_lock(&common->lock);
        /* if this instance is doing IO */
        if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
                /* Reset io_usrs member of channel object */
@@ -961,6 +956,7 @@ static int vpif_release(struct file *filep)
        if (fh->initialized)
                ch->initialized = 0;
 
+       mutex_unlock(&common->lock);
        filep->private_data = NULL;
        kfree(fh);
        return 0;
@@ -980,6 +976,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        struct common_obj *common;
        u8 index = 0;
        struct vb2_queue *q;
+       int ret;
 
        vpif_dbg(2, debug, "vpif_reqbufs\n");
 
@@ -1019,8 +1016,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_cap_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_capture: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1158,10 +1159,9 @@ static int vpif_streamon(struct file *file, void *priv,
                return ret;
 
        /* Enable streamon on the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 1);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 1);
 
-       if (ret && (ret != -ENOIOCTLCMD)) {
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "stream on failed in subdev\n");
                return ret;
        }
@@ -1221,73 +1221,105 @@ static int vpif_streamoff(struct file *file, void *priv,
 
        common->started = 0;
 
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               s_stream, 0);
+       ret = v4l2_subdev_call(ch->sd, video, s_stream, 0);
 
-       if (ret && (ret != -ENOIOCTLCMD))
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV)
                vpif_dbg(1, debug, "stream off failed in subdev\n");
 
        return vb2_streamoff(&common->buffer_queue, buftype);
 }
 
 /**
- * vpif_map_sub_device_to_input() - Maps sub device to input
- * @ch - ptr to channel
- * @config - ptr to capture configuration
+ * vpif_input_to_subdev() - Maps input to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
  * @input_index - Given input index from application
- * @sub_device_index - index into sd table
  *
  * lookup the sub device information for a given input index.
  * we report all the inputs to application. inputs table also
  * has sub device name for the each input
  */
-static struct vpif_subdev_info *vpif_map_sub_device_to_input(
-                               struct channel_obj *ch,
-                               struct vpif_capture_config *vpif_cfg,
-                               int input_index,
-                               int *sub_device_index)
+static int vpif_input_to_subdev(
+               struct vpif_capture_config *vpif_cfg,
+               struct vpif_capture_chan_config *chan_cfg,
+               int input_index)
 {
-       struct vpif_capture_chan_config *chan_cfg;
-       struct vpif_subdev_info *subdev_info = NULL;
-       const char *subdev_name = NULL;
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
        int i;
 
-       vpif_dbg(2, debug, "vpif_map_sub_device_to_input\n");
+       vpif_dbg(2, debug, "vpif_input_to_subdev\n");
 
-       chan_cfg = &vpif_cfg->chan_config[ch->channel_id];
-
-       /**
-        * search through the inputs to find the sub device supporting
-        * the input
-        */
-       for (i = 0; i < chan_cfg->input_count; i++) {
-               /* For each sub device, loop through input */
-               if (i == input_index) {
-                       subdev_name = chan_cfg->inputs[i].subdev_name;
-                       break;
-               }
-       }
-
-       /* if reached maximum. return null */
-       if (i == chan_cfg->input_count || (NULL == subdev_name))
-               return subdev_info;
+       subdev_name = chan_cfg->inputs[input_index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
 
        /* loop through the sub device list to get the sub device info */
        for (i = 0; i < vpif_cfg->subdev_count; i++) {
                subdev_info = &vpif_cfg->subdev_info[i];
                if (!strcmp(subdev_info->name, subdev_name))
-                       break;
+                       return i;
        }
+       return -1;
+}
 
-       if (i == vpif_cfg->subdev_count)
-               return subdev_info;
+/**
+ * vpif_set_input() - Select an input
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @_index - Given input index from application
+ *
+ * Select the given input.
+ */
+static int vpif_set_input(
+               struct vpif_capture_config *vpif_cfg,
+               struct channel_obj *ch,
+               int index)
+{
+       struct vpif_capture_chan_config *chan_cfg =
+                       &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
 
-       /* check if the sub device is registered */
-       if (NULL == vpif_obj.sd[i])
-               return NULL;
+       sd_index = vpif_input_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdev_info[sd_index];
+       }
+
+       /* first setup input path from sub device to vpif */
+       if (sd && vpif_cfg->setup_input_path) {
+               ret = vpif_cfg->setup_input_path(ch->channel_id,
+                                      subdev_info->name);
+               if (ret < 0) {
+                       vpif_dbg(1, debug, "couldn't setup input path for the" \
+                       " sub device %s, for input index %d\n",
+                       subdev_info->name, index);
+                       return ret;
+               }
+       }
 
-       *sub_device_index = i;
-       return subdev_info;
+       if (sd) {
+               input = chan_cfg->inputs[index].input_route;
+               output = chan_cfg->inputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing,
+                               input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_dbg(1, debug, "Failed to set input\n");
+                       return ret;
+               }
+       }
+       ch->input_idx = index;
+       ch->sd = sd;
+       /* copy interface parameters to vpif */
+       ch->vpifparams.iface = chan_cfg->vpif_if;
+
+       /* update tvnorms from the sub device input info */
+       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
+       return 0;
 }
 
 /**
@@ -1307,12 +1339,16 @@ static int vpif_querystd(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_dbg(2, debug, "vpif_querystd\n");
 
        /* Call querystd function of decoder device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], video,
-                               querystd, std_id);
-       if (ret < 0)
-               vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
+       ret = v4l2_subdev_call(ch->sd, video, querystd, std_id);
 
-       return ret;
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               return -ENODATA;
+       if (ret) {
+               vpif_dbg(1, debug, "Failed to query standard for sub devices\n");
+               return ret;
+       }
+
+       return 0;
 }
 
 /**
@@ -1368,8 +1404,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 
        /* Call encoder subdevice function to set the standard */
        ch->video.stdid = *std_id;
-       ch->video.dv_preset = V4L2_DV_INVALID;
-       memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
+       memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
 
        /* Get the information about the standard */
        if (vpif_update_std_info(ch)) {
@@ -1381,11 +1416,12 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
        vpif_config_format(ch);
 
        /* set standard in the sub device */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                               s_std, *std_id);
-       if (ret < 0)
+       ret = v4l2_subdev_call(ch->sd, core, s_std, *std_id);
+       if (ret && ret != -ENOIOCTLCMD && ret != -ENODEV) {
                vpif_dbg(1, debug, "Failed to set standard for sub devices\n");
-       return ret;
+               return ret;
+       }
+       return 0;
 }
 
 /**
@@ -1425,10 +1461,8 @@ static int vpif_g_input(struct file *file, void *priv, unsigned int *index)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
-
-       *index = vid_ch->input_idx;
 
+       *index = ch->input_idx;
        return 0;
 }
 
@@ -1445,13 +1479,13 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       struct video_obj *vid_ch = &ch->video;
-       struct vpif_subdev_info *subdev_info;
-       int ret = 0, sd_index = 0;
-       u32 input = 0, output = 0;
+       int ret;
 
        chan_cfg = &config->chan_config[ch->channel_id];
 
+       if (index >= chan_cfg->input_count)
+               return -EINVAL;
+
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
@@ -1470,45 +1504,7 @@ static int vpif_s_input(struct file *file, void *priv, unsigned int index)
                return ret;
 
        fh->initialized = 1;
-       subdev_info = vpif_map_sub_device_to_input(ch, config, index,
-                                                  &sd_index);
-       if (NULL == subdev_info) {
-               vpif_dbg(1, debug,
-                       "couldn't lookup sub device for the input index\n");
-               return -EINVAL;
-       }
-
-       /* first setup input path from sub device to vpif */
-       if (config->setup_input_path) {
-               ret = config->setup_input_path(ch->channel_id,
-                                              subdev_info->name);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "couldn't setup input path for the"
-                               " sub device %s, for input index %d\n",
-                               subdev_info->name, index);
-                       return ret;
-               }
-       }
-
-       if (subdev_info->can_route) {
-               input = subdev_info->input;
-               output = subdev_info->output;
-               ret = v4l2_subdev_call(vpif_obj.sd[sd_index], video, s_routing,
-                                       input, output, 0);
-               if (ret < 0) {
-                       vpif_dbg(1, debug, "Failed to set input\n");
-                       return ret;
-               }
-       }
-       vid_ch->input_idx = index;
-       ch->curr_subdev_info = subdev_info;
-       ch->curr_sd_index = sd_index;
-       /* copy interface parameters to vpif */
-       ch->vpifparams.iface = subdev_info->vpif_if;
-
-       /* update tvnorms from the sub device input info */
-       ch->video_dev->tvnorms = chan_cfg->inputs[index].input.std;
-       return ret;
+       return vpif_set_input(config, ch, index);
 }
 
 /**
@@ -1639,9 +1635,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_capture_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif capture", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "VPIF Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -1703,109 +1701,44 @@ static int vpif_cropcap(struct file *file, void *priv,
 }
 
 /**
- * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler
  * @file: file ptr
  * @priv: file handle
- * @preset: input preset
+ * @timings: input timings
  */
-static int vpif_enum_dv_presets(struct file *file, void *priv,
-               struct v4l2_dv_enum_preset *preset)
+static int
+vpif_enum_dv_timings(struct file *file, void *priv,
+                    struct v4l2_enum_dv_timings *timings)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
+       int ret;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                       video, enum_dv_presets, preset);
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
+       return ret;
 }
 
 /**
- * vpif_query_dv_presets() - QUERY_DV_PRESET handler
- * @file: file ptr
- * @priv: file handle
- * @preset: input preset
- */
-static int vpif_query_dv_preset(struct file *file, void *priv,
-               struct v4l2_dv_preset *preset)
-{
-       struct vpif_fh *fh = priv;
-       struct channel_obj *ch = fh->channel;
-
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                      video, query_dv_preset, preset);
-}
-/**
- * vpif_s_dv_presets() - S_DV_PRESETS handler
+ * vpif_query_dv_timings() - QUERY_DV_TIMINGS handler
  * @file: file ptr
  * @priv: file handle
- * @preset: input preset
+ * @timings: input timings
  */
-static int vpif_s_dv_preset(struct file *file, void *priv,
-               struct v4l2_dv_preset *preset)
+static int
+vpif_query_dv_timings(struct file *file, void *priv,
+                     struct v4l2_dv_timings *timings)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       int ret = 0;
-
-       if (common->started) {
-               vpif_dbg(1, debug, "streaming in progress\n");
-               return -EBUSY;
-       }
-
-       if ((VPIF_CHANNEL0_VIDEO == ch->channel_id) ||
-           (VPIF_CHANNEL1_VIDEO == ch->channel_id)) {
-               if (!fh->initialized) {
-                       vpif_dbg(1, debug, "Channel Busy\n");
-                       return -EBUSY;
-               }
-       }
-
-       ret = v4l2_prio_check(&ch->prio, fh->prio);
-       if (ret)
-               return ret;
-
-       fh->initialized = 1;
-
-       /* Call encoder subdevice function to set the standard */
-       if (mutex_lock_interruptible(&common->lock))
-               return -ERESTARTSYS;
-
-       ch->video.dv_preset = preset->preset;
-       ch->video.stdid = V4L2_STD_UNKNOWN;
-       memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
-
-       /* Get the information about the standard */
-       if (vpif_update_std_info(ch)) {
-               vpif_dbg(1, debug, "Error getting the standard info\n");
-               ret = -EINVAL;
-       } else {
-               /* Configure the default format information */
-               vpif_config_format(ch);
-
-               ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                               video, s_dv_preset, preset);
-       }
-
-       mutex_unlock(&common->lock);
+       int ret;
 
+       ret = v4l2_subdev_call(ch->sd, video, query_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -ENODATA;
        return ret;
 }
-/**
- * vpif_g_dv_presets() - G_DV_PRESETS handler
- * @file: file ptr
- * @priv: file handle
- * @preset: input preset
- */
-static int vpif_g_dv_preset(struct file *file, void *priv,
-               struct v4l2_dv_preset *preset)
-{
-       struct vpif_fh *fh = priv;
-       struct channel_obj *ch = fh->channel;
-
-       preset->preset = ch->video.dv_preset;
-
-       return 0;
-}
 
 /**
  * vpif_s_dv_timings() - S_DV_TIMINGS handler
@@ -1821,7 +1754,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        struct vpif_params *vpifparams = &ch->vpifparams;
        struct vpif_channel_config_params *std_info = &vpifparams->std_info;
        struct video_obj *vid_ch = &ch->video;
-       struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+       struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt;
        int ret;
 
        if (timings->type != V4L2_DV_BT_656_1120) {
@@ -1830,13 +1763,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1857,7 +1786,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       *bt = timings->bt;
+       vid_ch->dv_timings = *timings;
 
        /* Configure video port timings */
 
@@ -1900,10 +1829,8 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        std_info->vbi_supported = 0;
        std_info->hd_sd = 1;
        std_info->stdid = 0;
-       std_info->dv_preset = V4L2_DV_INVALID;
 
        vid_ch->stdid = 0;
-       vid_ch->dv_preset = V4L2_DV_INVALID;
        return 0;
 }
 
@@ -1919,9 +1846,8 @@ static int vpif_g_dv_timings(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct video_obj *vid_ch = &ch->video;
-       struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
 
-       timings->bt = *bt;
+       *timings = vid_ch->dv_timings;
 
        return 0;
 }
@@ -1964,8 +1890,7 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1982,8 +1907,7 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
 
-       return v4l2_subdev_call(vpif_obj.sd[ch->curr_sd_index], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -2024,10 +1948,8 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
        .vidioc_streamon                = vpif_streamon,
        .vidioc_streamoff               = vpif_streamoff,
        .vidioc_cropcap                 = vpif_cropcap,
-       .vidioc_enum_dv_presets         = vpif_enum_dv_presets,
-       .vidioc_s_dv_preset             = vpif_s_dv_preset,
-       .vidioc_g_dv_preset             = vpif_g_dv_preset,
-       .vidioc_query_dv_preset         = vpif_query_dv_preset,
+       .vidioc_enum_dv_timings         = vpif_enum_dv_timings,
+       .vidioc_query_dv_timings        = vpif_query_dv_timings,
        .vidioc_s_dv_timings            = vpif_s_dv_timings,
        .vidioc_g_dv_timings            = vpif_g_dv_timings,
        .vidioc_g_chip_ident            = vpif_g_chip_ident,
@@ -2123,7 +2045,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_capture_config *config;
-       int i, j, k, m, q, err;
+       int i, j, k, err;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct channel_obj *ch;
        struct common_obj *common;
@@ -2146,18 +2069,19 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Capture",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Capture", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
-                               i--;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
@@ -2171,7 +2095,7 @@ static __init int vpif_probe(struct platform_device *pdev)
                                video_device_release(ch->video_dev);
                        }
                        err = -ENOMEM;
-                       goto vpif_dev_alloc_err;
+                       goto vpif_int_err;
                }
 
                /* Initialize field of video device */
@@ -2202,28 +2126,6 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
-       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
-               ch = vpif_obj.dev[j];
-               ch->channel_id = j;
-               common = &(ch->common[VPIF_VIDEO_INDEX]);
-               spin_lock_init(&common->irqlock);
-               mutex_init(&common->lock);
-               /* Locking in file operations other than ioctl should be done
-                  by the driver, not the V4L2 core.
-                  This driver needs auditing so that this flag can be removed. */
-               set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags);
-               ch->video_dev->lock = &common->lock;
-               /* Initialize prio member of channel object */
-               v4l2_prio_init(&ch->prio);
-               err = video_register_device(ch->video_dev,
-                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
-               if (err)
-                       goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-
-       }
-
        i2c_adap = i2c_get_adapter(1);
        config = pdev->dev.platform_data;
 
@@ -2233,7 +2135,7 @@ static __init int vpif_probe(struct platform_device *pdev)
        if (vpif_obj.sd == NULL) {
                vpif_err("unable to allocate memory for subdevice pointers\n");
                err = -ENOMEM;
-               goto probe_out;
+               goto vpif_sd_error;
        }
 
        for (i = 0; i < subdev_count; i++) {
@@ -2250,19 +2152,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
                v4l2_info(&vpif_obj.v4l2_dev, "registered sub device %s\n",
                          subdevdata->name);
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
+       for (j = 0; j < VPIF_CAPTURE_MAX_DEVICES; j++) {
+               ch = vpif_obj.dev[j];
+               ch->channel_id = j;
+               common = &(ch->common[VPIF_VIDEO_INDEX]);
+               spin_lock_init(&common->irqlock);
+               mutex_init(&common->lock);
+               ch->video_dev->lock = &common->lock;
+               /* Initialize prio member of channel object */
+               v4l2_prio_init(&ch->prio);
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select input 0 */
+               err = vpif_set_input(config, ch, 0);
+               if (err)
+                       goto probe_out;
+
+               err = video_register_device(ch->video_dev,
+                                           VFL_TYPE_GRABBER, (j ? 1 : 0));
+               if (err)
+                       goto probe_out;
+       }
        v4l2_info(&vpif_obj.v4l2_dev, "VPIF capture driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       /* free sub devices memory */
-       kfree(vpif_obj.sd);
-
-       j = VPIF_CAPTURE_MAX_DEVICES;
 probe_out:
        for (k = 0; k < j; k++) {
                /* Get the pointer to the channel object */
@@ -2270,22 +2185,23 @@ probe_out:
                /* Unregister video device */
                video_unregister_device(ch->video_dev);
        }
+probe_subdev_out:
+       /* free sub devices memory */
+       kfree(vpif_obj.sd);
 
-vpif_dev_alloc_err:
-       k = VPIF_CAPTURE_MAX_DEVICES-1;
-       res = platform_get_resource(pdev, IORESOURCE_IRQ, k);
-       i = res->end;
-
-vpif_int_err:
-       for (q = k; q >= 0; q--) {
-               for (m = i; m >= (int)res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[q]->channel_id));
-
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, q-1);
-               if (res)
-                       i = res->end;
+vpif_sd_error:
+       for (i = 0; i < VPIF_CAPTURE_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
        }
+vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
+       }
        return err;
 }
 
similarity index 91%
rename from drivers/media/video/davinci/vpif_capture.h
rename to drivers/media/platform/davinci/vpif_capture.h
index 3511510f43ee32098732e0f480f1067579404a69..3d3c1e5cd5d4c63c1eb23b61be1574296ab27885 100644 (file)
@@ -25,7 +25,6 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
-#include <media/videobuf-core.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/davinci/vpif_types.h>
 
@@ -54,10 +53,7 @@ struct video_obj {
        enum v4l2_field buf_field;
        /* Currently selected or default standard */
        v4l2_std_id stdid;
-       u32 dv_preset;
-       struct v4l2_bt_timings bt_timings;
-       /* This is to track the last input that is passed to application */
-       u32 input_idx;
+       struct v4l2_dv_timings dv_timings;
 };
 
 struct vpif_cap_buffer {
@@ -121,10 +117,10 @@ struct channel_obj {
        u8 initialized;
        /* Identifies channel */
        enum vpif_channel_id channel_id;
-       /* index into sd table */
-       int curr_sd_index;
-       /* ptr to current sub device information */
-       struct vpif_subdev_info *curr_subdev_info;
+       /* Current input */
+       u32 input_idx;
+       /* subdev corresponding to the current input, may be NULL */
+       struct v4l2_subdev *sd;
        /* vpif configuration params */
        struct vpif_params vpifparams;
        /* common object array */
@@ -161,10 +157,6 @@ struct vpif_config_params {
        u32 video_limit[VPIF_CAPTURE_NUM_CHANNELS];
        u8 max_device_type;
 };
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-};
+
 #endif                         /* End of __KERNEL__ */
 #endif                         /* VPIF_CAPTURE_H */
similarity index 89%
rename from drivers/media/video/davinci/vpif_display.c
rename to drivers/media/platform/davinci/vpif_display.c
index e129c98921ad493b0b8ea90562d2878325218fc5..b716fbd4241f8599f90c8dbf7caf4b99e0f338bb 100644 (file)
@@ -280,12 +280,13 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
        }
 
        /* clock settings */
-       ret =
-           vpif_config_data->set_clock(ch->vpifparams.std_info.ycmux_mode,
-                                       ch->vpifparams.std_info.hd_sd);
-       if (ret < 0) {
-               vpif_err("can't set clock\n");
-               return ret;
+       if (vpif_config_data->set_clock) {
+               ret = vpif_config_data->set_clock(ch->vpifparams.std_info.
+               ycmux_mode, ch->vpifparams.std_info.hd_sd);
+               if (ret < 0) {
+                       vpif_err("can't set clock\n");
+                       return ret;
+               }
        }
 
        /* set the parameters and addresses */
@@ -302,11 +303,12 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
 
        /* Set interrupt for both the fields in VPIF
            Register enable channel in VPIF register */
+       channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
        if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
                channel2_intr_assert();
                channel2_intr_enable(1);
                enable_channel2(1);
-               if (vpif_config_data->ch2_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                        channel2_clipping_enable(1);
        }
 
@@ -315,10 +317,9 @@ static int vpif_start_streaming(struct vb2_queue *vq, unsigned int count)
                channel3_intr_assert();
                channel3_intr_enable(1);
                enable_channel3(1);
-               if (vpif_config_data->ch3_clip_en)
+               if (vpif_config_data->chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                        channel3_clipping_enable(1);
        }
-       channel_first_int[VPIF_VIDEO_INDEX][ch->channel_id] = 1;
 
        return 0;
 }
@@ -499,12 +500,6 @@ static int vpif_update_std_info(struct channel_obj *ch)
                                memcpy(std_info, config, sizeof(*config));
                                break;
                        }
-               } else {
-                       vpif_dbg(2, debug, "HD format\n");
-                       if (config->dv_preset == vid_ch->dv_preset) {
-                               memcpy(std_info, config, sizeof(*config));
-                               break;
-                       }
                }
        }
 
@@ -523,10 +518,10 @@ static int vpif_update_resolution(struct channel_obj *ch)
        struct vpif_params *vpifparams = &ch->vpifparams;
        struct vpif_channel_config_params *std_info = &vpifparams->std_info;
 
-       if (!vid_ch->stdid && !vid_ch->dv_preset && !vid_ch->bt_timings.height)
+       if (!vid_ch->stdid && !vid_ch->dv_timings.bt.height)
                return -EINVAL;
 
-       if (vid_ch->stdid || vid_ch->dv_preset) {
+       if (vid_ch->stdid) {
                if (vpif_update_std_info(ch))
                        return -EINVAL;
        }
@@ -695,10 +690,15 @@ static int vpif_mmap(struct file *filep, struct vm_area_struct *vma)
        struct vpif_fh *fh = filep->private_data;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &(ch->common[VPIF_VIDEO_INDEX]);
+       int ret;
 
        vpif_dbg(2, debug, "vpif_mmap\n");
 
-       return vb2_mmap(&common->buffer_queue, vma);
+       if (mutex_lock_interruptible(&common->lock))
+               return -ERESTARTSYS;
+       ret = vb2_mmap(&common->buffer_queue, vma);
+       mutex_unlock(&common->lock);
+       return ret;
 }
 
 /*
@@ -709,11 +709,15 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait)
        struct vpif_fh *fh = filep->private_data;
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+       unsigned int res = 0;
 
-       if (common->started)
-               return vb2_poll(&common->buffer_queue, filep, wait);
+       if (common->started) {
+               mutex_lock(&common->lock);
+               res = vb2_poll(&common->buffer_queue, filep, wait);
+               mutex_unlock(&common->lock);
+       }
 
-       return 0;
+       return res;
 }
 
 /*
@@ -723,10 +727,10 @@ static unsigned int vpif_poll(struct file *filep, poll_table *wait)
 static int vpif_open(struct file *filep)
 {
        struct video_device *vdev = video_devdata(filep);
-       struct channel_obj *ch = NULL;
-       struct vpif_fh *fh = NULL;
+       struct channel_obj *ch = video_get_drvdata(vdev);
+       struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
+       struct vpif_fh *fh;
 
-       ch = video_get_drvdata(vdev);
        /* Allocate memory for the file handle object */
        fh = kzalloc(sizeof(struct vpif_fh), GFP_KERNEL);
        if (fh == NULL) {
@@ -734,6 +738,10 @@ static int vpif_open(struct file *filep)
                return -ENOMEM;
        }
 
+       if (mutex_lock_interruptible(&common->lock)) {
+               kfree(fh);
+               return -ERESTARTSYS;
+       }
        /* store pointer to fh in private_data member of filep */
        filep->private_data = fh;
        fh->channel = ch;
@@ -751,6 +759,7 @@ static int vpif_open(struct file *filep)
        /* Initialize priority of this instance to default priority */
        fh->prio = V4L2_PRIORITY_UNSET;
        v4l2_prio_open(&ch->prio, &fh->prio);
+       mutex_unlock(&common->lock);
 
        return 0;
 }
@@ -765,6 +774,7 @@ static int vpif_release(struct file *filep)
        struct channel_obj *ch = fh->channel;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
 
+       mutex_lock(&common->lock);
        /* if this instance is doing IO */
        if (fh->io_allowed[VPIF_VIDEO_INDEX]) {
                /* Reset io_usrs member of channel object */
@@ -799,6 +809,7 @@ static int vpif_release(struct file *filep)
        v4l2_prio_close(&ch->prio, fh->prio);
        filep->private_data = NULL;
        fh->initialized = 0;
+       mutex_unlock(&common->lock);
        kfree(fh);
 
        return 0;
@@ -816,9 +827,11 @@ static int vpif_querycap(struct file *file, void  *priv,
 {
        struct vpif_display_config *config = vpif_dev->platform_data;
 
-       cap->capabilities = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
-       strlcpy(cap->driver, "vpif display", sizeof(cap->driver));
-       strlcpy(cap->bus_info, "Platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       snprintf(cap->driver, sizeof(cap->driver), "%s", dev_name(vpif_dev));
+       snprintf(cap->bus_info, sizeof(cap->bus_info), "platform:%s",
+                dev_name(vpif_dev));
        strlcpy(cap->card, config->card_name, sizeof(cap->card));
 
        return 0;
@@ -925,6 +938,7 @@ static int vpif_reqbufs(struct file *file, void *priv,
        enum v4l2_field field;
        struct vb2_queue *q;
        u8 index = 0;
+       int ret;
 
        /* This file handle has not initialized the channel,
           It is not allowed to do settings */
@@ -970,8 +984,12 @@ static int vpif_reqbufs(struct file *file, void *priv,
        q->mem_ops = &vb2_dma_contig_memops;
        q->buf_struct_size = sizeof(struct vpif_disp_buffer);
 
-       vb2_queue_init(q);
-
+       ret = vb2_queue_init(q);
+       if (ret) {
+               vpif_err("vpif_display: vb2_queue_init() failed\n");
+               vb2_dma_contig_cleanup_ctx(common->alloc_ctx);
+               return ret;
+       }
        /* Set io allowed member of file handle to TRUE */
        fh->io_allowed[index] = 1;
        /* Increment io usrs member of channel object to 1 */
@@ -1039,9 +1057,7 @@ static int vpif_s_std(struct file *file, void *priv, v4l2_std_id *std_id)
 
        /* Call encoder subdevice function to set the standard */
        ch->video.stdid = *std_id;
-       ch->video.dv_preset = V4L2_DV_INVALID;
-       memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
-
+       memset(&ch->video.dv_timings, 0, sizeof(ch->video.dv_timings));
        /* Get the information about the standard */
        if (vpif_update_resolution(ch))
                return -EINVAL;
@@ -1165,14 +1181,16 @@ static int vpif_streamoff(struct file *file, void *priv,
        if (buftype == V4L2_BUF_TYPE_VIDEO_OUTPUT) {
                /* disable channel */
                if (VPIF_CHANNEL2_VIDEO == ch->channel_id) {
-                       if (vpif_config_data->ch2_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL2_VIDEO].clip_en)
                                channel2_clipping_enable(0);
                        enable_channel2(0);
                        channel2_intr_enable(0);
                }
                if ((VPIF_CHANNEL3_VIDEO == ch->channel_id) ||
                                        (2 == common->started)) {
-                       if (vpif_config_data->ch3_clip_en)
+                       if (vpif_config_data->
+                               chan_config[VPIF_CHANNEL3_VIDEO].clip_en)
                                channel3_clipping_enable(0);
                        enable_channel3(0);
                        channel3_intr_enable(0);
@@ -1205,49 +1223,126 @@ static int vpif_enum_output(struct file *file, void *fh,
 {
 
        struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
+       struct vpif_fh *vpif_handler = fh;
+       struct channel_obj *ch = vpif_handler->channel;
 
-       if (output->index >= config->output_count) {
+       chan_cfg = &config->chan_config[ch->channel_id];
+       if (output->index >= chan_cfg->output_count) {
                vpif_dbg(1, debug, "Invalid output index\n");
                return -EINVAL;
        }
 
-       strcpy(output->name, config->output[output->index]);
-       output->type = V4L2_OUTPUT_TYPE_ANALOG;
-       output->std = VPIF_V4L2_STD;
+       *output = chan_cfg->outputs[output->index].output;
+       return 0;
+}
+
+/**
+ * vpif_output_to_subdev() - Maps output to sub device
+ * @vpif_cfg - global config ptr
+ * @chan_cfg - channel config ptr
+ * @index - Given output index from application
+ *
+ * lookup the sub device information for a given output index.
+ * we report all the output to application. output table also
+ * has sub device name for the each output
+ */
+static int
+vpif_output_to_subdev(struct vpif_display_config *vpif_cfg,
+                     struct vpif_display_chan_config *chan_cfg, int index)
+{
+       struct vpif_subdev_info *subdev_info;
+       const char *subdev_name;
+       int i;
+
+       vpif_dbg(2, debug, "vpif_output_to_subdev\n");
+
+       if (chan_cfg->outputs == NULL)
+               return -1;
 
+       subdev_name = chan_cfg->outputs[index].subdev_name;
+       if (subdev_name == NULL)
+               return -1;
+
+       /* loop through the sub device list to get the sub device info */
+       for (i = 0; i < vpif_cfg->subdev_count; i++) {
+               subdev_info = &vpif_cfg->subdevinfo[i];
+               if (!strcmp(subdev_info->name, subdev_name))
+                       return i;
+       }
+       return -1;
+}
+
+/**
+ * vpif_set_output() - Select an output
+ * @vpif_cfg - global config ptr
+ * @ch - channel
+ * @index - Given output index from application
+ *
+ * Select the given output.
+ */
+static int vpif_set_output(struct vpif_display_config *vpif_cfg,
+                     struct channel_obj *ch, int index)
+{
+       struct vpif_display_chan_config *chan_cfg =
+               &vpif_cfg->chan_config[ch->channel_id];
+       struct vpif_subdev_info *subdev_info = NULL;
+       struct v4l2_subdev *sd = NULL;
+       u32 input = 0, output = 0;
+       int sd_index;
+       int ret;
+
+       sd_index = vpif_output_to_subdev(vpif_cfg, chan_cfg, index);
+       if (sd_index >= 0) {
+               sd = vpif_obj.sd[sd_index];
+               subdev_info = &vpif_cfg->subdevinfo[sd_index];
+       }
+
+       if (sd) {
+               input = chan_cfg->outputs[index].input_route;
+               output = chan_cfg->outputs[index].output_route;
+               ret = v4l2_subdev_call(sd, video, s_routing, input, output, 0);
+               if (ret < 0 && ret != -ENOIOCTLCMD) {
+                       vpif_err("Failed to set output\n");
+                       return ret;
+               }
+
+       }
+       ch->output_idx = index;
+       ch->sd = sd;
+       if (chan_cfg->outputs != NULL)
+               /* update tvnorms from the sub device output info */
+               ch->video_dev->tvnorms = chan_cfg->outputs[index].output.std;
        return 0;
 }
 
 static int vpif_s_output(struct file *file, void *priv, unsigned int i)
 {
+       struct vpif_display_config *config = vpif_dev->platform_data;
+       struct vpif_display_chan_config *chan_cfg;
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
        struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       int ret = 0;
+
+       chan_cfg = &config->chan_config[ch->channel_id];
+
+       if (i >= chan_cfg->output_count)
+               return -EINVAL;
 
        if (common->started) {
                vpif_err("Streaming in progress\n");
                return -EBUSY;
        }
 
-       ret = v4l2_device_call_until_err(&vpif_obj.v4l2_dev, 1, video,
-                                                       s_routing, 0, i, 0);
-
-       if (ret < 0)
-               vpif_err("Failed to set output standard\n");
-
-       vid_ch->output_id = i;
-       return ret;
+       return vpif_set_output(config, ch, i);
 }
 
 static int vpif_g_output(struct file *file, void *priv, unsigned int *i)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       *i = vid_ch->output_id;
+       *i = ch->output_idx;
 
        return 0;
 }
@@ -1271,87 +1366,25 @@ static int vpif_s_priority(struct file *file, void *priv, enum v4l2_priority p)
 }
 
 /**
- * vpif_enum_dv_presets() - ENUM_DV_PRESETS handler
+ * vpif_enum_dv_timings() - ENUM_DV_TIMINGS handler
  * @file: file ptr
  * @priv: file handle
- * @preset: input preset
+ * @timings: input timings
  */
-static int vpif_enum_dv_presets(struct file *file, void *priv,
-               struct v4l2_dv_enum_preset *preset)
+static int
+vpif_enum_dv_timings(struct file *file, void *priv,
+                    struct v4l2_enum_dv_timings *timings)
 {
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
-
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, enum_dv_presets, preset);
-}
-
-/**
- * vpif_s_dv_presets() - S_DV_PRESETS handler
- * @file: file ptr
- * @priv: file handle
- * @preset: input preset
- */
-static int vpif_s_dv_preset(struct file *file, void *priv,
-               struct v4l2_dv_preset *preset)
-{
-       struct vpif_fh *fh = priv;
-       struct channel_obj *ch = fh->channel;
-       struct common_obj *common = &ch->common[VPIF_VIDEO_INDEX];
-       struct video_obj *vid_ch = &ch->video;
-       int ret = 0;
-
-       if (common->started) {
-               vpif_dbg(1, debug, "streaming in progress\n");
-               return -EBUSY;
-       }
-
-       ret = v4l2_prio_check(&ch->prio, fh->prio);
-       if (ret != 0)
-               return ret;
-
-       fh->initialized = 1;
-
-       /* Call encoder subdevice function to set the standard */
-       if (mutex_lock_interruptible(&common->lock))
-               return -ERESTARTSYS;
-
-       ch->video.dv_preset = preset->preset;
-       ch->video.stdid = V4L2_STD_UNKNOWN;
-       memset(&ch->video.bt_timings, 0, sizeof(ch->video.bt_timings));
-
-       /* Get the information about the standard */
-       if (vpif_update_resolution(ch)) {
-               ret = -EINVAL;
-       } else {
-               /* Configure the default format information */
-               vpif_config_format(ch);
-
-               ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                               video, s_dv_preset, preset);
-       }
-
-       mutex_unlock(&common->lock);
+       int ret;
 
+       ret = v4l2_subdev_call(ch->sd, video, enum_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD && ret == -ENODEV)
+               return -EINVAL;
        return ret;
 }
-/**
- * vpif_g_dv_presets() - G_DV_PRESETS handler
- * @file: file ptr
- * @priv: file handle
- * @preset: input preset
- */
-static int vpif_g_dv_preset(struct file *file, void *priv,
-               struct v4l2_dv_preset *preset)
-{
-       struct vpif_fh *fh = priv;
-       struct channel_obj *ch = fh->channel;
 
-       preset->preset = ch->video.dv_preset;
-
-       return 0;
-}
 /**
  * vpif_s_dv_timings() - S_DV_TIMINGS handler
  * @file: file ptr
@@ -1366,7 +1399,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        struct vpif_params *vpifparams = &ch->vpifparams;
        struct vpif_channel_config_params *std_info = &vpifparams->std_info;
        struct video_obj *vid_ch = &ch->video;
-       struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
+       struct v4l2_bt_timings *bt = &vid_ch->dv_timings.bt;
        int ret;
 
        if (timings->type != V4L2_DV_BT_656_1120) {
@@ -1375,13 +1408,9 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        }
 
        /* Configure subdevice timings, if any */
-       ret = v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id],
-                       video, s_dv_timings, timings);
-       if (ret == -ENOIOCTLCMD) {
-               vpif_dbg(2, debug, "Custom DV timings not supported by "
-                               "subdevice\n");
-               return -EINVAL;
-       }
+       ret = v4l2_subdev_call(ch->sd, video, s_dv_timings, timings);
+       if (ret == -ENOIOCTLCMD || ret == -ENODEV)
+               ret = 0;
        if (ret < 0) {
                vpif_dbg(2, debug, "Error setting custom DV timings\n");
                return ret;
@@ -1402,7 +1431,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
                return -EINVAL;
        }
 
-       *bt = timings->bt;
+       vid_ch->dv_timings = *timings;
 
        /* Configure video port timings */
 
@@ -1446,10 +1475,7 @@ static int vpif_s_dv_timings(struct file *file, void *priv,
        std_info->vbi_supported = 0;
        std_info->hd_sd = 1;
        std_info->stdid = 0;
-       std_info->dv_preset = V4L2_DV_INVALID;
-
        vid_ch->stdid = 0;
-       vid_ch->dv_preset = V4L2_DV_INVALID;
 
        return 0;
 }
@@ -1466,9 +1492,8 @@ static int vpif_g_dv_timings(struct file *file, void *priv,
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
        struct video_obj *vid_ch = &ch->video;
-       struct v4l2_bt_timings *bt = &vid_ch->bt_timings;
 
-       timings->bt = *bt;
+       *timings = vid_ch->dv_timings;
 
        return 0;
 }
@@ -1510,10 +1535,8 @@ static int vpif_dbg_g_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       g_register, reg);
+       return v4l2_subdev_call(ch->sd, core, g_register, reg);
 }
 
 /*
@@ -1529,10 +1552,8 @@ static int vpif_dbg_s_register(struct file *file, void *priv,
                struct v4l2_dbg_register *reg){
        struct vpif_fh *fh = priv;
        struct channel_obj *ch = fh->channel;
-       struct video_obj *vid_ch = &ch->video;
 
-       return v4l2_subdev_call(vpif_obj.sd[vid_ch->output_id], core,
-                       s_register, reg);
+       return v4l2_subdev_call(ch->sd, core, s_register, reg);
 }
 #endif
 
@@ -1572,9 +1593,7 @@ static const struct v4l2_ioctl_ops vpif_ioctl_ops = {
        .vidioc_s_output                = vpif_s_output,
        .vidioc_g_output                = vpif_g_output,
        .vidioc_cropcap                 = vpif_cropcap,
-       .vidioc_enum_dv_presets         = vpif_enum_dv_presets,
-       .vidioc_s_dv_preset             = vpif_s_dv_preset,
-       .vidioc_g_dv_preset             = vpif_g_dv_preset,
+       .vidioc_enum_dv_timings         = vpif_enum_dv_timings,
        .vidioc_s_dv_timings            = vpif_s_dv_timings,
        .vidioc_g_dv_timings            = vpif_g_dv_timings,
        .vidioc_g_chip_ident            = vpif_g_chip_ident,
@@ -1598,9 +1617,6 @@ static struct video_device vpif_video_template = {
        .name           = "vpif",
        .fops           = &vpif_fops,
        .ioctl_ops      = &vpif_ioctl_ops,
-       .tvnorms        = VPIF_V4L2_STD,
-       .current_norm   = V4L2_STD_625_50,
-
 };
 
 /*Configure the channels, buffer sizei, request irq */
@@ -1673,7 +1689,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 {
        struct vpif_subdev_info *subdevdata;
        struct vpif_display_config *config;
-       int i, j = 0, k, q, m, err = 0;
+       int i, j = 0, k, err = 0;
+       int res_idx = 0;
        struct i2c_adapter *i2c_adap;
        struct common_obj *common;
        struct channel_obj *ch;
@@ -1696,21 +1713,22 @@ static __init int vpif_probe(struct platform_device *pdev)
                return err;
        }
 
-       k = 0;
-       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, k))) {
+       while ((res = platform_get_resource(pdev, IORESOURCE_IRQ, res_idx))) {
                for (i = res->start; i <= res->end; i++) {
                        if (request_irq(i, vpif_channel_isr, IRQF_SHARED,
-                                       "VPIF_Display",
-                               (void *)(&vpif_obj.dev[k]->channel_id))) {
+                                       "VPIF_Display", (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id))) {
                                err = -EBUSY;
+                               for (j = 0; j < i; j++)
+                                       free_irq(j, (void *)
+                                       (&vpif_obj.dev[res_idx]->channel_id));
                                goto vpif_int_err;
                        }
                }
-               k++;
+               res_idx++;
        }
 
        for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
-
                /* Get the pointer to the channel object */
                ch = vpif_obj.dev[i];
 
@@ -1729,6 +1747,7 @@ static __init int vpif_probe(struct platform_device *pdev)
                *vfd = vpif_video_template;
                vfd->v4l2_dev = &vpif_obj.v4l2_dev;
                vfd->release = video_device_release;
+               vfd->vfl_dir = VFL_DIR_TX;
                snprintf(vfd->name, sizeof(vfd->name),
                         "VPIF_Display_DRIVER_V%s",
                         VPIF_DISPLAY_VERSION);
@@ -1755,6 +1774,32 @@ static __init int vpif_probe(struct platform_device *pdev)
                }
        }
 
+       i2c_adap = i2c_get_adapter(1);
+       config = pdev->dev.platform_data;
+       subdev_count = config->subdev_count;
+       subdevdata = config->subdevinfo;
+       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
+                                                               GFP_KERNEL);
+       if (vpif_obj.sd == NULL) {
+               vpif_err("unable to allocate memory for subdevice pointers\n");
+               err = -ENOMEM;
+               goto vpif_sd_error;
+       }
+
+       for (i = 0; i < subdev_count; i++) {
+               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
+                                               i2c_adap,
+                                               &subdevdata[i].board_info,
+                                               NULL);
+               if (!vpif_obj.sd[i]) {
+                       vpif_err("Error registering v4l2 subdevice\n");
+                       goto probe_subdev_out;
+               }
+
+               if (vpif_obj.sd[i])
+                       vpif_obj.sd[i]->grp_id = 1 << i;
+       }
+
        for (j = 0; j < VPIF_DISPLAY_MAX_DEVICES; j++) {
                ch = vpif_obj.dev[j];
                /* Initialize field of the channel objects */
@@ -1776,6 +1821,8 @@ static __init int vpif_probe(struct platform_device *pdev)
 
                }
                ch->initialized = 0;
+               if (subdev_count)
+                       ch->sd = vpif_obj.sd[0];
                ch->channel_id = j;
                if (j < 2)
                        ch->common[VPIF_VIDEO_INDEX].numbuffers =
@@ -1789,11 +1836,13 @@ static __init int vpif_probe(struct platform_device *pdev)
                v4l2_prio_init(&ch->prio);
                ch->common[VPIF_VIDEO_INDEX].fmt.type =
                                                V4L2_BUF_TYPE_VIDEO_OUTPUT;
-               /* Locking in file operations other than ioctl should be done
-                  by the driver, not the V4L2 core.
-                  This driver needs auditing so that this flag can be removed. */
-               set_bit(V4L2_FL_LOCK_ALL_FOPS, &ch->video_dev->flags);
                ch->video_dev->lock = &common->lock;
+               video_set_drvdata(ch->video_dev, ch);
+
+               /* select output 0 */
+               err = vpif_set_output(config, ch, 0);
+               if (err)
+                       goto probe_out;
 
                /* register video device */
                vpif_dbg(1, debug, "channel=%x,channel->video_dev=%x\n",
@@ -1803,42 +1852,12 @@ static __init int vpif_probe(struct platform_device *pdev)
                                          VFL_TYPE_GRABBER, (j ? 3 : 2));
                if (err < 0)
                        goto probe_out;
-
-               video_set_drvdata(ch->video_dev, ch);
-       }
-
-       i2c_adap = i2c_get_adapter(1);
-       config = pdev->dev.platform_data;
-       subdev_count = config->subdev_count;
-       subdevdata = config->subdevinfo;
-       vpif_obj.sd = kzalloc(sizeof(struct v4l2_subdev *) * subdev_count,
-                                                               GFP_KERNEL);
-       if (vpif_obj.sd == NULL) {
-               vpif_err("unable to allocate memory for subdevice pointers\n");
-               err = -ENOMEM;
-               goto probe_out;
-       }
-
-       for (i = 0; i < subdev_count; i++) {
-               vpif_obj.sd[i] = v4l2_i2c_new_subdev_board(&vpif_obj.v4l2_dev,
-                                               i2c_adap,
-                                               &subdevdata[i].board_info,
-                                               NULL);
-               if (!vpif_obj.sd[i]) {
-                       vpif_err("Error registering v4l2 subdevice\n");
-                       goto probe_subdev_out;
-               }
-
-               if (vpif_obj.sd[i])
-                       vpif_obj.sd[i]->grp_id = 1 << i;
        }
 
        v4l2_info(&vpif_obj.v4l2_dev,
                        " VPIF display driver initialized\n");
        return 0;
 
-probe_subdev_out:
-       kfree(vpif_obj.sd);
 probe_out:
        for (k = 0; k < j; k++) {
                ch = vpif_obj.dev[k];
@@ -1846,14 +1865,21 @@ probe_out:
                video_device_release(ch->video_dev);
                ch->video_dev = NULL;
        }
+probe_subdev_out:
+       kfree(vpif_obj.sd);
+vpif_sd_error:
+       for (i = 0; i < VPIF_DISPLAY_MAX_DEVICES; i++) {
+               ch = vpif_obj.dev[i];
+               /* Note: does nothing if ch->video_dev == NULL */
+               video_device_release(ch->video_dev);
+       }
 vpif_int_err:
        v4l2_device_unregister(&vpif_obj.v4l2_dev);
        vpif_err("VPIF IRQ request failed\n");
-       for (q = k; k >= 0; k--) {
-               for (m = i; m >= res->start; m--)
-                       free_irq(m, (void *)(&vpif_obj.dev[k]->channel_id));
-               res = platform_get_resource(pdev, IORESOURCE_IRQ, k-1);
-               m = res->end;
+       for (i = 0; i < res_idx; i++) {
+               res = platform_get_resource(pdev, IORESOURCE_IRQ, i);
+               for (j = res->start; j <= res->end; j++)
+                       free_irq(j, (void *)(&vpif_obj.dev[i]->channel_id));
        }
 
        return err;
similarity index 91%
rename from drivers/media/video/davinci/vpif_display.h
rename to drivers/media/platform/davinci/vpif_display.h
index 8967ffb4405846ec6ffa0213eb747a19448af232..a5a18f74395cdfa80a8f5e56d314f949afcb9f84 100644 (file)
@@ -20,7 +20,6 @@
 #include <linux/videodev2.h>
 #include <media/v4l2-common.h>
 #include <media/v4l2-device.h>
-#include <media/videobuf-core.h>
 #include <media/videobuf2-dma-contig.h>
 #include <media/davinci/vpif_types.h>
 
@@ -62,15 +61,7 @@ struct video_obj {
                                         * most recent displayed frame only */
        v4l2_std_id stdid;              /* Currently selected or default
                                         * standard */
-       u32 dv_preset;
-       struct v4l2_bt_timings bt_timings;
-       u32 output_id;                  /* Current output id */
-};
-
-struct vbi_obj {
-       int num_services;
-       struct vpif_vbi_params vbiparams;       /* vpif parameters for the raw
-                                                * vbi data */
+       struct v4l2_dv_timings dv_timings;
 };
 
 struct vpif_disp_buffer {
@@ -133,12 +124,13 @@ struct channel_obj {
                                         * which is being displayed */
        u8 initialized;                 /* flag to indicate whether
                                         * encoder is initialized */
+       u32 output_idx;                 /* Current output index */
+       struct v4l2_subdev *sd;         /* Current output subdev(may be NULL) */
 
        enum vpif_channel_id channel_id;/* Identifies channel */
        struct vpif_params vpifparams;
        struct common_obj common[VPIF_NUMOBJECTS];
        struct video_obj video;
-       struct vbi_obj vbi;
 };
 
 /* File handle structure */
@@ -170,12 +162,4 @@ struct vpif_config_params {
        u8 min_numbuffers;
 };
 
-/* Struct which keeps track of the line numbers for the sliced vbi service */
-struct vpif_service_line {
-       u16 service_id;
-       u16 service_line[2];
-       u16 enc_service_id;
-       u8 bytestowrite;
-};
-
 #endif                         /* DAVINCIHD_DISPLAY_H */
similarity index 99%
rename from drivers/media/video/davinci/vpss.c
rename to drivers/media/platform/davinci/vpss.c
index 3e5cf27ec2b29abe2165e180a6bfddba64833514..146e4b01ac177593b58ad5c7fadc1724d2118973 100644 (file)
@@ -357,7 +357,7 @@ void dm365_vpss_set_pg_frame_size(struct vpss_pg_frame_size frame_size)
 }
 EXPORT_SYMBOL(dm365_vpss_set_pg_frame_size);
 
-static int __init vpss_probe(struct platform_device *pdev)
+static int __devinit vpss_probe(struct platform_device *pdev)
 {
        struct resource         *r1, *r2;
        char *platform_name;
diff --git a/drivers/media/platform/exynos-gsc/Makefile b/drivers/media/platform/exynos-gsc/Makefile
new file mode 100644 (file)
index 0000000..6d1411c
--- /dev/null
@@ -0,0 +1,3 @@
+exynos-gsc-objs := gsc-core.o gsc-m2m.o gsc-regs.o
+
+obj-$(CONFIG_VIDEO_SAMSUNG_EXYNOS_GSC) += exynos-gsc.o
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.c b/drivers/media/platform/exynos-gsc/gsc-core.c
new file mode 100644 (file)
index 0000000..bfec9e6
--- /dev/null
@@ -0,0 +1,1252 @@
+/*
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series G-Scaler driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+#include <linux/of.h>
+#include <media/v4l2-ioctl.h>
+
+#include "gsc-core.h"
+
+#define GSC_CLOCK_GATE_NAME    "gscl"
+
+static const struct gsc_fmt gsc_formats[] = {
+       {
+               .name           = "RGB565",
+               .pixelformat    = V4L2_PIX_FMT_RGB565X,
+               .depth          = { 16 },
+               .color          = GSC_RGB,
+               .num_planes     = 1,
+               .num_comp       = 1,
+       }, {
+               .name           = "XRGB-8-8-8-8, 32 bpp",
+               .pixelformat    = V4L2_PIX_FMT_RGB32,
+               .depth          = { 32 },
+               .color          = GSC_RGB,
+               .num_planes     = 1,
+               .num_comp       = 1,
+       }, {
+               .name           = "YUV 4:2:2 packed, YCbYCr",
+               .pixelformat    = V4L2_PIX_FMT_YUYV,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 1,
+               .mbus_code      = V4L2_MBUS_FMT_YUYV8_2X8,
+       }, {
+               .name           = "YUV 4:2:2 packed, CbYCrY",
+               .pixelformat    = V4L2_PIX_FMT_UYVY,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_C,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 1,
+               .mbus_code      = V4L2_MBUS_FMT_UYVY8_2X8,
+       }, {
+               .name           = "YUV 4:2:2 packed, CrYCbY",
+               .pixelformat    = V4L2_PIX_FMT_VYUY,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_C,
+               .corder         = GSC_CRCB,
+               .num_planes     = 1,
+               .num_comp       = 1,
+               .mbus_code      = V4L2_MBUS_FMT_VYUY8_2X8,
+       }, {
+               .name           = "YUV 4:2:2 packed, YCrYCb",
+               .pixelformat    = V4L2_PIX_FMT_YVYU,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CRCB,
+               .num_planes     = 1,
+               .num_comp       = 1,
+               .mbus_code      = V4L2_MBUS_FMT_YVYU8_2X8,
+       }, {
+               .name           = "YUV 4:4:4 planar, YCbYCr",
+               .pixelformat    = V4L2_PIX_FMT_YUV32,
+               .depth          = { 32 },
+               .color          = GSC_YUV444,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 1,
+       }, {
+               .name           = "YUV 4:2:2 planar, Y/Cb/Cr",
+               .pixelformat    = V4L2_PIX_FMT_YUV422P,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 3,
+       }, {
+               .name           = "YUV 4:2:2 planar, Y/CbCr",
+               .pixelformat    = V4L2_PIX_FMT_NV16,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 2,
+       }, {
+               .name           = "YUV 4:2:2 planar, Y/CrCb",
+               .pixelformat    = V4L2_PIX_FMT_NV61,
+               .depth          = { 16 },
+               .color          = GSC_YUV422,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CRCB,
+               .num_planes     = 1,
+               .num_comp       = 2,
+       }, {
+               .name           = "YUV 4:2:0 planar, YCbCr",
+               .pixelformat    = V4L2_PIX_FMT_YUV420,
+               .depth          = { 12 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 3,
+       }, {
+               .name           = "YUV 4:2:0 planar, YCrCb",
+               .pixelformat    = V4L2_PIX_FMT_YVU420,
+               .depth          = { 12 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CRCB,
+               .num_planes     = 1,
+               .num_comp       = 3,
+
+       }, {
+               .name           = "YUV 4:2:0 planar, Y/CbCr",
+               .pixelformat    = V4L2_PIX_FMT_NV12,
+               .depth          = { 12 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 1,
+               .num_comp       = 2,
+       }, {
+               .name           = "YUV 4:2:0 planar, Y/CrCb",
+               .pixelformat    = V4L2_PIX_FMT_NV21,
+               .depth          = { 12 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CRCB,
+               .num_planes     = 1,
+               .num_comp       = 2,
+       }, {
+               .name           = "YUV 4:2:0 non-contig. 2p, Y/CbCr",
+               .pixelformat    = V4L2_PIX_FMT_NV12M,
+               .depth          = { 8, 4 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 2,
+               .num_comp       = 2,
+       }, {
+               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cb/Cr",
+               .pixelformat    = V4L2_PIX_FMT_YUV420M,
+               .depth          = { 8, 2, 2 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CBCR,
+               .num_planes     = 3,
+               .num_comp       = 3,
+       }, {
+               .name           = "YUV 4:2:0 non-contig. 3p, Y/Cr/Cb",
+               .pixelformat    = V4L2_PIX_FMT_YVU420M,
+               .depth          = { 8, 2, 2 },
+               .color          = GSC_YUV420,
+               .yorder         = GSC_LSB_Y,
+               .corder         = GSC_CRCB,
+               .num_planes     = 3,
+               .num_comp       = 3,
+       }
+};
+
+const struct gsc_fmt *get_format(int index)
+{
+       if (index >= ARRAY_SIZE(gsc_formats))
+               return NULL;
+
+       return (struct gsc_fmt *)&gsc_formats[index];
+}
+
+const struct gsc_fmt *find_fmt(u32 *pixelformat, u32 *mbus_code, u32 index)
+{
+       const struct gsc_fmt *fmt, *def_fmt = NULL;
+       unsigned int i;
+
+       if (index >= ARRAY_SIZE(gsc_formats))
+               return NULL;
+
+       for (i = 0; i < ARRAY_SIZE(gsc_formats); ++i) {
+               fmt = get_format(i);
+               if (pixelformat && fmt->pixelformat == *pixelformat)
+                       return fmt;
+               if (mbus_code && fmt->mbus_code == *mbus_code)
+                       return fmt;
+               if (index == i)
+                       def_fmt = fmt;
+       }
+       return def_fmt;
+
+}
+
+void gsc_set_frame_size(struct gsc_frame *frame, int width, int height)
+{
+       frame->f_width  = width;
+       frame->f_height = height;
+       frame->crop.width = width;
+       frame->crop.height = height;
+       frame->crop.left = 0;
+       frame->crop.top = 0;
+}
+
+int gsc_cal_prescaler_ratio(struct gsc_variant *var, u32 src, u32 dst,
+                                                               u32 *ratio)
+{
+       if ((dst > src) || (dst >= src / var->poly_sc_down_max)) {
+               *ratio = 1;
+               return 0;
+       }
+
+       if ((src / var->poly_sc_down_max / var->pre_sc_down_max) > dst) {
+               pr_err("Exceeded maximum downscaling ratio (1/16))");
+               return -EINVAL;
+       }
+
+       *ratio = (dst > (src / 8)) ? 2 : 4;
+
+       return 0;
+}
+
+void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *sh)
+{
+       if (hratio == 4 && vratio == 4)
+               *sh = 4;
+       else if ((hratio == 4 && vratio == 2) ||
+                (hratio == 2 && vratio == 4))
+               *sh = 3;
+       else if ((hratio == 4 && vratio == 1) ||
+                (hratio == 1 && vratio == 4) ||
+                (hratio == 2 && vratio == 2))
+               *sh = 2;
+       else if (hratio == 1 && vratio == 1)
+               *sh = 0;
+       else
+               *sh = 1;
+}
+
+void gsc_check_src_scale_info(struct gsc_variant *var,
+                               struct gsc_frame *s_frame, u32 *wratio,
+                                u32 tx, u32 ty, u32 *hratio)
+{
+       int remainder = 0, walign, halign;
+
+       if (is_yuv420(s_frame->fmt->color)) {
+               walign = GSC_SC_ALIGN_4;
+               halign = GSC_SC_ALIGN_4;
+       } else if (is_yuv422(s_frame->fmt->color)) {
+               walign = GSC_SC_ALIGN_4;
+               halign = GSC_SC_ALIGN_2;
+       } else {
+               walign = GSC_SC_ALIGN_2;
+               halign = GSC_SC_ALIGN_2;
+       }
+
+       remainder = s_frame->crop.width % (*wratio * walign);
+       if (remainder) {
+               s_frame->crop.width -= remainder;
+               gsc_cal_prescaler_ratio(var, s_frame->crop.width, tx, wratio);
+               pr_info("cropped src width size is recalculated from %d to %d",
+                       s_frame->crop.width + remainder, s_frame->crop.width);
+       }
+
+       remainder = s_frame->crop.height % (*hratio * halign);
+       if (remainder) {
+               s_frame->crop.height -= remainder;
+               gsc_cal_prescaler_ratio(var, s_frame->crop.height, ty, hratio);
+               pr_info("cropped src height size is recalculated from %d to %d",
+                       s_frame->crop.height + remainder, s_frame->crop.height);
+       }
+}
+
+int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f)
+{
+       const struct gsc_fmt *fmt;
+
+       fmt = find_fmt(NULL, NULL, f->index);
+       if (!fmt)
+               return -EINVAL;
+
+       strlcpy(f->description, fmt->name, sizeof(f->description));
+       f->pixelformat = fmt->pixelformat;
+
+       return 0;
+}
+
+static u32 get_plane_info(struct gsc_frame *frm, u32 addr, u32 *index)
+{
+       if (frm->addr.y == addr) {
+               *index = 0;
+               return frm->addr.y;
+       } else if (frm->addr.cb == addr) {
+               *index = 1;
+               return frm->addr.cb;
+       } else if (frm->addr.cr == addr) {
+               *index = 2;
+               return frm->addr.cr;
+       } else {
+               pr_err("Plane address is wrong");
+               return -EINVAL;
+       }
+}
+
+void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm)
+{
+       u32 f_chk_addr, f_chk_len, s_chk_addr, s_chk_len;
+       f_chk_addr = f_chk_len = s_chk_addr = s_chk_len = 0;
+
+       f_chk_addr = frm->addr.y;
+       f_chk_len = frm->payload[0];
+       if (frm->fmt->num_planes == 2) {
+               s_chk_addr = frm->addr.cb;
+               s_chk_len = frm->payload[1];
+       } else if (frm->fmt->num_planes == 3) {
+               u32 low_addr, low_plane, mid_addr, mid_plane;
+               u32 high_addr, high_plane;
+               u32 t_min, t_max;
+
+               t_min = min3(frm->addr.y, frm->addr.cb, frm->addr.cr);
+               low_addr = get_plane_info(frm, t_min, &low_plane);
+               t_max = max3(frm->addr.y, frm->addr.cb, frm->addr.cr);
+               high_addr = get_plane_info(frm, t_max, &high_plane);
+
+               mid_plane = 3 - (low_plane + high_plane);
+               if (mid_plane == 0)
+                       mid_addr = frm->addr.y;
+               else if (mid_plane == 1)
+                       mid_addr = frm->addr.cb;
+               else if (mid_plane == 2)
+                       mid_addr = frm->addr.cr;
+               else
+                       return;
+
+               f_chk_addr = low_addr;
+               if (mid_addr + frm->payload[mid_plane] - low_addr >
+                   high_addr + frm->payload[high_plane] - mid_addr) {
+                       f_chk_len = frm->payload[low_plane];
+                       s_chk_addr = mid_addr;
+                       s_chk_len = high_addr +
+                                       frm->payload[high_plane] - mid_addr;
+               } else {
+                       f_chk_len = mid_addr +
+                                       frm->payload[mid_plane] - low_addr;
+                       s_chk_addr = high_addr;
+                       s_chk_len = frm->payload[high_plane];
+               }
+       }
+       pr_debug("f_addr = 0x%08x, f_len = %d, s_addr = 0x%08x, s_len = %d\n",
+                       f_chk_addr, f_chk_len, s_chk_addr, s_chk_len);
+}
+
+int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
+{
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       struct gsc_variant *variant = gsc->variant;
+       struct v4l2_pix_format_mplane *pix_mp = &f->fmt.pix_mp;
+       const struct gsc_fmt *fmt;
+       u32 max_w, max_h, mod_x, mod_y;
+       u32 min_w, min_h, tmp_w, tmp_h;
+       int i;
+
+       pr_debug("user put w: %d, h: %d", pix_mp->width, pix_mp->height);
+
+       fmt = find_fmt(&pix_mp->pixelformat, NULL, 0);
+       if (!fmt) {
+               pr_err("pixelformat format (0x%X) invalid\n",
+                                               pix_mp->pixelformat);
+               return -EINVAL;
+       }
+
+       if (pix_mp->field == V4L2_FIELD_ANY)
+               pix_mp->field = V4L2_FIELD_NONE;
+       else if (pix_mp->field != V4L2_FIELD_NONE) {
+               pr_err("Not supported field order(%d)\n", pix_mp->field);
+               return -EINVAL;
+       }
+
+       max_w = variant->pix_max->target_rot_dis_w;
+       max_h = variant->pix_max->target_rot_dis_h;
+
+       mod_x = ffs(variant->pix_align->org_w) - 1;
+       if (is_yuv420(fmt->color))
+               mod_y = ffs(variant->pix_align->org_h) - 1;
+       else
+               mod_y = ffs(variant->pix_align->org_h) - 2;
+
+       if (V4L2_TYPE_IS_OUTPUT(f->type)) {
+               min_w = variant->pix_min->org_w;
+               min_h = variant->pix_min->org_h;
+       } else {
+               min_w = variant->pix_min->target_rot_dis_w;
+               min_h = variant->pix_min->target_rot_dis_h;
+       }
+
+       pr_debug("mod_x: %d, mod_y: %d, max_w: %d, max_h = %d",
+                       mod_x, mod_y, max_w, max_h);
+
+       /* To check if image size is modified to adjust parameter against
+          hardware abilities */
+       tmp_w = pix_mp->width;
+       tmp_h = pix_mp->height;
+
+       v4l_bound_align_image(&pix_mp->width, min_w, max_w, mod_x,
+               &pix_mp->height, min_h, max_h, mod_y, 0);
+       if (tmp_w != pix_mp->width || tmp_h != pix_mp->height)
+               pr_info("Image size has been modified from %dx%d to %dx%d",
+                        tmp_w, tmp_h, pix_mp->width, pix_mp->height);
+
+       pix_mp->num_planes = fmt->num_planes;
+
+       if (pix_mp->width >= 1280) /* HD */
+               pix_mp->colorspace = V4L2_COLORSPACE_REC709;
+       else /* SD */
+               pix_mp->colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+
+       for (i = 0; i < pix_mp->num_planes; ++i) {
+               int bpl = (pix_mp->width * fmt->depth[i]) >> 3;
+               pix_mp->plane_fmt[i].bytesperline = bpl;
+               pix_mp->plane_fmt[i].sizeimage = bpl * pix_mp->height;
+
+               pr_debug("[%d]: bpl: %d, sizeimage: %d",
+                               i, bpl, pix_mp->plane_fmt[i].sizeimage);
+       }
+
+       return 0;
+}
+
+int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f)
+{
+       struct gsc_frame *frame;
+       struct v4l2_pix_format_mplane *pix_mp;
+       int i;
+
+       frame = ctx_get_frame(ctx, f->type);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
+
+       pix_mp = &f->fmt.pix_mp;
+
+       pix_mp->width           = frame->f_width;
+       pix_mp->height          = frame->f_height;
+       pix_mp->field           = V4L2_FIELD_NONE;
+       pix_mp->pixelformat     = frame->fmt->pixelformat;
+       pix_mp->colorspace      = V4L2_COLORSPACE_REC709;
+       pix_mp->num_planes      = frame->fmt->num_planes;
+
+       for (i = 0; i < pix_mp->num_planes; ++i) {
+               pix_mp->plane_fmt[i].bytesperline = (frame->f_width *
+                       frame->fmt->depth[i]) / 8;
+               pix_mp->plane_fmt[i].sizeimage =
+                        pix_mp->plane_fmt[i].bytesperline * frame->f_height;
+       }
+
+       return 0;
+}
+
+void gsc_check_crop_change(u32 tmp_w, u32 tmp_h, u32 *w, u32 *h)
+{
+       if (tmp_w != *w || tmp_h != *h) {
+               pr_info("Cropped size has been modified from %dx%d to %dx%d",
+                                                       *w, *h, tmp_w, tmp_h);
+               *w = tmp_w;
+               *h = tmp_h;
+       }
+}
+
+int gsc_g_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr)
+{
+       struct gsc_frame *frame;
+
+       frame = ctx_get_frame(ctx, cr->type);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
+
+       cr->c = frame->crop;
+
+       return 0;
+}
+
+int gsc_try_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr)
+{
+       struct gsc_frame *f;
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       struct gsc_variant *variant = gsc->variant;
+       u32 mod_x = 0, mod_y = 0, tmp_w, tmp_h;
+       u32 min_w, min_h, max_w, max_h;
+
+       if (cr->c.top < 0 || cr->c.left < 0) {
+               pr_err("doesn't support negative values for top & left\n");
+               return -EINVAL;
+       }
+       pr_debug("user put w: %d, h: %d", cr->c.width, cr->c.height);
+
+       if (cr->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               f = &ctx->d_frame;
+       else if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+               f = &ctx->s_frame;
+       else
+               return -EINVAL;
+
+       max_w = f->f_width;
+       max_h = f->f_height;
+       tmp_w = cr->c.width;
+       tmp_h = cr->c.height;
+
+       if (V4L2_TYPE_IS_OUTPUT(cr->type)) {
+               if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 1) ||
+                   is_rgb(f->fmt->color))
+                       min_w = 32;
+               else
+                       min_w = 64;
+               if ((is_yuv422(f->fmt->color) && f->fmt->num_comp == 3) ||
+                   is_yuv420(f->fmt->color))
+                       min_h = 32;
+               else
+                       min_h = 16;
+       } else {
+               if (is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color))
+                       mod_x = ffs(variant->pix_align->target_w) - 1;
+               if (is_yuv420(f->fmt->color))
+                       mod_y = ffs(variant->pix_align->target_h) - 1;
+               if (ctx->gsc_ctrls.rotate->val == 90 ||
+                   ctx->gsc_ctrls.rotate->val == 270) {
+                       max_w = f->f_height;
+                       max_h = f->f_width;
+                       min_w = variant->pix_min->target_rot_en_w;
+                       min_h = variant->pix_min->target_rot_en_h;
+                       tmp_w = cr->c.height;
+                       tmp_h = cr->c.width;
+               } else {
+                       min_w = variant->pix_min->target_rot_dis_w;
+                       min_h = variant->pix_min->target_rot_dis_h;
+               }
+       }
+       pr_debug("mod_x: %d, mod_y: %d, min_w: %d, min_h = %d",
+                                       mod_x, mod_y, min_w, min_h);
+       pr_debug("tmp_w : %d, tmp_h : %d", tmp_w, tmp_h);
+
+       v4l_bound_align_image(&tmp_w, min_w, max_w, mod_x,
+                             &tmp_h, min_h, max_h, mod_y, 0);
+
+       if (!V4L2_TYPE_IS_OUTPUT(cr->type) &&
+               (ctx->gsc_ctrls.rotate->val == 90 ||
+               ctx->gsc_ctrls.rotate->val == 270))
+               gsc_check_crop_change(tmp_h, tmp_w,
+                                       &cr->c.width, &cr->c.height);
+       else
+               gsc_check_crop_change(tmp_w, tmp_h,
+                                       &cr->c.width, &cr->c.height);
+
+
+       /* adjust left/top if cropping rectangle is out of bounds */
+       /* Need to add code to algin left value with 2's multiple */
+       if (cr->c.left + tmp_w > max_w)
+               cr->c.left = max_w - tmp_w;
+       if (cr->c.top + tmp_h > max_h)
+               cr->c.top = max_h - tmp_h;
+
+       if ((is_yuv420(f->fmt->color) || is_yuv422(f->fmt->color)) &&
+               cr->c.left & 1)
+                       cr->c.left -= 1;
+
+       pr_debug("Aligned l:%d, t:%d, w:%d, h:%d, f_w: %d, f_h: %d",
+           cr->c.left, cr->c.top, cr->c.width, cr->c.height, max_w, max_h);
+
+       return 0;
+}
+
+int gsc_check_scaler_ratio(struct gsc_variant *var, int sw, int sh, int dw,
+                          int dh, int rot, int out_path)
+{
+       int tmp_w, tmp_h, sc_down_max;
+
+       if (out_path == GSC_DMA)
+               sc_down_max = var->sc_down_max;
+       else
+               sc_down_max = var->local_sc_down;
+
+       if (rot == 90 || rot == 270) {
+               tmp_w = dh;
+               tmp_h = dw;
+       } else {
+               tmp_w = dw;
+               tmp_h = dh;
+       }
+
+       if ((sw / tmp_w) > sc_down_max ||
+           (sh / tmp_h) > sc_down_max ||
+           (tmp_w / sw) > var->sc_up_max ||
+           (tmp_h / sh) > var->sc_up_max)
+               return -EINVAL;
+
+       return 0;
+}
+
+int gsc_set_scaler_info(struct gsc_ctx *ctx)
+{
+       struct gsc_scaler *sc = &ctx->scaler;
+       struct gsc_frame *s_frame = &ctx->s_frame;
+       struct gsc_frame *d_frame = &ctx->d_frame;
+       struct gsc_variant *variant = ctx->gsc_dev->variant;
+       struct device *dev = &ctx->gsc_dev->pdev->dev;
+       int tx, ty;
+       int ret;
+
+       ret = gsc_check_scaler_ratio(variant, s_frame->crop.width,
+               s_frame->crop.height, d_frame->crop.width, d_frame->crop.height,
+               ctx->gsc_ctrls.rotate->val, ctx->out_path);
+       if (ret) {
+               pr_err("out of scaler range");
+               return ret;
+       }
+
+       if (ctx->gsc_ctrls.rotate->val == 90 ||
+           ctx->gsc_ctrls.rotate->val == 270) {
+               ty = d_frame->crop.width;
+               tx = d_frame->crop.height;
+       } else {
+               tx = d_frame->crop.width;
+               ty = d_frame->crop.height;
+       }
+
+       if (tx <= 0 || ty <= 0) {
+               dev_err(dev, "Invalid target size: %dx%d", tx, ty);
+               return -EINVAL;
+       }
+
+       ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.width,
+                                     tx, &sc->pre_hratio);
+       if (ret) {
+               pr_err("Horizontal scale ratio is out of range");
+               return ret;
+       }
+
+       ret = gsc_cal_prescaler_ratio(variant, s_frame->crop.height,
+                                     ty, &sc->pre_vratio);
+       if (ret) {
+               pr_err("Vertical scale ratio is out of range");
+               return ret;
+       }
+
+       gsc_check_src_scale_info(variant, s_frame, &sc->pre_hratio,
+                                tx, ty, &sc->pre_vratio);
+
+       gsc_get_prescaler_shfactor(sc->pre_hratio, sc->pre_vratio,
+                                  &sc->pre_shfactor);
+
+       sc->main_hratio = (s_frame->crop.width << 16) / tx;
+       sc->main_vratio = (s_frame->crop.height << 16) / ty;
+
+       pr_debug("scaler input/output size : sx = %d, sy = %d, tx = %d, ty = %d",
+                       s_frame->crop.width, s_frame->crop.height, tx, ty);
+       pr_debug("scaler ratio info : pre_shfactor : %d, pre_h : %d",
+                       sc->pre_shfactor, sc->pre_hratio);
+       pr_debug("pre_v :%d, main_h : %d, main_v : %d",
+                       sc->pre_vratio, sc->main_hratio, sc->main_vratio);
+
+       return 0;
+}
+
+static int __gsc_s_ctrl(struct gsc_ctx *ctx, struct v4l2_ctrl *ctrl)
+{
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       struct gsc_variant *variant = gsc->variant;
+       unsigned int flags = GSC_DST_FMT | GSC_SRC_FMT;
+       int ret = 0;
+
+       if (ctrl->flags & V4L2_CTRL_FLAG_INACTIVE)
+               return 0;
+
+       switch (ctrl->id) {
+       case V4L2_CID_HFLIP:
+               ctx->hflip = ctrl->val;
+               break;
+
+       case V4L2_CID_VFLIP:
+               ctx->vflip = ctrl->val;
+               break;
+
+       case V4L2_CID_ROTATE:
+               if ((ctx->state & flags) == flags) {
+                       ret = gsc_check_scaler_ratio(variant,
+                                       ctx->s_frame.crop.width,
+                                       ctx->s_frame.crop.height,
+                                       ctx->d_frame.crop.width,
+                                       ctx->d_frame.crop.height,
+                                       ctx->gsc_ctrls.rotate->val,
+                                       ctx->out_path);
+
+                       if (ret)
+                               return -EINVAL;
+               }
+
+               ctx->rotation = ctrl->val;
+               break;
+
+       case V4L2_CID_ALPHA_COMPONENT:
+               ctx->d_frame.alpha = ctrl->val;
+               break;
+       }
+
+       ctx->state |= GSC_PARAMS;
+       return 0;
+}
+
+static int gsc_s_ctrl(struct v4l2_ctrl *ctrl)
+{
+       struct gsc_ctx *ctx = ctrl_to_ctx(ctrl);
+       unsigned long flags;
+       int ret;
+
+       spin_lock_irqsave(&ctx->gsc_dev->slock, flags);
+       ret = __gsc_s_ctrl(ctx, ctrl);
+       spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags);
+
+       return ret;
+}
+
+static const struct v4l2_ctrl_ops gsc_ctrl_ops = {
+       .s_ctrl = gsc_s_ctrl,
+};
+
+int gsc_ctrls_create(struct gsc_ctx *ctx)
+{
+       if (ctx->ctrls_rdy) {
+               pr_err("Control handler of this context was created already");
+               return 0;
+       }
+
+       v4l2_ctrl_handler_init(&ctx->ctrl_handler, GSC_MAX_CTRL_NUM);
+
+       ctx->gsc_ctrls.rotate = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                               &gsc_ctrl_ops, V4L2_CID_ROTATE, 0, 270, 90, 0);
+       ctx->gsc_ctrls.hflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                               &gsc_ctrl_ops, V4L2_CID_HFLIP, 0, 1, 1, 0);
+       ctx->gsc_ctrls.vflip = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                               &gsc_ctrl_ops, V4L2_CID_VFLIP, 0, 1, 1, 0);
+       ctx->gsc_ctrls.global_alpha = v4l2_ctrl_new_std(&ctx->ctrl_handler,
+                       &gsc_ctrl_ops, V4L2_CID_ALPHA_COMPONENT, 0, 255, 1, 0);
+
+       ctx->ctrls_rdy = ctx->ctrl_handler.error == 0;
+
+       if (ctx->ctrl_handler.error) {
+               int err = ctx->ctrl_handler.error;
+               v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+               pr_err("Failed to create G-Scaler control handlers");
+               return err;
+       }
+
+       return 0;
+}
+
+void gsc_ctrls_delete(struct gsc_ctx *ctx)
+{
+       if (ctx->ctrls_rdy) {
+               v4l2_ctrl_handler_free(&ctx->ctrl_handler);
+               ctx->ctrls_rdy = false;
+       }
+}
+
+/* The color format (num_comp, num_planes) must be already configured. */
+int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
+                       struct gsc_frame *frame, struct gsc_addr *addr)
+{
+       int ret = 0;
+       u32 pix_size;
+
+       if ((vb == NULL) || (frame == NULL))
+               return -EINVAL;
+
+       pix_size = frame->f_width * frame->f_height;
+
+       pr_debug("num_planes= %d, num_comp= %d, pix_size= %d",
+               frame->fmt->num_planes, frame->fmt->num_comp, pix_size);
+
+       addr->y = vb2_dma_contig_plane_dma_addr(vb, 0);
+
+       if (frame->fmt->num_planes == 1) {
+               switch (frame->fmt->num_comp) {
+               case 1:
+                       addr->cb = 0;
+                       addr->cr = 0;
+                       break;
+               case 2:
+                       /* decompose Y into Y/Cb */
+                       addr->cb = (dma_addr_t)(addr->y + pix_size);
+                       addr->cr = 0;
+                       break;
+               case 3:
+                       /* decompose Y into Y/Cb/Cr */
+                       addr->cb = (dma_addr_t)(addr->y + pix_size);
+                       if (GSC_YUV420 == frame->fmt->color)
+                               addr->cr = (dma_addr_t)(addr->cb
+                                               + (pix_size >> 2));
+                       else /* 422 */
+                               addr->cr = (dma_addr_t)(addr->cb
+                                               + (pix_size >> 1));
+                       break;
+               default:
+                       pr_err("Invalid the number of color planes");
+                       return -EINVAL;
+               }
+       } else {
+               if (frame->fmt->num_planes >= 2)
+                       addr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
+
+               if (frame->fmt->num_planes == 3)
+                       addr->cr = vb2_dma_contig_plane_dma_addr(vb, 2);
+       }
+
+       if ((frame->fmt->pixelformat == V4L2_PIX_FMT_VYUY) ||
+               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVYU) ||
+               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV61) ||
+               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420) ||
+               (frame->fmt->pixelformat == V4L2_PIX_FMT_NV21) ||
+               (frame->fmt->pixelformat == V4L2_PIX_FMT_YVU420M))
+               swap(addr->cb, addr->cr);
+
+       pr_debug("ADDR: y= 0x%X  cb= 0x%X cr= 0x%X ret= %d",
+               addr->y, addr->cb, addr->cr, ret);
+
+       return ret;
+}
+
+static irqreturn_t gsc_irq_handler(int irq, void *priv)
+{
+       struct gsc_dev *gsc = priv;
+       struct gsc_ctx *ctx;
+       int gsc_irq;
+
+       gsc_irq = gsc_hw_get_irq_status(gsc);
+       gsc_hw_clear_irq(gsc, gsc_irq);
+
+       if (gsc_irq == GSC_IRQ_OVERRUN) {
+               pr_err("Local path input over-run interrupt has occurred!\n");
+               return IRQ_HANDLED;
+       }
+
+       spin_lock(&gsc->slock);
+
+       if (test_and_clear_bit(ST_M2M_PEND, &gsc->state)) {
+
+               gsc_hw_enable_control(gsc, false);
+
+               if (test_and_clear_bit(ST_M2M_SUSPENDING, &gsc->state)) {
+                       set_bit(ST_M2M_SUSPENDED, &gsc->state);
+                       wake_up(&gsc->irq_queue);
+                       goto isr_unlock;
+               }
+               ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev);
+
+               if (!ctx || !ctx->m2m_ctx)
+                       goto isr_unlock;
+
+               spin_unlock(&gsc->slock);
+               gsc_m2m_job_finish(ctx, VB2_BUF_STATE_DONE);
+
+               /* wake_up job_abort, stop_streaming */
+               if (ctx->state & GSC_CTX_STOP_REQ) {
+                       ctx->state &= ~GSC_CTX_STOP_REQ;
+                       wake_up(&gsc->irq_queue);
+               }
+               return IRQ_HANDLED;
+       }
+
+isr_unlock:
+       spin_unlock(&gsc->slock);
+       return IRQ_HANDLED;
+}
+
+static struct gsc_pix_max gsc_v_100_max = {
+       .org_scaler_bypass_w    = 8192,
+       .org_scaler_bypass_h    = 8192,
+       .org_scaler_input_w     = 4800,
+       .org_scaler_input_h     = 3344,
+       .real_rot_dis_w         = 4800,
+       .real_rot_dis_h         = 3344,
+       .real_rot_en_w          = 2047,
+       .real_rot_en_h          = 2047,
+       .target_rot_dis_w       = 4800,
+       .target_rot_dis_h       = 3344,
+       .target_rot_en_w        = 2016,
+       .target_rot_en_h        = 2016,
+};
+
+static struct gsc_pix_min gsc_v_100_min = {
+       .org_w                  = 64,
+       .org_h                  = 32,
+       .real_w                 = 64,
+       .real_h                 = 32,
+       .target_rot_dis_w       = 64,
+       .target_rot_dis_h       = 32,
+       .target_rot_en_w        = 32,
+       .target_rot_en_h        = 16,
+};
+
+static struct gsc_pix_align gsc_v_100_align = {
+       .org_h                  = 16,
+       .org_w                  = 16, /* yuv420 : 16, others : 8 */
+       .offset_h               = 2,  /* yuv420/422 : 2, others : 1 */
+       .real_w                 = 16, /* yuv420/422 : 4~16, others : 2~8 */
+       .real_h                 = 16, /* yuv420 : 4~16, others : 1 */
+       .target_w               = 2,  /* yuv420/422 : 2, others : 1 */
+       .target_h               = 2,  /* yuv420 : 2, others : 1 */
+};
+
+static struct gsc_variant gsc_v_100_variant = {
+       .pix_max                = &gsc_v_100_max,
+       .pix_min                = &gsc_v_100_min,
+       .pix_align              = &gsc_v_100_align,
+       .in_buf_cnt             = 8,
+       .out_buf_cnt            = 16,
+       .sc_up_max              = 8,
+       .sc_down_max            = 16,
+       .poly_sc_down_max       = 4,
+       .pre_sc_down_max        = 4,
+       .local_sc_down          = 2,
+};
+
+static struct gsc_driverdata gsc_v_100_drvdata = {
+       .variant = {
+               [0] = &gsc_v_100_variant,
+               [1] = &gsc_v_100_variant,
+               [2] = &gsc_v_100_variant,
+               [3] = &gsc_v_100_variant,
+       },
+       .num_entities = 4,
+       .lclk_frequency = 266000000UL,
+};
+
+static struct platform_device_id gsc_driver_ids[] = {
+       {
+               .name           = "exynos-gsc",
+               .driver_data    = (unsigned long)&gsc_v_100_drvdata,
+       },
+       {},
+};
+MODULE_DEVICE_TABLE(platform, gsc_driver_ids);
+
+static const struct of_device_id exynos_gsc_match[] = {
+       { .compatible = "samsung,exynos5250-gsc",
+       .data = &gsc_v_100_drvdata, },
+       {},
+};
+MODULE_DEVICE_TABLE(of, exynos_gsc_match);
+
+static void *gsc_get_drv_data(struct platform_device *pdev)
+{
+       struct gsc_driverdata *driver_data = NULL;
+
+       if (pdev->dev.of_node) {
+               const struct of_device_id *match;
+               match = of_match_node(of_match_ptr(exynos_gsc_match),
+                                       pdev->dev.of_node);
+               if (match)
+                       driver_data =  match->data;
+       } else {
+               driver_data = (struct gsc_driverdata *)
+                       platform_get_device_id(pdev)->driver_data;
+       }
+
+       return driver_data;
+}
+
+static void gsc_clk_put(struct gsc_dev *gsc)
+{
+       if (IS_ERR_OR_NULL(gsc->clock))
+               return;
+
+       clk_unprepare(gsc->clock);
+       clk_put(gsc->clock);
+       gsc->clock = NULL;
+}
+
+static int gsc_clk_get(struct gsc_dev *gsc)
+{
+       int ret;
+
+       dev_dbg(&gsc->pdev->dev, "gsc_clk_get Called\n");
+
+       gsc->clock = clk_get(&gsc->pdev->dev, GSC_CLOCK_GATE_NAME);
+       if (IS_ERR(gsc->clock))
+               goto err_print;
+
+       ret = clk_prepare(gsc->clock);
+       if (ret < 0) {
+               clk_put(gsc->clock);
+               gsc->clock = NULL;
+               goto err;
+       }
+
+       return 0;
+
+err:
+       dev_err(&gsc->pdev->dev, "clock prepare failed for clock: %s\n",
+                                       GSC_CLOCK_GATE_NAME);
+       gsc_clk_put(gsc);
+err_print:
+       dev_err(&gsc->pdev->dev, "failed to get clock~~~: %s\n",
+                                       GSC_CLOCK_GATE_NAME);
+       return -ENXIO;
+}
+
+static int gsc_m2m_suspend(struct gsc_dev *gsc)
+{
+       unsigned long flags;
+       int timeout;
+
+       spin_lock_irqsave(&gsc->slock, flags);
+       if (!gsc_m2m_pending(gsc)) {
+               spin_unlock_irqrestore(&gsc->slock, flags);
+               return 0;
+       }
+       clear_bit(ST_M2M_SUSPENDED, &gsc->state);
+       set_bit(ST_M2M_SUSPENDING, &gsc->state);
+       spin_unlock_irqrestore(&gsc->slock, flags);
+
+       timeout = wait_event_timeout(gsc->irq_queue,
+                            test_bit(ST_M2M_SUSPENDED, &gsc->state),
+                            GSC_SHUTDOWN_TIMEOUT);
+
+       clear_bit(ST_M2M_SUSPENDING, &gsc->state);
+       return timeout == 0 ? -EAGAIN : 0;
+}
+
+static int gsc_m2m_resume(struct gsc_dev *gsc)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&gsc->slock, flags);
+       /* Clear for full H/W setup in first run after resume */
+       gsc->m2m.ctx = NULL;
+       spin_unlock_irqrestore(&gsc->slock, flags);
+
+       if (test_and_clear_bit(ST_M2M_SUSPENDED, &gsc->state))
+               gsc_m2m_job_finish(gsc->m2m.ctx,
+                                   VB2_BUF_STATE_ERROR);
+       return 0;
+}
+
+static int gsc_probe(struct platform_device *pdev)
+{
+       struct gsc_dev *gsc;
+       struct resource *res;
+       struct gsc_driverdata *drv_data = gsc_get_drv_data(pdev);
+       struct device *dev = &pdev->dev;
+       int ret = 0;
+
+       gsc = devm_kzalloc(dev, sizeof(struct gsc_dev), GFP_KERNEL);
+       if (!gsc)
+               return -ENOMEM;
+
+       if (dev->of_node)
+               gsc->id = of_alias_get_id(pdev->dev.of_node, "gsc");
+       else
+               gsc->id = pdev->id;
+
+       if (gsc->id < 0 || gsc->id >= drv_data->num_entities) {
+               dev_err(dev, "Invalid platform device id: %d\n", gsc->id);
+               return -EINVAL;
+       }
+
+       gsc->variant = drv_data->variant[gsc->id];
+       gsc->pdev = pdev;
+       gsc->pdata = dev->platform_data;
+
+       init_waitqueue_head(&gsc->irq_queue);
+       spin_lock_init(&gsc->slock);
+       mutex_init(&gsc->lock);
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       gsc->regs = devm_request_and_ioremap(dev, res);
+       if (!gsc->regs) {
+               dev_err(dev, "failed to map registers\n");
+               return -ENOENT;
+       }
+
+       res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+       if (!res) {
+               dev_err(dev, "failed to get IRQ resource\n");
+               return -ENXIO;
+       }
+
+       ret = gsc_clk_get(gsc);
+       if (ret)
+               return ret;
+
+       ret = devm_request_irq(dev, res->start, gsc_irq_handler,
+                               0, pdev->name, gsc);
+       if (ret) {
+               dev_err(dev, "failed to install irq (%d)\n", ret);
+               goto err_clk;
+       }
+
+       ret = gsc_register_m2m_device(gsc);
+       if (ret)
+               goto err_clk;
+
+       platform_set_drvdata(pdev, gsc);
+       pm_runtime_enable(dev);
+       ret = pm_runtime_get_sync(&pdev->dev);
+       if (ret < 0)
+               goto err_m2m;
+
+       /* Initialize continious memory allocator */
+       gsc->alloc_ctx = vb2_dma_contig_init_ctx(dev);
+       if (IS_ERR(gsc->alloc_ctx)) {
+               ret = PTR_ERR(gsc->alloc_ctx);
+               goto err_pm;
+       }
+
+       dev_dbg(dev, "gsc-%d registered successfully\n", gsc->id);
+
+       pm_runtime_put(dev);
+       return 0;
+err_pm:
+       pm_runtime_put(dev);
+err_m2m:
+       gsc_unregister_m2m_device(gsc);
+err_clk:
+       gsc_clk_put(gsc);
+       return ret;
+}
+
+static int __devexit gsc_remove(struct platform_device *pdev)
+{
+       struct gsc_dev *gsc = platform_get_drvdata(pdev);
+
+       gsc_unregister_m2m_device(gsc);
+
+       vb2_dma_contig_cleanup_ctx(gsc->alloc_ctx);
+       pm_runtime_disable(&pdev->dev);
+
+       dev_dbg(&pdev->dev, "%s driver unloaded\n", pdev->name);
+       return 0;
+}
+
+static int gsc_runtime_resume(struct device *dev)
+{
+       struct gsc_dev *gsc = dev_get_drvdata(dev);
+       int ret = 0;
+
+       pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+
+       ret = clk_enable(gsc->clock);
+       if (ret)
+               return ret;
+
+       gsc_hw_set_sw_reset(gsc);
+       gsc_wait_reset(gsc);
+
+       return gsc_m2m_resume(gsc);
+}
+
+static int gsc_runtime_suspend(struct device *dev)
+{
+       struct gsc_dev *gsc = dev_get_drvdata(dev);
+       int ret = 0;
+
+       ret = gsc_m2m_suspend(gsc);
+       if (!ret)
+               clk_disable(gsc->clock);
+
+       pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+       return ret;
+}
+
+static int gsc_resume(struct device *dev)
+{
+       struct gsc_dev *gsc = dev_get_drvdata(dev);
+       unsigned long flags;
+
+       pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+
+       /* Do not resume if the device was idle before system suspend */
+       spin_lock_irqsave(&gsc->slock, flags);
+       if (!test_and_clear_bit(ST_SUSPEND, &gsc->state) ||
+           !gsc_m2m_active(gsc)) {
+               spin_unlock_irqrestore(&gsc->slock, flags);
+               return 0;
+       }
+       gsc_hw_set_sw_reset(gsc);
+       gsc_wait_reset(gsc);
+
+       spin_unlock_irqrestore(&gsc->slock, flags);
+
+       return gsc_m2m_resume(gsc);
+}
+
+static int gsc_suspend(struct device *dev)
+{
+       struct gsc_dev *gsc = dev_get_drvdata(dev);
+
+       pr_debug("gsc%d: state: 0x%lx", gsc->id, gsc->state);
+
+       if (test_and_set_bit(ST_SUSPEND, &gsc->state))
+               return 0;
+
+       return gsc_m2m_suspend(gsc);
+}
+
+static const struct dev_pm_ops gsc_pm_ops = {
+       .suspend                = gsc_suspend,
+       .resume                 = gsc_resume,
+       .runtime_suspend        = gsc_runtime_suspend,
+       .runtime_resume         = gsc_runtime_resume,
+};
+
+static struct platform_driver gsc_driver = {
+       .probe          = gsc_probe,
+       .remove = __devexit_p(gsc_remove),
+       .id_table       = gsc_driver_ids,
+       .driver = {
+               .name   = GSC_MODULE_NAME,
+               .owner  = THIS_MODULE,
+               .pm     = &gsc_pm_ops,
+               .of_match_table = exynos_gsc_match,
+       }
+};
+
+module_platform_driver(gsc_driver);
+
+MODULE_AUTHOR("Hyunwong Kim <khw0178.kim@samsung.com>");
+MODULE_DESCRIPTION("Samsung EXYNOS5 Soc series G-Scaler driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/platform/exynos-gsc/gsc-core.h b/drivers/media/platform/exynos-gsc/gsc-core.h
new file mode 100644 (file)
index 0000000..5f157ef
--- /dev/null
@@ -0,0 +1,527 @@
+/*
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * header file for Samsung EXYNOS5 SoC series G-Scaler driver
+
+ * 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.
+ */
+
+#ifndef GSC_CORE_H_
+#define GSC_CORE_H_
+
+#include <linux/delay.h>
+#include <linux/sched.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+#include <linux/videodev2.h>
+#include <linux/io.h>
+#include <linux/pm_runtime.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-ctrls.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-mediabus.h>
+#include <media/videobuf2-dma-contig.h>
+
+#include "gsc-regs.h"
+
+#define CONFIG_VB2_GSC_DMA_CONTIG      1
+#define GSC_MODULE_NAME                        "exynos-gsc"
+
+#define GSC_SHUTDOWN_TIMEOUT           ((100*HZ)/1000)
+#define GSC_MAX_DEVS                   4
+#define GSC_M2M_BUF_NUM                        0
+#define GSC_MAX_CTRL_NUM               10
+#define GSC_SC_ALIGN_4                 4
+#define GSC_SC_ALIGN_2                 2
+#define DEFAULT_CSC_EQ                 1
+#define DEFAULT_CSC_RANGE              1
+
+#define GSC_PARAMS                     (1 << 0)
+#define GSC_SRC_FMT                    (1 << 1)
+#define GSC_DST_FMT                    (1 << 2)
+#define GSC_CTX_M2M                    (1 << 3)
+#define GSC_CTX_STOP_REQ               (1 << 6)
+
+enum gsc_dev_flags {
+       /* for global */
+       ST_SUSPEND,
+
+       /* for m2m node */
+       ST_M2M_OPEN,
+       ST_M2M_RUN,
+       ST_M2M_PEND,
+       ST_M2M_SUSPENDED,
+       ST_M2M_SUSPENDING,
+};
+
+enum gsc_irq {
+       GSC_IRQ_DONE,
+       GSC_IRQ_OVERRUN
+};
+
+/**
+ * enum gsc_datapath - the path of data used for G-Scaler
+ * @GSC_CAMERA: from camera
+ * @GSC_DMA: from/to DMA
+ * @GSC_LOCAL: to local path
+ * @GSC_WRITEBACK: from FIMD
+ */
+enum gsc_datapath {
+       GSC_CAMERA = 0x1,
+       GSC_DMA,
+       GSC_MIXER,
+       GSC_FIMD,
+       GSC_WRITEBACK,
+};
+
+enum gsc_color_fmt {
+       GSC_RGB = 0x1,
+       GSC_YUV420 = 0x2,
+       GSC_YUV422 = 0x4,
+       GSC_YUV444 = 0x8,
+};
+
+enum gsc_yuv_fmt {
+       GSC_LSB_Y = 0x10,
+       GSC_LSB_C,
+       GSC_CBCR = 0x20,
+       GSC_CRCB,
+};
+
+#define fh_to_ctx(__fh) container_of(__fh, struct gsc_ctx, fh)
+#define is_rgb(x) (!!((x) & 0x1))
+#define is_yuv420(x) (!!((x) & 0x2))
+#define is_yuv422(x) (!!((x) & 0x4))
+
+#define gsc_m2m_active(dev)    test_bit(ST_M2M_RUN, &(dev)->state)
+#define gsc_m2m_pending(dev)   test_bit(ST_M2M_PEND, &(dev)->state)
+#define gsc_m2m_opened(dev)    test_bit(ST_M2M_OPEN, &(dev)->state)
+
+#define ctrl_to_ctx(__ctrl) \
+       container_of((__ctrl)->handler, struct gsc_ctx, ctrl_handler)
+/**
+ * struct gsc_fmt - the driver's internal color format data
+ * @mbus_code: Media Bus pixel code, -1 if not applicable
+ * @name: format description
+ * @pixelformat: the fourcc code for this format, 0 if not applicable
+ * @yorder: Y/C order
+ * @corder: Chrominance order control
+ * @num_planes: number of physically non-contiguous data planes
+ * @nr_comp: number of physically contiguous data planes
+ * @depth: per plane driver's private 'number of bits per pixel'
+ * @flags: flags indicating which operation mode format applies to
+ */
+struct gsc_fmt {
+       enum v4l2_mbus_pixelcode mbus_code;
+       char    *name;
+       u32     pixelformat;
+       u32     color;
+       u32     yorder;
+       u32     corder;
+       u16     num_planes;
+       u16     num_comp;
+       u8      depth[VIDEO_MAX_PLANES];
+       u32     flags;
+};
+
+/**
+ * struct gsc_input_buf - the driver's video buffer
+ * @vb:        videobuf2 buffer
+ * @list : linked list structure for buffer queue
+ * @idx : index of G-Scaler input buffer
+ */
+struct gsc_input_buf {
+       struct vb2_buffer       vb;
+       struct list_head        list;
+       int                     idx;
+};
+
+/**
+ * struct gsc_addr - the G-Scaler physical address set
+ * @y:  luminance plane address
+ * @cb:         Cb plane address
+ * @cr:         Cr plane address
+ */
+struct gsc_addr {
+       dma_addr_t y;
+       dma_addr_t cb;
+       dma_addr_t cr;
+};
+
+/* struct gsc_ctrls - the G-Scaler control set
+ * @rotate: rotation degree
+ * @hflip: horizontal flip
+ * @vflip: vertical flip
+ * @global_alpha: the alpha value of current frame
+ */
+struct gsc_ctrls {
+       struct v4l2_ctrl *rotate;
+       struct v4l2_ctrl *hflip;
+       struct v4l2_ctrl *vflip;
+       struct v4l2_ctrl *global_alpha;
+};
+
+/**
+ * struct gsc_scaler - the configuration data for G-Scaler inetrnal scaler
+ * @pre_shfactor:      pre sclaer shift factor
+ * @pre_hratio:                horizontal ratio of the prescaler
+ * @pre_vratio:                vertical ratio of the prescaler
+ * @main_hratio:       the main scaler's horizontal ratio
+ * @main_vratio:       the main scaler's vertical ratio
+ */
+struct gsc_scaler {
+       u32 pre_shfactor;
+       u32 pre_hratio;
+       u32 pre_vratio;
+       u32 main_hratio;
+       u32 main_vratio;
+};
+
+struct gsc_dev;
+
+struct gsc_ctx;
+
+/**
+ * struct gsc_frame - source/target frame properties
+ * @f_width:   SRC : SRCIMG_WIDTH, DST : OUTPUTDMA_WHOLE_IMG_WIDTH
+ * @f_height:  SRC : SRCIMG_HEIGHT, DST : OUTPUTDMA_WHOLE_IMG_HEIGHT
+ * @crop:      cropped(source)/scaled(destination) size
+ * @payload:   image size in bytes (w x h x bpp)
+ * @addr:      image frame buffer physical addresses
+ * @fmt:       G-Scaler color format pointer
+ * @colorspace: value indicating v4l2_colorspace
+ * @alpha:     frame's alpha value
+ */
+struct gsc_frame {
+       u32 f_width;
+       u32 f_height;
+       struct v4l2_rect crop;
+       unsigned long payload[VIDEO_MAX_PLANES];
+       struct gsc_addr addr;
+       const struct gsc_fmt *fmt;
+       u32 colorspace;
+       u8 alpha;
+};
+
+/**
+ * struct gsc_m2m_device - v4l2 memory-to-memory device data
+ * @vfd: the video device node for v4l2 m2m mode
+ * @m2m_dev: v4l2 memory-to-memory device data
+ * @ctx: hardware context data
+ * @refcnt: the reference counter
+ */
+struct gsc_m2m_device {
+       struct video_device     *vfd;
+       struct v4l2_m2m_dev     *m2m_dev;
+       struct gsc_ctx          *ctx;
+       int                     refcnt;
+};
+
+/**
+ *  struct gsc_pix_max - image pixel size limits in various IP configurations
+ *
+ *  @org_scaler_bypass_w: max pixel width when the scaler is disabled
+ *  @org_scaler_bypass_h: max pixel height when the scaler is disabled
+ *  @org_scaler_input_w: max pixel width when the scaler is enabled
+ *  @org_scaler_input_h: max pixel height when the scaler is enabled
+ *  @real_rot_dis_w: max pixel src cropped height with the rotator is off
+ *  @real_rot_dis_h: max pixel src croppped width with the rotator is off
+ *  @real_rot_en_w: max pixel src cropped width with the rotator is on
+ *  @real_rot_en_h: max pixel src cropped height with the rotator is on
+ *  @target_rot_dis_w: max pixel dst scaled width with the rotator is off
+ *  @target_rot_dis_h: max pixel dst scaled height with the rotator is off
+ *  @target_rot_en_w: max pixel dst scaled width with the rotator is on
+ *  @target_rot_en_h: max pixel dst scaled height with the rotator is on
+ */
+struct gsc_pix_max {
+       u16 org_scaler_bypass_w;
+       u16 org_scaler_bypass_h;
+       u16 org_scaler_input_w;
+       u16 org_scaler_input_h;
+       u16 real_rot_dis_w;
+       u16 real_rot_dis_h;
+       u16 real_rot_en_w;
+       u16 real_rot_en_h;
+       u16 target_rot_dis_w;
+       u16 target_rot_dis_h;
+       u16 target_rot_en_w;
+       u16 target_rot_en_h;
+};
+
+/**
+ *  struct gsc_pix_min - image pixel size limits in various IP configurations
+ *
+ *  @org_w: minimum source pixel width
+ *  @org_h: minimum source pixel height
+ *  @real_w: minimum input crop pixel width
+ *  @real_h: minimum input crop pixel height
+ *  @target_rot_dis_w: minimum output scaled pixel height when rotator is off
+ *  @target_rot_dis_h: minimum output scaled pixel height when rotator is off
+ *  @target_rot_en_w: minimum output scaled pixel height when rotator is on
+ *  @target_rot_en_h: minimum output scaled pixel height when rotator is on
+ */
+struct gsc_pix_min {
+       u16 org_w;
+       u16 org_h;
+       u16 real_w;
+       u16 real_h;
+       u16 target_rot_dis_w;
+       u16 target_rot_dis_h;
+       u16 target_rot_en_w;
+       u16 target_rot_en_h;
+};
+
+struct gsc_pix_align {
+       u16 org_h;
+       u16 org_w;
+       u16 offset_h;
+       u16 real_w;
+       u16 real_h;
+       u16 target_w;
+       u16 target_h;
+};
+
+/**
+ * struct gsc_variant - G-Scaler variant information
+ */
+struct gsc_variant {
+       struct gsc_pix_max *pix_max;
+       struct gsc_pix_min *pix_min;
+       struct gsc_pix_align *pix_align;
+       u16             in_buf_cnt;
+       u16             out_buf_cnt;
+       u16             sc_up_max;
+       u16             sc_down_max;
+       u16             poly_sc_down_max;
+       u16             pre_sc_down_max;
+       u16             local_sc_down;
+};
+
+/**
+ * struct gsc_driverdata - per device type driver data for init time.
+ *
+ * @variant: the variant information for this driver.
+ * @lclk_frequency: G-Scaler clock frequency
+ * @num_entities: the number of g-scalers
+ */
+struct gsc_driverdata {
+       struct gsc_variant *variant[GSC_MAX_DEVS];
+       unsigned long   lclk_frequency;
+       int             num_entities;
+};
+
+/**
+ * struct gsc_dev - abstraction for G-Scaler entity
+ * @slock:     the spinlock protecting this data structure
+ * @lock:      the mutex protecting this data structure
+ * @pdev:      pointer to the G-Scaler platform device
+ * @variant:   the IP variant information
+ * @id:                G-Scaler device index (0..GSC_MAX_DEVS)
+ * @clock:     clocks required for G-Scaler operation
+ * @regs:      the mapped hardware registers
+ * @irq_queue: interrupt handler waitqueue
+ * @m2m:       memory-to-memory V4L2 device information
+ * @state:     flags used to synchronize m2m and capture mode operation
+ * @alloc_ctx: videobuf2 memory allocator context
+ * @vdev:      video device for G-Scaler instance
+ */
+struct gsc_dev {
+       spinlock_t                      slock;
+       struct mutex                    lock;
+       struct platform_device          *pdev;
+       struct gsc_variant              *variant;
+       u16                             id;
+       struct clk                      *clock;
+       void __iomem                    *regs;
+       wait_queue_head_t               irq_queue;
+       struct gsc_m2m_device           m2m;
+       struct exynos_platform_gscaler  *pdata;
+       unsigned long                   state;
+       struct vb2_alloc_ctx            *alloc_ctx;
+       struct video_device             vdev;
+};
+
+/**
+ * gsc_ctx - the device context data
+ * @s_frame:           source frame properties
+ * @d_frame:           destination frame properties
+ * @in_path:           input mode (DMA or camera)
+ * @out_path:          output mode (DMA or FIFO)
+ * @scaler:            image scaler properties
+ * @flags:             additional flags for image conversion
+ * @state:             flags to keep track of user configuration
+ * @gsc_dev:           the G-Scaler device this context applies to
+ * @m2m_ctx:           memory-to-memory device context
+ * @fh:                 v4l2 file handle
+ * @ctrl_handler:       v4l2 controls handler
+ * @gsc_ctrls          G-Scaler control set
+ * @ctrls_rdy:          true if the control handler is initialized
+ */
+struct gsc_ctx {
+       struct gsc_frame        s_frame;
+       struct gsc_frame        d_frame;
+       enum gsc_datapath       in_path;
+       enum gsc_datapath       out_path;
+       struct gsc_scaler       scaler;
+       u32                     flags;
+       u32                     state;
+       int                     rotation;
+       unsigned int            hflip:1;
+       unsigned int            vflip:1;
+       struct gsc_dev          *gsc_dev;
+       struct v4l2_m2m_ctx     *m2m_ctx;
+       struct v4l2_fh          fh;
+       struct v4l2_ctrl_handler ctrl_handler;
+       struct gsc_ctrls        gsc_ctrls;
+       bool                    ctrls_rdy;
+};
+
+void gsc_set_prefbuf(struct gsc_dev *gsc, struct gsc_frame *frm);
+int gsc_register_m2m_device(struct gsc_dev *gsc);
+void gsc_unregister_m2m_device(struct gsc_dev *gsc);
+void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state);
+
+u32 get_plane_size(struct gsc_frame *fr, unsigned int plane);
+const struct gsc_fmt *get_format(int index);
+const struct gsc_fmt *find_fmt(u32 *pixelformat, u32 *mbus_code, u32 index);
+int gsc_enum_fmt_mplane(struct v4l2_fmtdesc *f);
+int gsc_try_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f);
+void gsc_set_frame_size(struct gsc_frame *frame, int width, int height);
+int gsc_g_fmt_mplane(struct gsc_ctx *ctx, struct v4l2_format *f);
+void gsc_check_crop_change(u32 tmp_w, u32 tmp_h, u32 *w, u32 *h);
+int gsc_g_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr);
+int gsc_try_crop(struct gsc_ctx *ctx, struct v4l2_crop *cr);
+int gsc_cal_prescaler_ratio(struct gsc_variant *var, u32 src, u32 dst,
+                                                       u32 *ratio);
+void gsc_get_prescaler_shfactor(u32 hratio, u32 vratio, u32 *sh);
+void gsc_check_src_scale_info(struct gsc_variant *var,
+                               struct gsc_frame *s_frame,
+                               u32 *wratio, u32 tx, u32 ty, u32 *hratio);
+int gsc_check_scaler_ratio(struct gsc_variant *var, int sw, int sh, int dw,
+                          int dh, int rot, int out_path);
+int gsc_set_scaler_info(struct gsc_ctx *ctx);
+int gsc_ctrls_create(struct gsc_ctx *ctx);
+void gsc_ctrls_delete(struct gsc_ctx *ctx);
+int gsc_prepare_addr(struct gsc_ctx *ctx, struct vb2_buffer *vb,
+                    struct gsc_frame *frame, struct gsc_addr *addr);
+
+static inline void gsc_ctx_state_lock_set(u32 state, struct gsc_ctx *ctx)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->gsc_dev->slock, flags);
+       ctx->state |= state;
+       spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags);
+}
+
+static inline void gsc_ctx_state_lock_clear(u32 state, struct gsc_ctx *ctx)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&ctx->gsc_dev->slock, flags);
+       ctx->state &= ~state;
+       spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags);
+}
+
+static inline void gsc_hw_enable_control(struct gsc_dev *dev, bool on)
+{
+       u32 cfg = readl(dev->regs + GSC_ENABLE);
+
+       if (on)
+               cfg |= GSC_ENABLE_ON;
+       else
+               cfg &= ~GSC_ENABLE_ON;
+
+       writel(cfg, dev->regs + GSC_ENABLE);
+}
+
+static inline int gsc_hw_get_irq_status(struct gsc_dev *dev)
+{
+       u32 cfg = readl(dev->regs + GSC_IRQ);
+       if (cfg & GSC_IRQ_STATUS_OR_IRQ)
+               return GSC_IRQ_OVERRUN;
+       else
+               return GSC_IRQ_DONE;
+
+}
+
+static inline void gsc_hw_clear_irq(struct gsc_dev *dev, int irq)
+{
+       u32 cfg = readl(dev->regs + GSC_IRQ);
+       if (irq == GSC_IRQ_OVERRUN)
+               cfg |= GSC_IRQ_STATUS_OR_IRQ;
+       else if (irq == GSC_IRQ_DONE)
+               cfg |= GSC_IRQ_STATUS_FRM_DONE_IRQ;
+       writel(cfg, dev->regs + GSC_IRQ);
+}
+
+static inline void gsc_lock(struct vb2_queue *vq)
+{
+       struct gsc_ctx *ctx = vb2_get_drv_priv(vq);
+       mutex_lock(&ctx->gsc_dev->lock);
+}
+
+static inline void gsc_unlock(struct vb2_queue *vq)
+{
+       struct gsc_ctx *ctx = vb2_get_drv_priv(vq);
+       mutex_unlock(&ctx->gsc_dev->lock);
+}
+
+static inline bool gsc_ctx_state_is_set(u32 mask, struct gsc_ctx *ctx)
+{
+       unsigned long flags;
+       bool ret;
+
+       spin_lock_irqsave(&ctx->gsc_dev->slock, flags);
+       ret = (ctx->state & mask) == mask;
+       spin_unlock_irqrestore(&ctx->gsc_dev->slock, flags);
+       return ret;
+}
+
+static inline struct gsc_frame *ctx_get_frame(struct gsc_ctx *ctx,
+                                             enum v4l2_buf_type type)
+{
+       struct gsc_frame *frame;
+
+       if (V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE == type) {
+               frame = &ctx->s_frame;
+       } else if (V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE == type) {
+               frame = &ctx->d_frame;
+       } else {
+               pr_err("Wrong buffer/video queue type (%d)", type);
+               return ERR_PTR(-EINVAL);
+       }
+
+       return frame;
+}
+
+void gsc_hw_set_sw_reset(struct gsc_dev *dev);
+int gsc_wait_reset(struct gsc_dev *dev);
+
+void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask);
+void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask);
+void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift, bool enable);
+void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift, bool enable);
+void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
+                                                       int index);
+void gsc_hw_set_output_addr(struct gsc_dev *dev, struct gsc_addr *addr,
+                                                       int index);
+void gsc_hw_set_input_path(struct gsc_ctx *ctx);
+void gsc_hw_set_in_size(struct gsc_ctx *ctx);
+void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx);
+void gsc_hw_set_in_image_format(struct gsc_ctx *ctx);
+void gsc_hw_set_output_path(struct gsc_ctx *ctx);
+void gsc_hw_set_out_size(struct gsc_ctx *ctx);
+void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx);
+void gsc_hw_set_out_image_format(struct gsc_ctx *ctx);
+void gsc_hw_set_prescaler(struct gsc_ctx *ctx);
+void gsc_hw_set_mainscaler(struct gsc_ctx *ctx);
+void gsc_hw_set_rotation(struct gsc_ctx *ctx);
+void gsc_hw_set_global_alpha(struct gsc_ctx *ctx);
+void gsc_hw_set_sfr_update(struct gsc_ctx *ctx);
+
+#endif /* GSC_CORE_H_ */
diff --git a/drivers/media/platform/exynos-gsc/gsc-m2m.c b/drivers/media/platform/exynos-gsc/gsc-m2m.c
new file mode 100644 (file)
index 0000000..3c7f005
--- /dev/null
@@ -0,0 +1,770 @@
+/*
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series G-Scaler driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+#include <linux/errno.h>
+#include <linux/bug.h>
+#include <linux/interrupt.h>
+#include <linux/workqueue.h>
+#include <linux/device.h>
+#include <linux/platform_device.h>
+#include <linux/list.h>
+#include <linux/io.h>
+#include <linux/slab.h>
+#include <linux/clk.h>
+
+#include <media/v4l2-ioctl.h>
+
+#include "gsc-core.h"
+
+static int gsc_m2m_ctx_stop_req(struct gsc_ctx *ctx)
+{
+       struct gsc_ctx *curr_ctx;
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       int ret;
+
+       curr_ctx = v4l2_m2m_get_curr_priv(gsc->m2m.m2m_dev);
+       if (!gsc_m2m_pending(gsc) || (curr_ctx != ctx))
+               return 0;
+
+       gsc_ctx_state_lock_set(GSC_CTX_STOP_REQ, ctx);
+       ret = wait_event_timeout(gsc->irq_queue,
+                       !gsc_ctx_state_is_set(GSC_CTX_STOP_REQ, ctx),
+                       GSC_SHUTDOWN_TIMEOUT);
+
+       return ret == 0 ? -ETIMEDOUT : ret;
+}
+
+static int gsc_m2m_start_streaming(struct vb2_queue *q, unsigned int count)
+{
+       struct gsc_ctx *ctx = q->drv_priv;
+       int ret;
+
+       ret = pm_runtime_get_sync(&ctx->gsc_dev->pdev->dev);
+       return ret > 0 ? 0 : ret;
+}
+
+static int gsc_m2m_stop_streaming(struct vb2_queue *q)
+{
+       struct gsc_ctx *ctx = q->drv_priv;
+       int ret;
+
+       ret = gsc_m2m_ctx_stop_req(ctx);
+       if (ret == -ETIMEDOUT)
+               gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+
+       pm_runtime_put(&ctx->gsc_dev->pdev->dev);
+
+       return 0;
+}
+
+void gsc_m2m_job_finish(struct gsc_ctx *ctx, int vb_state)
+{
+       struct vb2_buffer *src_vb, *dst_vb;
+
+       if (!ctx || !ctx->m2m_ctx)
+               return;
+
+       src_vb = v4l2_m2m_src_buf_remove(ctx->m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(ctx->m2m_ctx);
+
+       if (src_vb && dst_vb) {
+               v4l2_m2m_buf_done(src_vb, vb_state);
+               v4l2_m2m_buf_done(dst_vb, vb_state);
+
+               v4l2_m2m_job_finish(ctx->gsc_dev->m2m.m2m_dev,
+                                   ctx->m2m_ctx);
+       }
+}
+
+
+static void gsc_m2m_job_abort(void *priv)
+{
+       struct gsc_ctx *ctx = priv;
+       int ret;
+
+       ret = gsc_m2m_ctx_stop_req(ctx);
+       if (ret == -ETIMEDOUT)
+               gsc_m2m_job_finish(ctx, VB2_BUF_STATE_ERROR);
+}
+
+static int gsc_fill_addr(struct gsc_ctx *ctx)
+{
+       struct gsc_frame *s_frame, *d_frame;
+       struct vb2_buffer *vb = NULL;
+       int ret;
+
+       s_frame = &ctx->s_frame;
+       d_frame = &ctx->d_frame;
+
+       vb = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       ret = gsc_prepare_addr(ctx, vb, s_frame, &s_frame->addr);
+       if (ret)
+               return ret;
+
+       vb = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+       return gsc_prepare_addr(ctx, vb, d_frame, &d_frame->addr);
+}
+
+static void gsc_m2m_device_run(void *priv)
+{
+       struct gsc_ctx *ctx = priv;
+       struct gsc_dev *gsc;
+       unsigned long flags;
+       u32 ret;
+       bool is_set = false;
+
+       if (WARN(!ctx, "null hardware context\n"))
+               return;
+
+       gsc = ctx->gsc_dev;
+       spin_lock_irqsave(&gsc->slock, flags);
+
+       set_bit(ST_M2M_PEND, &gsc->state);
+
+       /* Reconfigure hardware if the context has changed. */
+       if (gsc->m2m.ctx != ctx) {
+               pr_debug("gsc->m2m.ctx = 0x%p, current_ctx = 0x%p",
+                               gsc->m2m.ctx, ctx);
+               ctx->state |= GSC_PARAMS;
+               gsc->m2m.ctx = ctx;
+       }
+
+       is_set = (ctx->state & GSC_CTX_STOP_REQ) ? 1 : 0;
+       ctx->state &= ~GSC_CTX_STOP_REQ;
+       if (is_set) {
+               wake_up(&gsc->irq_queue);
+               goto put_device;
+       }
+
+       ret = gsc_fill_addr(ctx);
+       if (ret) {
+               pr_err("Wrong address");
+               goto put_device;
+       }
+
+       gsc_set_prefbuf(gsc, &ctx->s_frame);
+       gsc_hw_set_input_addr(gsc, &ctx->s_frame.addr, GSC_M2M_BUF_NUM);
+       gsc_hw_set_output_addr(gsc, &ctx->d_frame.addr, GSC_M2M_BUF_NUM);
+
+       if (ctx->state & GSC_PARAMS) {
+               gsc_hw_set_input_buf_masking(gsc, GSC_M2M_BUF_NUM, false);
+               gsc_hw_set_output_buf_masking(gsc, GSC_M2M_BUF_NUM, false);
+               gsc_hw_set_frm_done_irq_mask(gsc, false);
+               gsc_hw_set_gsc_irq_enable(gsc, true);
+
+               if (gsc_set_scaler_info(ctx)) {
+                       pr_err("Scaler setup error");
+                       goto put_device;
+               }
+
+               gsc_hw_set_input_path(ctx);
+               gsc_hw_set_in_size(ctx);
+               gsc_hw_set_in_image_format(ctx);
+
+               gsc_hw_set_output_path(ctx);
+               gsc_hw_set_out_size(ctx);
+               gsc_hw_set_out_image_format(ctx);
+
+               gsc_hw_set_prescaler(ctx);
+               gsc_hw_set_mainscaler(ctx);
+               gsc_hw_set_rotation(ctx);
+               gsc_hw_set_global_alpha(ctx);
+       }
+
+       /* update shadow registers */
+       gsc_hw_set_sfr_update(ctx);
+
+       ctx->state &= ~GSC_PARAMS;
+       gsc_hw_enable_control(gsc, true);
+
+       spin_unlock_irqrestore(&gsc->slock, flags);
+       return;
+
+put_device:
+       ctx->state &= ~GSC_PARAMS;
+       spin_unlock_irqrestore(&gsc->slock, flags);
+}
+
+static int gsc_m2m_queue_setup(struct vb2_queue *vq,
+                       const struct v4l2_format *fmt,
+                       unsigned int *num_buffers, unsigned int *num_planes,
+                       unsigned int sizes[], void *allocators[])
+{
+       struct gsc_ctx *ctx = vb2_get_drv_priv(vq);
+       struct gsc_frame *frame;
+       int i;
+
+       frame = ctx_get_frame(ctx, vq->type);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
+
+       if (!frame->fmt)
+               return -EINVAL;
+
+       *num_planes = frame->fmt->num_planes;
+       for (i = 0; i < frame->fmt->num_planes; i++) {
+               sizes[i] = frame->payload[i];
+               allocators[i] = ctx->gsc_dev->alloc_ctx;
+       }
+       return 0;
+}
+
+static int gsc_m2m_buf_prepare(struct vb2_buffer *vb)
+{
+       struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct gsc_frame *frame;
+       int i;
+
+       frame = ctx_get_frame(ctx, vb->vb2_queue->type);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
+
+       if (!V4L2_TYPE_IS_OUTPUT(vb->vb2_queue->type)) {
+               for (i = 0; i < frame->fmt->num_planes; i++)
+                       vb2_set_plane_payload(vb, i, frame->payload[i]);
+       }
+
+       return 0;
+}
+
+static void gsc_m2m_buf_queue(struct vb2_buffer *vb)
+{
+       struct gsc_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+
+       pr_debug("ctx: %p, ctx->state: 0x%x", ctx, ctx->state);
+
+       if (ctx->m2m_ctx)
+               v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+static struct vb2_ops gsc_m2m_qops = {
+       .queue_setup     = gsc_m2m_queue_setup,
+       .buf_prepare     = gsc_m2m_buf_prepare,
+       .buf_queue       = gsc_m2m_buf_queue,
+       .wait_prepare    = gsc_unlock,
+       .wait_finish     = gsc_lock,
+       .stop_streaming  = gsc_m2m_stop_streaming,
+       .start_streaming = gsc_m2m_start_streaming,
+};
+
+static int gsc_m2m_querycap(struct file *file, void *fh,
+                          struct v4l2_capability *cap)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       struct gsc_dev *gsc = ctx->gsc_dev;
+
+       strlcpy(cap->driver, gsc->pdev->name, sizeof(cap->driver));
+       strlcpy(cap->card, gsc->pdev->name, sizeof(cap->card));
+       strlcpy(cap->bus_info, "platform", sizeof(cap->bus_info));
+       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_M2M_MPLANE |
+               V4L2_CAP_VIDEO_CAPTURE_MPLANE | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int gsc_m2m_enum_fmt_mplane(struct file *file, void *priv,
+                               struct v4l2_fmtdesc *f)
+{
+       return gsc_enum_fmt_mplane(f);
+}
+
+static int gsc_m2m_g_fmt_mplane(struct file *file, void *fh,
+                            struct v4l2_format *f)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+
+       return gsc_g_fmt_mplane(ctx, f);
+}
+
+static int gsc_m2m_try_fmt_mplane(struct file *file, void *fh,
+                                 struct v4l2_format *f)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+
+       return gsc_try_fmt_mplane(ctx, f);
+}
+
+static int gsc_m2m_s_fmt_mplane(struct file *file, void *fh,
+                                struct v4l2_format *f)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       struct vb2_queue *vq;
+       struct gsc_frame *frame;
+       struct v4l2_pix_format_mplane *pix;
+       int i, ret = 0;
+
+       ret = gsc_m2m_try_fmt_mplane(file, fh, f);
+       if (ret)
+               return ret;
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+
+       if (vb2_is_streaming(vq)) {
+               pr_err("queue (%d) busy", f->type);
+               return -EBUSY;
+       }
+
+       if (V4L2_TYPE_IS_OUTPUT(f->type))
+               frame = &ctx->s_frame;
+       else
+               frame = &ctx->d_frame;
+
+       pix = &f->fmt.pix_mp;
+       frame->fmt = find_fmt(&pix->pixelformat, NULL, 0);
+       frame->colorspace = pix->colorspace;
+       if (!frame->fmt)
+               return -EINVAL;
+
+       for (i = 0; i < frame->fmt->num_planes; i++)
+               frame->payload[i] = pix->plane_fmt[i].sizeimage;
+
+       gsc_set_frame_size(frame, pix->width, pix->height);
+
+       if (f->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+               gsc_ctx_state_lock_set(GSC_PARAMS | GSC_DST_FMT, ctx);
+       else
+               gsc_ctx_state_lock_set(GSC_PARAMS | GSC_SRC_FMT, ctx);
+
+       pr_debug("f_w: %d, f_h: %d", frame->f_width, frame->f_height);
+
+       return 0;
+}
+
+static int gsc_m2m_reqbufs(struct file *file, void *fh,
+                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       struct gsc_frame *frame;
+       u32 max_cnt;
+
+       max_cnt = (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
+               gsc->variant->in_buf_cnt : gsc->variant->out_buf_cnt;
+       if (reqbufs->count > max_cnt) {
+               return -EINVAL;
+       } else if (reqbufs->count == 0) {
+               if (reqbufs->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+                       gsc_ctx_state_lock_clear(GSC_SRC_FMT, ctx);
+               else
+                       gsc_ctx_state_lock_clear(GSC_DST_FMT, ctx);
+       }
+
+       frame = ctx_get_frame(ctx, reqbufs->type);
+
+       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int gsc_m2m_querybuf(struct file *file, void *fh,
+                                       struct v4l2_buffer *buf)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int gsc_m2m_qbuf(struct file *file, void *fh,
+                         struct v4l2_buffer *buf)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int gsc_m2m_dqbuf(struct file *file, void *fh,
+                          struct v4l2_buffer *buf)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int gsc_m2m_streamon(struct file *file, void *fh,
+                          enum v4l2_buf_type type)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+
+       /* The source and target color format need to be set */
+       if (V4L2_TYPE_IS_OUTPUT(type)) {
+               if (!gsc_ctx_state_is_set(GSC_SRC_FMT, ctx))
+                       return -EINVAL;
+       } else if (!gsc_ctx_state_is_set(GSC_DST_FMT, ctx)) {
+               return -EINVAL;
+       }
+
+       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int gsc_m2m_streamoff(struct file *file, void *fh,
+                           enum v4l2_buf_type type)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+/* Return 1 if rectangle a is enclosed in rectangle b, or 0 otherwise. */
+static int is_rectangle_enclosed(struct v4l2_rect *a, struct v4l2_rect *b)
+{
+       if (a->left < b->left || a->top < b->top)
+               return 0;
+
+       if (a->left + a->width > b->left + b->width)
+               return 0;
+
+       if (a->top + a->height > b->top + b->height)
+               return 0;
+
+       return 1;
+}
+
+static int gsc_m2m_g_selection(struct file *file, void *fh,
+                       struct v4l2_selection *s)
+{
+       struct gsc_frame *frame;
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+
+       if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+           (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE))
+               return -EINVAL;
+
+       frame = ctx_get_frame(ctx, s->type);
+       if (IS_ERR(frame))
+               return PTR_ERR(frame);
+
+       switch (s->target) {
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               s->r.left = 0;
+               s->r.top = 0;
+               s->r.width = frame->f_width;
+               s->r.height = frame->f_height;
+               return 0;
+
+       case V4L2_SEL_TGT_COMPOSE:
+       case V4L2_SEL_TGT_CROP:
+               s->r.left = frame->crop.left;
+               s->r.top = frame->crop.top;
+               s->r.width = frame->crop.width;
+               s->r.height = frame->crop.height;
+               return 0;
+       }
+
+       return -EINVAL;
+}
+
+static int gsc_m2m_s_selection(struct file *file, void *fh,
+                               struct v4l2_selection *s)
+{
+       struct gsc_frame *frame;
+       struct gsc_ctx *ctx = fh_to_ctx(fh);
+       struct v4l2_crop cr;
+       struct gsc_variant *variant = ctx->gsc_dev->variant;
+       int ret;
+
+       cr.type = s->type;
+       cr.c = s->r;
+
+       if ((s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) &&
+           (s->type != V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE))
+               return -EINVAL;
+
+       ret = gsc_try_crop(ctx, &cr);
+       if (ret)
+               return ret;
+
+       if (s->flags & V4L2_SEL_FLAG_LE &&
+           !is_rectangle_enclosed(&cr.c, &s->r))
+               return -ERANGE;
+
+       if (s->flags & V4L2_SEL_FLAG_GE &&
+           !is_rectangle_enclosed(&s->r, &cr.c))
+               return -ERANGE;
+
+       s->r = cr.c;
+
+       switch (s->target) {
+       case V4L2_SEL_TGT_COMPOSE_BOUNDS:
+       case V4L2_SEL_TGT_COMPOSE_DEFAULT:
+       case V4L2_SEL_TGT_COMPOSE:
+               frame = &ctx->s_frame;
+               break;
+
+       case V4L2_SEL_TGT_CROP_BOUNDS:
+       case V4L2_SEL_TGT_CROP:
+       case V4L2_SEL_TGT_CROP_DEFAULT:
+               frame = &ctx->d_frame;
+               break;
+
+       default:
+               return -EINVAL;
+       }
+
+       /* Check to see if scaling ratio is within supported range */
+       if (gsc_ctx_state_is_set(GSC_DST_FMT | GSC_SRC_FMT, ctx)) {
+               if (s->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       ret = gsc_check_scaler_ratio(variant, cr.c.width,
+                               cr.c.height, ctx->d_frame.crop.width,
+                               ctx->d_frame.crop.height,
+                               ctx->gsc_ctrls.rotate->val, ctx->out_path);
+               } else {
+                       ret = gsc_check_scaler_ratio(variant,
+                               ctx->s_frame.crop.width,
+                               ctx->s_frame.crop.height, cr.c.width,
+                               cr.c.height, ctx->gsc_ctrls.rotate->val,
+                               ctx->out_path);
+               }
+
+               if (ret) {
+                       pr_err("Out of scaler range");
+                       return -EINVAL;
+               }
+       }
+
+       frame->crop = cr.c;
+
+       gsc_ctx_state_lock_set(GSC_PARAMS, ctx);
+       return 0;
+}
+
+static const struct v4l2_ioctl_ops gsc_m2m_ioctl_ops = {
+       .vidioc_querycap                = gsc_m2m_querycap,
+       .vidioc_enum_fmt_vid_cap_mplane = gsc_m2m_enum_fmt_mplane,
+       .vidioc_enum_fmt_vid_out_mplane = gsc_m2m_enum_fmt_mplane,
+       .vidioc_g_fmt_vid_cap_mplane    = gsc_m2m_g_fmt_mplane,
+       .vidioc_g_fmt_vid_out_mplane    = gsc_m2m_g_fmt_mplane,
+       .vidioc_try_fmt_vid_cap_mplane  = gsc_m2m_try_fmt_mplane,
+       .vidioc_try_fmt_vid_out_mplane  = gsc_m2m_try_fmt_mplane,
+       .vidioc_s_fmt_vid_cap_mplane    = gsc_m2m_s_fmt_mplane,
+       .vidioc_s_fmt_vid_out_mplane    = gsc_m2m_s_fmt_mplane,
+       .vidioc_reqbufs                 = gsc_m2m_reqbufs,
+       .vidioc_querybuf                = gsc_m2m_querybuf,
+       .vidioc_qbuf                    = gsc_m2m_qbuf,
+       .vidioc_dqbuf                   = gsc_m2m_dqbuf,
+       .vidioc_streamon                = gsc_m2m_streamon,
+       .vidioc_streamoff               = gsc_m2m_streamoff,
+       .vidioc_g_selection             = gsc_m2m_g_selection,
+       .vidioc_s_selection             = gsc_m2m_s_selection
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                       struct vb2_queue *dst_vq)
+{
+       struct gsc_ctx *ctx = priv;
+       int ret;
+
+       memset(src_vq, 0, sizeof(*src_vq));
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->ops = &gsc_m2m_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       memset(dst_vq, 0, sizeof(*dst_vq));
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->ops = &gsc_m2m_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+
+       return vb2_queue_init(dst_vq);
+}
+
+static int gsc_m2m_open(struct file *file)
+{
+       struct gsc_dev *gsc = video_drvdata(file);
+       struct gsc_ctx *ctx = NULL;
+       int ret;
+
+       pr_debug("pid: %d, state: 0x%lx", task_pid_nr(current), gsc->state);
+
+       if (mutex_lock_interruptible(&gsc->lock))
+               return -ERESTARTSYS;
+
+       ctx = kzalloc(sizeof (*ctx), GFP_KERNEL);
+       if (!ctx) {
+               ret = -ENOMEM;
+               goto unlock;
+       }
+
+       v4l2_fh_init(&ctx->fh, gsc->m2m.vfd);
+       ret = gsc_ctrls_create(ctx);
+       if (ret)
+               goto error_fh;
+
+       /* Use separate control handler per file handle */
+       ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+       file->private_data = &ctx->fh;
+       v4l2_fh_add(&ctx->fh);
+
+       ctx->gsc_dev = gsc;
+       /* Default color format */
+       ctx->s_frame.fmt = get_format(0);
+       ctx->d_frame.fmt = get_format(0);
+       /* Setup the device context for mem2mem mode. */
+       ctx->state = GSC_CTX_M2M;
+       ctx->flags = 0;
+       ctx->in_path = GSC_DMA;
+       ctx->out_path = GSC_DMA;
+
+       ctx->m2m_ctx = v4l2_m2m_ctx_init(gsc->m2m.m2m_dev, ctx, queue_init);
+       if (IS_ERR(ctx->m2m_ctx)) {
+               pr_err("Failed to initialize m2m context");
+               ret = PTR_ERR(ctx->m2m_ctx);
+               goto error_ctrls;
+       }
+
+       if (gsc->m2m.refcnt++ == 0)
+               set_bit(ST_M2M_OPEN, &gsc->state);
+
+       pr_debug("gsc m2m driver is opened, ctx(0x%p)", ctx);
+
+       mutex_unlock(&gsc->lock);
+       return 0;
+
+error_ctrls:
+       gsc_ctrls_delete(ctx);
+error_fh:
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+       kfree(ctx);
+unlock:
+       mutex_unlock(&gsc->lock);
+       return ret;
+}
+
+static int gsc_m2m_release(struct file *file)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct gsc_dev *gsc = ctx->gsc_dev;
+
+       pr_debug("pid: %d, state: 0x%lx, refcnt= %d",
+               task_pid_nr(current), gsc->state, gsc->m2m.refcnt);
+
+       if (mutex_lock_interruptible(&gsc->lock))
+               return -ERESTARTSYS;
+
+       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       gsc_ctrls_delete(ctx);
+       v4l2_fh_del(&ctx->fh);
+       v4l2_fh_exit(&ctx->fh);
+
+       if (--gsc->m2m.refcnt <= 0)
+               clear_bit(ST_M2M_OPEN, &gsc->state);
+       kfree(ctx);
+
+       mutex_unlock(&gsc->lock);
+       return 0;
+}
+
+static unsigned int gsc_m2m_poll(struct file *file,
+                                       struct poll_table_struct *wait)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       int ret;
+
+       if (mutex_lock_interruptible(&gsc->lock))
+               return -ERESTARTSYS;
+
+       ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_unlock(&gsc->lock);
+
+       return ret;
+}
+
+static int gsc_m2m_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct gsc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct gsc_dev *gsc = ctx->gsc_dev;
+       int ret;
+
+       if (mutex_lock_interruptible(&gsc->lock))
+               return -ERESTARTSYS;
+
+       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&gsc->lock);
+
+       return ret;
+}
+
+static const struct v4l2_file_operations gsc_m2m_fops = {
+       .owner          = THIS_MODULE,
+       .open           = gsc_m2m_open,
+       .release        = gsc_m2m_release,
+       .poll           = gsc_m2m_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = gsc_m2m_mmap,
+};
+
+static struct v4l2_m2m_ops gsc_m2m_ops = {
+       .device_run     = gsc_m2m_device_run,
+       .job_abort      = gsc_m2m_job_abort,
+};
+
+int gsc_register_m2m_device(struct gsc_dev *gsc)
+{
+       struct platform_device *pdev;
+       int ret;
+
+       if (!gsc)
+               return -ENODEV;
+
+       pdev = gsc->pdev;
+
+       gsc->vdev.fops          = &gsc_m2m_fops;
+       gsc->vdev.ioctl_ops     = &gsc_m2m_ioctl_ops;
+       gsc->vdev.release       = video_device_release_empty;
+       gsc->vdev.lock          = &gsc->lock;
+       snprintf(gsc->vdev.name, sizeof(gsc->vdev.name), "%s.%d:m2m",
+                                       GSC_MODULE_NAME, gsc->id);
+
+       video_set_drvdata(&gsc->vdev, gsc);
+
+       gsc->m2m.vfd = &gsc->vdev;
+       gsc->m2m.m2m_dev = v4l2_m2m_init(&gsc_m2m_ops);
+       if (IS_ERR(gsc->m2m.m2m_dev)) {
+               dev_err(&pdev->dev, "failed to initialize v4l2-m2m device\n");
+               ret = PTR_ERR(gsc->m2m.m2m_dev);
+               goto err_m2m_r1;
+       }
+
+       ret = video_register_device(&gsc->vdev, VFL_TYPE_GRABBER, -1);
+       if (ret) {
+               dev_err(&pdev->dev,
+                        "%s(): failed to register video device\n", __func__);
+               goto err_m2m_r2;
+       }
+
+       pr_debug("gsc m2m driver registered as /dev/video%d", gsc->vdev.num);
+       return 0;
+
+err_m2m_r2:
+       v4l2_m2m_release(gsc->m2m.m2m_dev);
+err_m2m_r1:
+       video_device_release(gsc->m2m.vfd);
+
+       return ret;
+}
+
+void gsc_unregister_m2m_device(struct gsc_dev *gsc)
+{
+       if (gsc)
+               v4l2_m2m_release(gsc->m2m.m2m_dev);
+}
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.c b/drivers/media/platform/exynos-gsc/gsc-regs.c
new file mode 100644 (file)
index 0000000..0d8625f
--- /dev/null
@@ -0,0 +1,425 @@
+/*
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Samsung EXYNOS5 SoC series G-Scaler driver
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published
+ * by the Free Software Foundation, either version 2 of the License,
+ * or (at your option) any later version.
+ */
+
+#include <linux/io.h>
+#include <linux/delay.h>
+#include <mach/map.h>
+
+#include "gsc-core.h"
+
+void gsc_hw_set_sw_reset(struct gsc_dev *dev)
+{
+       writel(GSC_SW_RESET_SRESET, dev->regs + GSC_SW_RESET);
+}
+
+int gsc_wait_reset(struct gsc_dev *dev)
+{
+       unsigned long end = jiffies + msecs_to_jiffies(50);
+       u32 cfg;
+
+       while (time_before(jiffies, end)) {
+               cfg = readl(dev->regs + GSC_SW_RESET);
+               if (!cfg)
+                       return 0;
+               usleep_range(10, 20);
+       }
+
+       return -EBUSY;
+}
+
+void gsc_hw_set_frm_done_irq_mask(struct gsc_dev *dev, bool mask)
+{
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_IRQ);
+       if (mask)
+               cfg |= GSC_IRQ_FRMDONE_MASK;
+       else
+               cfg &= ~GSC_IRQ_FRMDONE_MASK;
+       writel(cfg, dev->regs + GSC_IRQ);
+}
+
+void gsc_hw_set_gsc_irq_enable(struct gsc_dev *dev, bool mask)
+{
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_IRQ);
+       if (mask)
+               cfg |= GSC_IRQ_ENABLE;
+       else
+               cfg &= ~GSC_IRQ_ENABLE;
+       writel(cfg, dev->regs + GSC_IRQ);
+}
+
+void gsc_hw_set_input_buf_masking(struct gsc_dev *dev, u32 shift,
+                               bool enable)
+{
+       u32 cfg = readl(dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
+       u32 mask = 1 << shift;
+
+       cfg &= ~mask;
+       cfg |= enable << shift;
+
+       writel(cfg, dev->regs + GSC_IN_BASE_ADDR_Y_MASK);
+       writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CB_MASK);
+       writel(cfg, dev->regs + GSC_IN_BASE_ADDR_CR_MASK);
+}
+
+void gsc_hw_set_output_buf_masking(struct gsc_dev *dev, u32 shift,
+                               bool enable)
+{
+       u32 cfg = readl(dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
+       u32 mask = 1 << shift;
+
+       cfg &= ~mask;
+       cfg |= enable << shift;
+
+       writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_Y_MASK);
+       writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CB_MASK);
+       writel(cfg, dev->regs + GSC_OUT_BASE_ADDR_CR_MASK);
+}
+
+void gsc_hw_set_input_addr(struct gsc_dev *dev, struct gsc_addr *addr,
+                               int index)
+{
+       pr_debug("src_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X", index,
+                       addr->y, addr->cb, addr->cr);
+       writel(addr->y, dev->regs + GSC_IN_BASE_ADDR_Y(index));
+       writel(addr->cb, dev->regs + GSC_IN_BASE_ADDR_CB(index));
+       writel(addr->cr, dev->regs + GSC_IN_BASE_ADDR_CR(index));
+
+}
+
+void gsc_hw_set_output_addr(struct gsc_dev *dev,
+                            struct gsc_addr *addr, int index)
+{
+       pr_debug("dst_buf[%d]: 0x%X, cb: 0x%X, cr: 0x%X",
+                       index, addr->y, addr->cb, addr->cr);
+       writel(addr->y, dev->regs + GSC_OUT_BASE_ADDR_Y(index));
+       writel(addr->cb, dev->regs + GSC_OUT_BASE_ADDR_CB(index));
+       writel(addr->cr, dev->regs + GSC_OUT_BASE_ADDR_CR(index));
+}
+
+void gsc_hw_set_input_path(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+
+       u32 cfg = readl(dev->regs + GSC_IN_CON);
+       cfg &= ~(GSC_IN_PATH_MASK | GSC_IN_LOCAL_SEL_MASK);
+
+       if (ctx->in_path == GSC_DMA)
+               cfg |= GSC_IN_PATH_MEMORY;
+
+       writel(cfg, dev->regs + GSC_IN_CON);
+}
+
+void gsc_hw_set_in_size(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->s_frame;
+       u32 cfg;
+
+       /* Set input pixel offset */
+       cfg = GSC_SRCIMG_OFFSET_X(frame->crop.left);
+       cfg |= GSC_SRCIMG_OFFSET_Y(frame->crop.top);
+       writel(cfg, dev->regs + GSC_SRCIMG_OFFSET);
+
+       /* Set input original size */
+       cfg = GSC_SRCIMG_WIDTH(frame->f_width);
+       cfg |= GSC_SRCIMG_HEIGHT(frame->f_height);
+       writel(cfg, dev->regs + GSC_SRCIMG_SIZE);
+
+       /* Set input cropped size */
+       cfg = GSC_CROPPED_WIDTH(frame->crop.width);
+       cfg |= GSC_CROPPED_HEIGHT(frame->crop.height);
+       writel(cfg, dev->regs + GSC_CROPPED_SIZE);
+}
+
+void gsc_hw_set_in_image_rgb(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->s_frame;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_IN_CON);
+       if (frame->colorspace == V4L2_COLORSPACE_REC709)
+               cfg |= GSC_IN_RGB_HD_WIDE;
+       else
+               cfg |= GSC_IN_RGB_SD_WIDE;
+
+       if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
+               cfg |= GSC_IN_RGB565;
+       else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
+               cfg |= GSC_IN_XRGB8888;
+
+       writel(cfg, dev->regs + GSC_IN_CON);
+}
+
+void gsc_hw_set_in_image_format(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->s_frame;
+       u32 i, depth = 0;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_IN_CON);
+       cfg &= ~(GSC_IN_RGB_TYPE_MASK | GSC_IN_YUV422_1P_ORDER_MASK |
+                GSC_IN_CHROMA_ORDER_MASK | GSC_IN_FORMAT_MASK |
+                GSC_IN_TILE_TYPE_MASK | GSC_IN_TILE_MODE);
+       writel(cfg, dev->regs + GSC_IN_CON);
+
+       if (is_rgb(frame->fmt->color)) {
+               gsc_hw_set_in_image_rgb(ctx);
+               return;
+       }
+       for (i = 0; i < frame->fmt->num_planes; i++)
+               depth += frame->fmt->depth[i];
+
+       switch (frame->fmt->num_comp) {
+       case 1:
+               cfg |= GSC_IN_YUV422_1P;
+               if (frame->fmt->yorder == GSC_LSB_Y)
+                       cfg |= GSC_IN_YUV422_1P_ORDER_LSB_Y;
+               else
+                       cfg |= GSC_IN_YUV422_1P_OEDER_LSB_C;
+               if (frame->fmt->corder == GSC_CBCR)
+                       cfg |= GSC_IN_CHROMA_ORDER_CBCR;
+               else
+                       cfg |= GSC_IN_CHROMA_ORDER_CRCB;
+               break;
+       case 2:
+               if (depth == 12)
+                       cfg |= GSC_IN_YUV420_2P;
+               else
+                       cfg |= GSC_IN_YUV422_2P;
+               if (frame->fmt->corder == GSC_CBCR)
+                       cfg |= GSC_IN_CHROMA_ORDER_CBCR;
+               else
+                       cfg |= GSC_IN_CHROMA_ORDER_CRCB;
+               break;
+       case 3:
+               if (depth == 12)
+                       cfg |= GSC_IN_YUV420_3P;
+               else
+                       cfg |= GSC_IN_YUV422_3P;
+               break;
+       };
+
+       writel(cfg, dev->regs + GSC_IN_CON);
+}
+
+void gsc_hw_set_output_path(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+
+       u32 cfg = readl(dev->regs + GSC_OUT_CON);
+       cfg &= ~GSC_OUT_PATH_MASK;
+
+       if (ctx->out_path == GSC_DMA)
+               cfg |= GSC_OUT_PATH_MEMORY;
+       else
+               cfg |= GSC_OUT_PATH_LOCAL;
+
+       writel(cfg, dev->regs + GSC_OUT_CON);
+}
+
+void gsc_hw_set_out_size(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       /* Set output original size */
+       if (ctx->out_path == GSC_DMA) {
+               cfg = GSC_DSTIMG_OFFSET_X(frame->crop.left);
+               cfg |= GSC_DSTIMG_OFFSET_Y(frame->crop.top);
+               writel(cfg, dev->regs + GSC_DSTIMG_OFFSET);
+
+               cfg = GSC_DSTIMG_WIDTH(frame->f_width);
+               cfg |= GSC_DSTIMG_HEIGHT(frame->f_height);
+               writel(cfg, dev->regs + GSC_DSTIMG_SIZE);
+       }
+
+       /* Set output scaled size */
+       if (ctx->gsc_ctrls.rotate->val == 90 ||
+           ctx->gsc_ctrls.rotate->val == 270) {
+               cfg = GSC_SCALED_WIDTH(frame->crop.height);
+               cfg |= GSC_SCALED_HEIGHT(frame->crop.width);
+       } else {
+               cfg = GSC_SCALED_WIDTH(frame->crop.width);
+               cfg |= GSC_SCALED_HEIGHT(frame->crop.height);
+       }
+       writel(cfg, dev->regs + GSC_SCALED_SIZE);
+}
+
+void gsc_hw_set_out_image_rgb(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_OUT_CON);
+       if (frame->colorspace == V4L2_COLORSPACE_REC709)
+               cfg |= GSC_OUT_RGB_HD_WIDE;
+       else
+               cfg |= GSC_OUT_RGB_SD_WIDE;
+
+       if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB565X)
+               cfg |= GSC_OUT_RGB565;
+       else if (frame->fmt->pixelformat == V4L2_PIX_FMT_RGB32)
+               cfg |= GSC_OUT_XRGB8888;
+
+       writel(cfg, dev->regs + GSC_OUT_CON);
+}
+
+void gsc_hw_set_out_image_format(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->d_frame;
+       u32 i, depth = 0;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_OUT_CON);
+       cfg &= ~(GSC_OUT_RGB_TYPE_MASK | GSC_OUT_YUV422_1P_ORDER_MASK |
+                GSC_OUT_CHROMA_ORDER_MASK | GSC_OUT_FORMAT_MASK |
+                GSC_OUT_TILE_TYPE_MASK | GSC_OUT_TILE_MODE);
+       writel(cfg, dev->regs + GSC_OUT_CON);
+
+       if (is_rgb(frame->fmt->color)) {
+               gsc_hw_set_out_image_rgb(ctx);
+               return;
+       }
+
+       if (ctx->out_path != GSC_DMA) {
+               cfg |= GSC_OUT_YUV444;
+               goto end_set;
+       }
+
+       for (i = 0; i < frame->fmt->num_planes; i++)
+               depth += frame->fmt->depth[i];
+
+       switch (frame->fmt->num_comp) {
+       case 1:
+               cfg |= GSC_OUT_YUV422_1P;
+               if (frame->fmt->yorder == GSC_LSB_Y)
+                       cfg |= GSC_OUT_YUV422_1P_ORDER_LSB_Y;
+               else
+                       cfg |= GSC_OUT_YUV422_1P_OEDER_LSB_C;
+               if (frame->fmt->corder == GSC_CBCR)
+                       cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
+               else
+                       cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
+               break;
+       case 2:
+               if (depth == 12)
+                       cfg |= GSC_OUT_YUV420_2P;
+               else
+                       cfg |= GSC_OUT_YUV422_2P;
+               if (frame->fmt->corder == GSC_CBCR)
+                       cfg |= GSC_OUT_CHROMA_ORDER_CBCR;
+               else
+                       cfg |= GSC_OUT_CHROMA_ORDER_CRCB;
+               break;
+       case 3:
+               cfg |= GSC_OUT_YUV420_3P;
+               break;
+       };
+
+end_set:
+       writel(cfg, dev->regs + GSC_OUT_CON);
+}
+
+void gsc_hw_set_prescaler(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_scaler *sc = &ctx->scaler;
+       u32 cfg;
+
+       cfg = GSC_PRESC_SHFACTOR(sc->pre_shfactor);
+       cfg |= GSC_PRESC_H_RATIO(sc->pre_hratio);
+       cfg |= GSC_PRESC_V_RATIO(sc->pre_vratio);
+       writel(cfg, dev->regs + GSC_PRE_SCALE_RATIO);
+}
+
+void gsc_hw_set_mainscaler(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_scaler *sc = &ctx->scaler;
+       u32 cfg;
+
+       cfg = GSC_MAIN_H_RATIO_VALUE(sc->main_hratio);
+       writel(cfg, dev->regs + GSC_MAIN_H_RATIO);
+
+       cfg = GSC_MAIN_V_RATIO_VALUE(sc->main_vratio);
+       writel(cfg, dev->regs + GSC_MAIN_V_RATIO);
+}
+
+void gsc_hw_set_rotation(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_IN_CON);
+       cfg &= ~GSC_IN_ROT_MASK;
+
+       switch (ctx->gsc_ctrls.rotate->val) {
+       case 270:
+               cfg |= GSC_IN_ROT_270;
+               break;
+       case 180:
+               cfg |= GSC_IN_ROT_180;
+               break;
+       case 90:
+               if (ctx->gsc_ctrls.hflip->val)
+                       cfg |= GSC_IN_ROT_90_XFLIP;
+               else if (ctx->gsc_ctrls.vflip->val)
+                       cfg |= GSC_IN_ROT_90_YFLIP;
+               else
+                       cfg |= GSC_IN_ROT_90;
+               break;
+       case 0:
+               if (ctx->gsc_ctrls.hflip->val)
+                       cfg |= GSC_IN_ROT_XFLIP;
+               else if (ctx->gsc_ctrls.vflip->val)
+                       cfg |= GSC_IN_ROT_YFLIP;
+       }
+
+       writel(cfg, dev->regs + GSC_IN_CON);
+}
+
+void gsc_hw_set_global_alpha(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       struct gsc_frame *frame = &ctx->d_frame;
+       u32 cfg;
+
+       if (!is_rgb(frame->fmt->color)) {
+               pr_debug("Not a RGB format");
+               return;
+       }
+
+       cfg = readl(dev->regs + GSC_OUT_CON);
+       cfg &= ~GSC_OUT_GLOBAL_ALPHA_MASK;
+
+       cfg |= GSC_OUT_GLOBAL_ALPHA(ctx->gsc_ctrls.global_alpha->val);
+       writel(cfg, dev->regs + GSC_OUT_CON);
+}
+
+void gsc_hw_set_sfr_update(struct gsc_ctx *ctx)
+{
+       struct gsc_dev *dev = ctx->gsc_dev;
+       u32 cfg;
+
+       cfg = readl(dev->regs + GSC_ENABLE);
+       cfg |= GSC_ENABLE_SFR_UPDATE;
+       writel(cfg, dev->regs + GSC_ENABLE);
+}
diff --git a/drivers/media/platform/exynos-gsc/gsc-regs.h b/drivers/media/platform/exynos-gsc/gsc-regs.h
new file mode 100644 (file)
index 0000000..533e994
--- /dev/null
@@ -0,0 +1,172 @@
+/*
+ * Copyright (c) 2011 - 2012 Samsung Electronics Co., Ltd.
+ *             http://www.samsung.com
+ *
+ * Register definition file for Samsung G-Scaler driver
+ *
+ * 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.
+ */
+
+#ifndef REGS_GSC_H_
+#define REGS_GSC_H_
+
+/* G-Scaler enable */
+#define GSC_ENABLE                     0x00
+#define GSC_ENABLE_OP_STATUS           (1 << 2)
+#define GSC_ENABLE_SFR_UPDATE          (1 << 1)
+#define GSC_ENABLE_ON                  (1 << 0)
+
+/* G-Scaler S/W reset */
+#define GSC_SW_RESET                   0x04
+#define GSC_SW_RESET_SRESET            (1 << 0)
+
+/* G-Scaler IRQ */
+#define GSC_IRQ                                0x08
+#define GSC_IRQ_STATUS_OR_IRQ          (1 << 17)
+#define GSC_IRQ_STATUS_FRM_DONE_IRQ    (1 << 16)
+#define GSC_IRQ_FRMDONE_MASK           (1 << 1)
+#define GSC_IRQ_ENABLE                 (1 << 0)
+
+/* G-Scaler input control */
+#define GSC_IN_CON                     0x10
+#define GSC_IN_ROT_MASK                        (7 << 16)
+#define GSC_IN_ROT_270                 (7 << 16)
+#define GSC_IN_ROT_90_YFLIP            (6 << 16)
+#define GSC_IN_ROT_90_XFLIP            (5 << 16)
+#define GSC_IN_ROT_90                  (4 << 16)
+#define GSC_IN_ROT_180                 (3 << 16)
+#define GSC_IN_ROT_YFLIP               (2 << 16)
+#define GSC_IN_ROT_XFLIP               (1 << 16)
+#define GSC_IN_RGB_TYPE_MASK           (3 << 14)
+#define GSC_IN_RGB_HD_WIDE             (3 << 14)
+#define GSC_IN_RGB_HD_NARROW           (2 << 14)
+#define GSC_IN_RGB_SD_WIDE             (1 << 14)
+#define GSC_IN_RGB_SD_NARROW           (0 << 14)
+#define GSC_IN_YUV422_1P_ORDER_MASK    (1 << 13)
+#define GSC_IN_YUV422_1P_ORDER_LSB_Y   (0 << 13)
+#define GSC_IN_YUV422_1P_OEDER_LSB_C   (1 << 13)
+#define GSC_IN_CHROMA_ORDER_MASK       (1 << 12)
+#define GSC_IN_CHROMA_ORDER_CBCR       (0 << 12)
+#define GSC_IN_CHROMA_ORDER_CRCB       (1 << 12)
+#define GSC_IN_FORMAT_MASK             (7 << 8)
+#define GSC_IN_XRGB8888                        (0 << 8)
+#define GSC_IN_RGB565                  (1 << 8)
+#define GSC_IN_YUV420_2P               (2 << 8)
+#define GSC_IN_YUV420_3P               (3 << 8)
+#define GSC_IN_YUV422_1P               (4 << 8)
+#define GSC_IN_YUV422_2P               (5 << 8)
+#define GSC_IN_YUV422_3P               (6 << 8)
+#define GSC_IN_TILE_TYPE_MASK          (1 << 4)
+#define GSC_IN_TILE_C_16x8             (0 << 4)
+#define GSC_IN_TILE_MODE               (1 << 3)
+#define GSC_IN_LOCAL_SEL_MASK          (3 << 1)
+#define GSC_IN_PATH_MASK               (1 << 0)
+#define GSC_IN_PATH_MEMORY             (0 << 0)
+
+/* G-Scaler source image size */
+#define GSC_SRCIMG_SIZE                        0x14
+#define GSC_SRCIMG_HEIGHT(x)           ((x) << 16)
+#define GSC_SRCIMG_WIDTH(x)            ((x) << 0)
+
+/* G-Scaler source image offset */
+#define GSC_SRCIMG_OFFSET              0x18
+#define GSC_SRCIMG_OFFSET_Y(x)         ((x) << 16)
+#define GSC_SRCIMG_OFFSET_X(x)         ((x) << 0)
+
+/* G-Scaler cropped source image size */
+#define GSC_CROPPED_SIZE               0x1c
+#define GSC_CROPPED_HEIGHT(x)          ((x) << 16)
+#define GSC_CROPPED_WIDTH(x)           ((x) << 0)
+
+/* G-Scaler output control */
+#define GSC_OUT_CON                    0x20
+#define GSC_OUT_GLOBAL_ALPHA_MASK      (0xff << 24)
+#define GSC_OUT_GLOBAL_ALPHA(x)                ((x) << 24)
+#define GSC_OUT_RGB_TYPE_MASK          (3 << 10)
+#define GSC_OUT_RGB_HD_NARROW          (3 << 10)
+#define GSC_OUT_RGB_HD_WIDE            (2 << 10)
+#define GSC_OUT_RGB_SD_NARROW          (1 << 10)
+#define GSC_OUT_RGB_SD_WIDE            (0 << 10)
+#define GSC_OUT_YUV422_1P_ORDER_MASK   (1 << 9)
+#define GSC_OUT_YUV422_1P_ORDER_LSB_Y  (0 << 9)
+#define GSC_OUT_YUV422_1P_OEDER_LSB_C  (1 << 9)
+#define GSC_OUT_CHROMA_ORDER_MASK      (1 << 8)
+#define GSC_OUT_CHROMA_ORDER_CBCR      (0 << 8)
+#define GSC_OUT_CHROMA_ORDER_CRCB      (1 << 8)
+#define GSC_OUT_FORMAT_MASK            (7 << 4)
+#define GSC_OUT_XRGB8888               (0 << 4)
+#define GSC_OUT_RGB565                 (1 << 4)
+#define GSC_OUT_YUV420_2P              (2 << 4)
+#define GSC_OUT_YUV420_3P              (3 << 4)
+#define GSC_OUT_YUV422_1P              (4 << 4)
+#define GSC_OUT_YUV422_2P              (5 << 4)
+#define GSC_OUT_YUV444                 (7 << 4)
+#define GSC_OUT_TILE_TYPE_MASK         (1 << 2)
+#define GSC_OUT_TILE_C_16x8            (0 << 2)
+#define GSC_OUT_TILE_MODE              (1 << 1)
+#define GSC_OUT_PATH_MASK              (1 << 0)
+#define GSC_OUT_PATH_LOCAL             (1 << 0)
+#define GSC_OUT_PATH_MEMORY            (0 << 0)
+
+/* G-Scaler scaled destination image size */
+#define GSC_SCALED_SIZE                        0x24
+#define GSC_SCALED_HEIGHT(x)           ((x) << 16)
+#define GSC_SCALED_WIDTH(x)            ((x) << 0)
+
+/* G-Scaler pre scale ratio */
+#define GSC_PRE_SCALE_RATIO            0x28
+#define GSC_PRESC_SHFACTOR(x)          ((x) << 28)
+#define GSC_PRESC_V_RATIO(x)           ((x) << 16)
+#define GSC_PRESC_H_RATIO(x)           ((x) << 0)
+
+/* G-Scaler main scale horizontal ratio */
+#define GSC_MAIN_H_RATIO               0x2c
+#define GSC_MAIN_H_RATIO_VALUE(x)      ((x) << 0)
+
+/* G-Scaler main scale vertical ratio */
+#define GSC_MAIN_V_RATIO               0x30
+#define GSC_MAIN_V_RATIO_VALUE(x)      ((x) << 0)
+
+/* G-Scaler destination image size */
+#define GSC_DSTIMG_SIZE                        0x40
+#define GSC_DSTIMG_HEIGHT(x)           ((x) << 16)
+#define GSC_DSTIMG_WIDTH(x)            ((x) << 0)
+
+/* G-Scaler destination image offset */
+#define GSC_DSTIMG_OFFSET              0x44
+#define GSC_DSTIMG_OFFSET_Y(x)         ((x) << 16)
+#define GSC_DSTIMG_OFFSET_X(x)         ((x) << 0)
+
+/* G-Scaler input y address mask */
+#define GSC_IN_BASE_ADDR_Y_MASK                0x4c
+/* G-Scaler input y base address */
+#define GSC_IN_BASE_ADDR_Y(n)          (0x50 + (n) * 0x4)
+
+/* G-Scaler input cb address mask */
+#define GSC_IN_BASE_ADDR_CB_MASK       0x7c
+/* G-Scaler input cb base address */
+#define GSC_IN_BASE_ADDR_CB(n)         (0x80 + (n) * 0x4)
+
+/* G-Scaler input cr address mask */
+#define GSC_IN_BASE_ADDR_CR_MASK       0xac
+/* G-Scaler input cr base address */
+#define GSC_IN_BASE_ADDR_CR(n)         (0xb0 + (n) * 0x4)
+
+/* G-Scaler output y address mask */
+#define GSC_OUT_BASE_ADDR_Y_MASK       0x10c
+/* G-Scaler output y base address */
+#define GSC_OUT_BASE_ADDR_Y(n)         (0x110 + (n) * 0x4)
+
+/* G-Scaler output cb address mask */
+#define GSC_OUT_BASE_ADDR_CB_MASK      0x15c
+/* G-Scaler output cb base address */
+#define GSC_OUT_BASE_ADDR_CB(n)                (0x160 + (n) * 0x4)
+
+/* G-Scaler output cr address mask */
+#define GSC_OUT_BASE_ADDR_CR_MASK      0x1ac
+/* G-Scaler output cr base address */
+#define GSC_OUT_BASE_ADDR_CR(n)                (0x1b0 + (n) * 0x4)
+
+#endif /* REGS_GSC_H_ */
similarity index 98%
rename from drivers/media/video/fsl-viu.c
rename to drivers/media/platform/fsl-viu.c
index 777486f7cadb65761e25d393e1c16f043426eaea..31ac4dc692475a5b5f1339941617569fd936f43e 100644 (file)
@@ -860,11 +860,11 @@ int vidioc_g_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg)
        return 0;
 }
 
-int vidioc_s_fbuf(struct file *file, void *priv, struct v4l2_framebuffer *arg)
+int vidioc_s_fbuf(struct file *file, void *priv, const struct v4l2_framebuffer *arg)
 {
        struct viu_fh  *fh = priv;
        struct viu_dev *dev = fh->dev;
-       struct v4l2_framebuffer *fb = arg;
+       const struct v4l2_framebuffer *fb = arg;
        struct viu_fmt *fmt;
 
        if (!capable(CAP_SYS_ADMIN) && !capable(CAP_SYS_RAWIO))
@@ -1279,10 +1279,16 @@ static int viu_open(struct file *file)
        dprintk(1, "open minor=%d type=%s users=%d\n", minor,
                v4l2_type_names[V4L2_BUF_TYPE_VIDEO_CAPTURE], dev->users);
 
+       if (mutex_lock_interruptible(&dev->lock)) {
+               dev->users--;
+               return -ERESTARTSYS;
+       }
+
        /* allocate and initialize per filehandle data */
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
        if (!fh) {
                dev->users--;
+               mutex_unlock(&dev->lock);
                return -ENOMEM;
        }
 
@@ -1325,6 +1331,7 @@ static int viu_open(struct file *file)
                                       fh->type, V4L2_FIELD_INTERLACED,
                                       sizeof(struct viu_buf), fh,
                                       &fh->dev->lock);
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -1340,9 +1347,12 @@ static ssize_t viu_read(struct file *file, char __user *data, size_t count,
                dev->ovenable = 0;
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
                viu_start_dma(dev);
                ret = videobuf_read_stream(&fh->vb_vidq, data, count,
                                ppos, 0, file->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
                return ret;
        }
        return 0;
@@ -1352,11 +1362,16 @@ static unsigned int viu_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct viu_fh *fh = file->private_data;
        struct videobuf_queue *q = &fh->vb_vidq;
+       struct viu_dev *dev = fh->dev;
+       unsigned int res;
 
        if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
                return POLLERR;
 
-       return videobuf_poll_stream(file, q, wait);
+       mutex_lock(&dev->lock);
+       res = videobuf_poll_stream(file, q, wait);
+       mutex_unlock(&dev->lock);
+       return res;
 }
 
 static int viu_release(struct file *file)
@@ -1365,9 +1380,11 @@ static int viu_release(struct file *file)
        struct viu_dev *dev = fh->dev;
        int minor = video_devdata(file)->minor;
 
+       mutex_lock(&dev->lock);
        viu_stop_dma(dev);
        videobuf_stop(&fh->vb_vidq);
        videobuf_mmap_free(&fh->vb_vidq);
+       mutex_unlock(&dev->lock);
 
        kfree(fh);
 
@@ -1394,11 +1411,15 @@ void viu_reset(struct viu_reg *reg)
 static int viu_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct viu_fh *fh = file->private_data;
+       struct viu_dev *dev = fh->dev;
        int ret;
 
        dprintk(1, "mmap called, vma=0x%08lx\n", (unsigned long)vma);
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
 
        dprintk(1, "vma start=0x%08lx, size=%ld, ret=%d\n",
                (unsigned long)vma->vm_start,
@@ -1544,10 +1565,6 @@ static int __devinit viu_of_probe(struct platform_device *op)
 
        /* initialize locks */
        mutex_init(&viu_dev->lock);
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &viu_dev->vdev->flags);
        viu_dev->vdev->lock = &viu_dev->lock;
        spin_lock_init(&viu_dev->slock);
 
diff --git a/drivers/media/platform/m2m-deinterlace.c b/drivers/media/platform/m2m-deinterlace.c
new file mode 100644 (file)
index 0000000..45164c4
--- /dev/null
@@ -0,0 +1,1124 @@
+/*
+ * V4L2 deinterlacing support.
+ *
+ * Copyright (c) 2012 Vista Silicon S.L.
+ * Javier Martin <javier.martin@vista-silicon.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
+ */
+
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/interrupt.h>
+#include <linux/dmaengine.h>
+#include <linux/platform_device.h>
+
+#include <media/v4l2-mem2mem.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ioctl.h>
+#include <media/videobuf2-dma-contig.h>
+
+#define MEM2MEM_TEST_MODULE_NAME "mem2mem-deinterlace"
+
+MODULE_DESCRIPTION("mem2mem device which supports deinterlacing using dmaengine");
+MODULE_AUTHOR("Javier Martin <javier.martin@vista-silicon.com");
+MODULE_LICENSE("GPL");
+MODULE_VERSION("0.0.1");
+
+static bool debug = true;
+module_param(debug, bool, 0644);
+
+/* Flags that indicate a format can be used for capture/output */
+#define MEM2MEM_CAPTURE        (1 << 0)
+#define MEM2MEM_OUTPUT (1 << 1)
+
+#define MEM2MEM_NAME           "m2m-deinterlace"
+
+#define dprintk(dev, fmt, arg...) \
+       v4l2_dbg(1, debug, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
+
+struct deinterlace_fmt {
+       char    *name;
+       u32     fourcc;
+       /* Types the format can be used for */
+       u32     types;
+};
+
+static struct deinterlace_fmt formats[] = {
+       {
+               .name   = "YUV 4:2:0 Planar",
+               .fourcc = V4L2_PIX_FMT_YUV420,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       },
+       {
+               .name   = "YUYV 4:2:2",
+               .fourcc = V4L2_PIX_FMT_YUYV,
+               .types  = MEM2MEM_CAPTURE | MEM2MEM_OUTPUT,
+       },
+};
+
+#define NUM_FORMATS ARRAY_SIZE(formats)
+
+/* Per-queue, driver-specific private data */
+struct deinterlace_q_data {
+       unsigned int            width;
+       unsigned int            height;
+       unsigned int            sizeimage;
+       struct deinterlace_fmt  *fmt;
+       enum v4l2_field         field;
+};
+
+enum {
+       V4L2_M2M_SRC = 0,
+       V4L2_M2M_DST = 1,
+};
+
+enum {
+       YUV420_DMA_Y_ODD,
+       YUV420_DMA_Y_EVEN,
+       YUV420_DMA_U_ODD,
+       YUV420_DMA_U_EVEN,
+       YUV420_DMA_V_ODD,
+       YUV420_DMA_V_EVEN,
+       YUV420_DMA_Y_ODD_DOUBLING,
+       YUV420_DMA_U_ODD_DOUBLING,
+       YUV420_DMA_V_ODD_DOUBLING,
+       YUYV_DMA_ODD,
+       YUYV_DMA_EVEN,
+       YUYV_DMA_EVEN_DOUBLING,
+};
+
+/* Source and destination queue data */
+static struct deinterlace_q_data q_data[2];
+
+static struct deinterlace_q_data *get_q_data(enum v4l2_buf_type type)
+{
+       switch (type) {
+       case V4L2_BUF_TYPE_VIDEO_OUTPUT:
+               return &q_data[V4L2_M2M_SRC];
+       case V4L2_BUF_TYPE_VIDEO_CAPTURE:
+               return &q_data[V4L2_M2M_DST];
+       default:
+               BUG();
+       }
+       return NULL;
+}
+
+static struct deinterlace_fmt *find_format(struct v4l2_format *f)
+{
+       struct deinterlace_fmt *fmt;
+       unsigned int k;
+
+       for (k = 0; k < NUM_FORMATS; k++) {
+               fmt = &formats[k];
+               if ((fmt->types & f->type) &&
+                       (fmt->fourcc == f->fmt.pix.pixelformat))
+                       break;
+       }
+
+       if (k == NUM_FORMATS)
+               return NULL;
+
+       return &formats[k];
+}
+
+struct deinterlace_dev {
+       struct v4l2_device      v4l2_dev;
+       struct video_device     *vfd;
+
+       atomic_t                busy;
+       struct mutex            dev_mutex;
+       spinlock_t              irqlock;
+
+       struct dma_chan         *dma_chan;
+
+       struct v4l2_m2m_dev     *m2m_dev;
+       struct vb2_alloc_ctx    *alloc_ctx;
+};
+
+struct deinterlace_ctx {
+       struct deinterlace_dev  *dev;
+
+       /* Abort requested by m2m */
+       int                     aborting;
+       enum v4l2_colorspace    colorspace;
+       dma_cookie_t            cookie;
+       struct v4l2_m2m_ctx     *m2m_ctx;
+       struct dma_interleaved_template *xt;
+};
+
+/*
+ * mem2mem callbacks
+ */
+static int deinterlace_job_ready(void *priv)
+{
+       struct deinterlace_ctx *ctx = priv;
+       struct deinterlace_dev *pcdev = ctx->dev;
+
+       if ((v4l2_m2m_num_src_bufs_ready(ctx->m2m_ctx) > 0)
+           && (v4l2_m2m_num_dst_bufs_ready(ctx->m2m_ctx) > 0)
+           && (atomic_read(&ctx->dev->busy) == 0)) {
+               dprintk(pcdev, "Task ready\n");
+               return 1;
+       }
+
+       dprintk(pcdev, "Task not ready to run\n");
+
+       return 0;
+}
+
+static void deinterlace_job_abort(void *priv)
+{
+       struct deinterlace_ctx *ctx = priv;
+       struct deinterlace_dev *pcdev = ctx->dev;
+
+       ctx->aborting = 1;
+
+       dprintk(pcdev, "Aborting task\n");
+
+       v4l2_m2m_job_finish(pcdev->m2m_dev, ctx->m2m_ctx);
+}
+
+static void deinterlace_lock(void *priv)
+{
+       struct deinterlace_ctx *ctx = priv;
+       struct deinterlace_dev *pcdev = ctx->dev;
+       mutex_lock(&pcdev->dev_mutex);
+}
+
+static void deinterlace_unlock(void *priv)
+{
+       struct deinterlace_ctx *ctx = priv;
+       struct deinterlace_dev *pcdev = ctx->dev;
+       mutex_unlock(&pcdev->dev_mutex);
+}
+
+static void dma_callback(void *data)
+{
+       struct deinterlace_ctx *curr_ctx = data;
+       struct deinterlace_dev *pcdev = curr_ctx->dev;
+       struct vb2_buffer *src_vb, *dst_vb;
+
+       atomic_set(&pcdev->busy, 0);
+
+       src_vb = v4l2_m2m_src_buf_remove(curr_ctx->m2m_ctx);
+       dst_vb = v4l2_m2m_dst_buf_remove(curr_ctx->m2m_ctx);
+
+       v4l2_m2m_buf_done(src_vb, VB2_BUF_STATE_DONE);
+       v4l2_m2m_buf_done(dst_vb, VB2_BUF_STATE_DONE);
+
+       v4l2_m2m_job_finish(pcdev->m2m_dev, curr_ctx->m2m_ctx);
+
+       dprintk(pcdev, "dma transfers completed.\n");
+}
+
+static void deinterlace_issue_dma(struct deinterlace_ctx *ctx, int op,
+                                 int do_callback)
+{
+       struct deinterlace_q_data *s_q_data, *d_q_data;
+       struct vb2_buffer *src_buf, *dst_buf;
+       struct deinterlace_dev *pcdev = ctx->dev;
+       struct dma_chan *chan = pcdev->dma_chan;
+       struct dma_device *dmadev = chan->device;
+       struct dma_async_tx_descriptor *tx;
+       unsigned int s_width, s_height;
+       unsigned int d_width, d_height;
+       unsigned int d_size, s_size;
+       dma_addr_t p_in, p_out;
+       enum dma_ctrl_flags flags;
+
+       src_buf = v4l2_m2m_next_src_buf(ctx->m2m_ctx);
+       dst_buf = v4l2_m2m_next_dst_buf(ctx->m2m_ctx);
+
+       s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       s_width = s_q_data->width;
+       s_height = s_q_data->height;
+       s_size = s_width * s_height;
+
+       d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
+       d_width = d_q_data->width;
+       d_height = d_q_data->height;
+       d_size = d_width * d_height;
+
+       p_in = (dma_addr_t)vb2_dma_contig_plane_dma_addr(src_buf, 0);
+       p_out = (dma_addr_t)vb2_dma_contig_plane_dma_addr(dst_buf, 0);
+       if (!p_in || !p_out) {
+               v4l2_err(&pcdev->v4l2_dev,
+                        "Acquiring kernel pointers to buffers failed\n");
+               return;
+       }
+
+       switch (op) {
+       case YUV420_DMA_Y_ODD:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width;
+               ctx->xt->sgl[0].icg = s_width;
+               ctx->xt->src_start = p_in;
+               ctx->xt->dst_start = p_out;
+               break;
+       case YUV420_DMA_Y_EVEN:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width;
+               ctx->xt->sgl[0].icg = s_width;
+               ctx->xt->src_start = p_in + s_size / 2;
+               ctx->xt->dst_start = p_out + s_width;
+               break;
+       case YUV420_DMA_U_ODD:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + s_size;
+               ctx->xt->dst_start = p_out + s_size;
+               break;
+       case YUV420_DMA_U_EVEN:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + (9 * s_size) / 8;
+               ctx->xt->dst_start = p_out + s_size + s_width / 2;
+               break;
+       case YUV420_DMA_V_ODD:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + (5 * s_size) / 4;
+               ctx->xt->dst_start = p_out + (5 * s_size) / 4;
+               break;
+       case YUV420_DMA_V_EVEN:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + (11 * s_size) / 8;
+               ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
+               break;
+       case YUV420_DMA_Y_ODD_DOUBLING:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width;
+               ctx->xt->sgl[0].icg = s_width;
+               ctx->xt->src_start = p_in;
+               ctx->xt->dst_start = p_out + s_width;
+               break;
+       case YUV420_DMA_U_ODD_DOUBLING:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + s_size;
+               ctx->xt->dst_start = p_out + s_size + s_width / 2;
+               break;
+       case YUV420_DMA_V_ODD_DOUBLING:
+               ctx->xt->numf = s_height / 4;
+               ctx->xt->sgl[0].size = s_width / 2;
+               ctx->xt->sgl[0].icg = s_width / 2;
+               ctx->xt->src_start = p_in + (5 * s_size) / 4;
+               ctx->xt->dst_start = p_out + (5 * s_size) / 4 + s_width / 2;
+               break;
+       case YUYV_DMA_ODD:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width * 2;
+               ctx->xt->sgl[0].icg = s_width * 2;
+               ctx->xt->src_start = p_in;
+               ctx->xt->dst_start = p_out;
+               break;
+       case YUYV_DMA_EVEN:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width * 2;
+               ctx->xt->sgl[0].icg = s_width * 2;
+               ctx->xt->src_start = p_in + s_size;
+               ctx->xt->dst_start = p_out + s_width * 2;
+               break;
+       case YUYV_DMA_EVEN_DOUBLING:
+       default:
+               ctx->xt->numf = s_height / 2;
+               ctx->xt->sgl[0].size = s_width * 2;
+               ctx->xt->sgl[0].icg = s_width * 2;
+               ctx->xt->src_start = p_in;
+               ctx->xt->dst_start = p_out + s_width * 2;
+               break;
+       }
+
+       /* Common parameters for al transfers */
+       ctx->xt->frame_size = 1;
+       ctx->xt->dir = DMA_MEM_TO_MEM;
+       ctx->xt->src_sgl = false;
+       ctx->xt->dst_sgl = true;
+       flags = DMA_CTRL_ACK | DMA_PREP_INTERRUPT |
+               DMA_COMPL_SKIP_DEST_UNMAP | DMA_COMPL_SKIP_SRC_UNMAP;
+
+       tx = dmadev->device_prep_interleaved_dma(chan, ctx->xt, flags);
+       if (tx == NULL) {
+               v4l2_warn(&pcdev->v4l2_dev, "DMA interleaved prep error\n");
+               return;
+       }
+
+       if (do_callback) {
+               tx->callback = dma_callback;
+               tx->callback_param = ctx;
+       }
+
+       ctx->cookie = dmaengine_submit(tx);
+       if (dma_submit_error(ctx->cookie)) {
+               v4l2_warn(&pcdev->v4l2_dev,
+                         "DMA submit error %d with src=0x%x dst=0x%x len=0x%x\n",
+                         ctx->cookie, (unsigned)p_in, (unsigned)p_out,
+                         s_size * 3/2);
+               return;
+       }
+
+       dma_async_issue_pending(chan);
+}
+
+static void deinterlace_device_run(void *priv)
+{
+       struct deinterlace_ctx *ctx = priv;
+       struct deinterlace_q_data *dst_q_data;
+
+       atomic_set(&ctx->dev->busy, 1);
+
+       dprintk(ctx->dev, "%s: DMA try issue.\n", __func__);
+
+       dst_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+       /*
+        * 4 possible field conversions are possible at the moment:
+        *  V4L2_FIELD_SEQ_TB --> V4L2_FIELD_INTERLACED_TB:
+        *      two separate fields in the same input buffer are interlaced
+        *      in the output buffer using weaving. Top field comes first.
+        *  V4L2_FIELD_SEQ_TB --> V4L2_FIELD_NONE:
+        *      top field from the input buffer is copied to the output buffer
+        *      using line doubling. Bottom field from the input buffer is discarded.
+        * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_INTERLACED_BT:
+        *      two separate fields in the same input buffer are interlaced
+        *      in the output buffer using weaving. Bottom field comes first.
+        * V4L2_FIELD_SEQ_BT --> V4L2_FIELD_NONE:
+        *      bottom field from the input buffer is copied to the output buffer
+        *      using line doubling. Top field from the input buffer is discarded.
+        */
+       switch (dst_q_data->fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420:
+               switch (dst_q_data->field) {
+               case V4L2_FIELD_INTERLACED_TB:
+               case V4L2_FIELD_INTERLACED_BT:
+                       dprintk(ctx->dev, "%s: yuv420 interlaced tb.\n",
+                               __func__);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_Y_EVEN, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_U_EVEN, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_V_EVEN, 1);
+                       break;
+               case V4L2_FIELD_NONE:
+               default:
+                       dprintk(ctx->dev, "%s: yuv420 interlaced line doubling.\n",
+                               __func__);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_Y_ODD_DOUBLING, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_U_ODD_DOUBLING, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUV420_DMA_V_ODD_DOUBLING, 1);
+                       break;
+               }
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       default:
+               switch (dst_q_data->field) {
+               case V4L2_FIELD_INTERLACED_TB:
+               case V4L2_FIELD_INTERLACED_BT:
+                       dprintk(ctx->dev, "%s: yuyv interlaced_tb.\n",
+                               __func__);
+                       deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUYV_DMA_EVEN, 1);
+                       break;
+               case V4L2_FIELD_NONE:
+               default:
+                       dprintk(ctx->dev, "%s: yuyv interlaced line doubling.\n",
+                               __func__);
+                       deinterlace_issue_dma(ctx, YUYV_DMA_ODD, 0);
+                       deinterlace_issue_dma(ctx, YUYV_DMA_EVEN_DOUBLING, 1);
+                       break;
+               }
+               break;
+       }
+
+       dprintk(ctx->dev, "%s: DMA issue done.\n", __func__);
+}
+
+/*
+ * video ioctls
+ */
+static int vidioc_querycap(struct file *file, void *priv,
+                          struct v4l2_capability *cap)
+{
+       strlcpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver));
+       strlcpy(cap->card, MEM2MEM_NAME, sizeof(cap->card));
+       strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->card));
+       /*
+        * This is only a mem-to-mem video device. The capture and output
+        * device capability flags are left only for backward compatibility
+        * and are scheduled for removal.
+        */
+       cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_VIDEO_OUTPUT |
+                          V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+
+       return 0;
+}
+
+static int enum_fmt(struct v4l2_fmtdesc *f, u32 type)
+{
+       int i, num;
+       struct deinterlace_fmt *fmt;
+
+       num = 0;
+
+       for (i = 0; i < NUM_FORMATS; ++i) {
+               if (formats[i].types & type) {
+                       /* index-th format of type type found ? */
+                       if (num == f->index)
+                               break;
+                       /* Correct type but haven't reached our index yet,
+                        * just increment per-type index */
+                       ++num;
+               }
+       }
+
+       if (i < NUM_FORMATS) {
+               /* Format found */
+               fmt = &formats[i];
+               strlcpy(f->description, fmt->name, sizeof(f->description));
+               f->pixelformat = fmt->fourcc;
+               return 0;
+       }
+
+       /* Format not found */
+       return -EINVAL;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(f, MEM2MEM_CAPTURE);
+}
+
+static int vidioc_enum_fmt_vid_out(struct file *file, void *priv,
+                                  struct v4l2_fmtdesc *f)
+{
+       return enum_fmt(f, MEM2MEM_OUTPUT);
+}
+
+static int vidioc_g_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
+{
+       struct vb2_queue *vq;
+       struct deinterlace_q_data *q_data;
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(f->type);
+
+       f->fmt.pix.width        = q_data->width;
+       f->fmt.pix.height       = q_data->height;
+       f->fmt.pix.field        = q_data->field;
+       f->fmt.pix.pixelformat  = q_data->fmt->fourcc;
+
+       switch (q_data->fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420:
+               f->fmt.pix.bytesperline = q_data->width * 3 / 2;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       default:
+               f->fmt.pix.bytesperline = q_data->width * 2;
+       }
+
+       f->fmt.pix.sizeimage    = q_data->sizeimage;
+       f->fmt.pix.colorspace   = ctx->colorspace;
+
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return vidioc_g_fmt(priv, f);
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       return vidioc_g_fmt(priv, f);
+}
+
+static int vidioc_try_fmt(struct v4l2_format *f, struct deinterlace_fmt *fmt)
+{
+       switch (f->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       default:
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+       }
+       f->fmt.pix.sizeimage = f->fmt.pix.height * f->fmt.pix.bytesperline;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct deinterlace_fmt *fmt;
+       struct deinterlace_ctx *ctx = priv;
+
+       fmt = find_format(f);
+       if (!fmt || !(fmt->types & MEM2MEM_CAPTURE))
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+       f->fmt.pix.colorspace = ctx->colorspace;
+
+       if (f->fmt.pix.field != V4L2_FIELD_INTERLACED_TB &&
+           f->fmt.pix.field != V4L2_FIELD_INTERLACED_BT &&
+           f->fmt.pix.field != V4L2_FIELD_NONE)
+               f->fmt.pix.field = V4L2_FIELD_INTERLACED_TB;
+
+       return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_try_fmt_vid_out(struct file *file, void *priv,
+                                 struct v4l2_format *f)
+{
+       struct deinterlace_fmt *fmt;
+
+       fmt = find_format(f);
+       if (!fmt || !(fmt->types & MEM2MEM_OUTPUT))
+               f->fmt.pix.pixelformat = V4L2_PIX_FMT_YUV420;
+
+       if (!f->fmt.pix.colorspace)
+               f->fmt.pix.colorspace = V4L2_COLORSPACE_REC709;
+
+       if (f->fmt.pix.field != V4L2_FIELD_SEQ_TB &&
+           f->fmt.pix.field != V4L2_FIELD_SEQ_BT)
+               f->fmt.pix.field = V4L2_FIELD_SEQ_TB;
+
+       return vidioc_try_fmt(f, fmt);
+}
+
+static int vidioc_s_fmt(struct deinterlace_ctx *ctx, struct v4l2_format *f)
+{
+       struct deinterlace_q_data *q_data;
+       struct vb2_queue *vq;
+
+       vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
+       if (!vq)
+               return -EINVAL;
+
+       q_data = get_q_data(f->type);
+       if (!q_data)
+               return -EINVAL;
+
+       if (vb2_is_busy(vq)) {
+               v4l2_err(&ctx->dev->v4l2_dev, "%s queue busy\n", __func__);
+               return -EBUSY;
+       }
+
+       q_data->fmt = find_format(f);
+       if (!q_data->fmt) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "Couldn't set format type %d, wxh: %dx%d. fmt: %d, field: %d\n",
+                       f->type, f->fmt.pix.width, f->fmt.pix.height,
+                       f->fmt.pix.pixelformat, f->fmt.pix.field);
+               return -EINVAL;
+       }
+
+       q_data->width           = f->fmt.pix.width;
+       q_data->height          = f->fmt.pix.height;
+       q_data->field           = f->fmt.pix.field;
+
+       switch (f->fmt.pix.pixelformat) {
+       case V4L2_PIX_FMT_YUV420:
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 3 / 2;
+               q_data->sizeimage = (q_data->width * q_data->height * 3) / 2;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       default:
+               f->fmt.pix.bytesperline = f->fmt.pix.width * 2;
+               q_data->sizeimage = q_data->width * q_data->height * 2;
+       }
+
+       dprintk(ctx->dev,
+               "Setting format for type %d, wxh: %dx%d, fmt: %d, field: %d\n",
+               f->type, q_data->width, q_data->height, q_data->fmt->fourcc,
+               q_data->field);
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       int ret;
+
+       ret = vidioc_try_fmt_vid_cap(file, priv, f);
+       if (ret)
+               return ret;
+       return vidioc_s_fmt(priv, f);
+}
+
+static int vidioc_s_fmt_vid_out(struct file *file, void *priv,
+                               struct v4l2_format *f)
+{
+       struct deinterlace_ctx *ctx = priv;
+       int ret;
+
+       ret = vidioc_try_fmt_vid_out(file, priv, f);
+       if (ret)
+               return ret;
+
+       ret = vidioc_s_fmt(priv, f);
+       if (!ret)
+               ctx->colorspace = f->fmt.pix.colorspace;
+
+       return ret;
+}
+
+static int vidioc_reqbufs(struct file *file, void *priv,
+                         struct v4l2_requestbuffers *reqbufs)
+{
+       struct deinterlace_ctx *ctx = priv;
+
+       return v4l2_m2m_reqbufs(file, ctx->m2m_ctx, reqbufs);
+}
+
+static int vidioc_querybuf(struct file *file, void *priv,
+                          struct v4l2_buffer *buf)
+{
+       struct deinterlace_ctx *ctx = priv;
+
+       return v4l2_m2m_querybuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct deinterlace_ctx *ctx = priv;
+
+       return v4l2_m2m_qbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
+{
+       struct deinterlace_ctx *ctx = priv;
+
+       return v4l2_m2m_dqbuf(file, ctx->m2m_ctx, buf);
+}
+
+static int vidioc_streamon(struct file *file, void *priv,
+                          enum v4l2_buf_type type)
+{
+       struct deinterlace_q_data *s_q_data, *d_q_data;
+       struct deinterlace_ctx *ctx = priv;
+
+       s_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_OUTPUT);
+       d_q_data = get_q_data(V4L2_BUF_TYPE_VIDEO_CAPTURE);
+
+       /* Check that src and dst queues have the same pix format */
+       if (s_q_data->fmt->fourcc != d_q_data->fmt->fourcc) {
+               v4l2_err(&ctx->dev->v4l2_dev,
+                        "src and dst formats don't match.\n");
+               return -EINVAL;
+       }
+
+       /* Check that input and output deinterlacing types are compatible */
+       switch (s_q_data->field) {
+       case V4L2_FIELD_SEQ_BT:
+               if (d_q_data->field != V4L2_FIELD_NONE &&
+                       d_q_data->field != V4L2_FIELD_INTERLACED_BT) {
+                       v4l2_err(&ctx->dev->v4l2_dev,
+                        "src and dst field conversion [(%d)->(%d)] not supported.\n",
+                               s_q_data->field, d_q_data->field);
+                       return -EINVAL;
+               }
+               break;
+       case V4L2_FIELD_SEQ_TB:
+               if (d_q_data->field != V4L2_FIELD_NONE &&
+                       d_q_data->field != V4L2_FIELD_INTERLACED_TB) {
+                       v4l2_err(&ctx->dev->v4l2_dev,
+                        "src and dst field conversion [(%d)->(%d)] not supported.\n",
+                               s_q_data->field, d_q_data->field);
+                       return -EINVAL;
+               }
+               break;
+       default:
+               return -EINVAL;
+       }
+
+       return v4l2_m2m_streamon(file, ctx->m2m_ctx, type);
+}
+
+static int vidioc_streamoff(struct file *file, void *priv,
+                           enum v4l2_buf_type type)
+{
+       struct deinterlace_ctx *ctx = priv;
+
+       return v4l2_m2m_streamoff(file, ctx->m2m_ctx, type);
+}
+
+static const struct v4l2_ioctl_ops deinterlace_ioctl_ops = {
+       .vidioc_querycap        = vidioc_querycap,
+
+       .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap   = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap   = vidioc_s_fmt_vid_cap,
+
+       .vidioc_enum_fmt_vid_out = vidioc_enum_fmt_vid_out,
+       .vidioc_g_fmt_vid_out   = vidioc_g_fmt_vid_out,
+       .vidioc_try_fmt_vid_out = vidioc_try_fmt_vid_out,
+       .vidioc_s_fmt_vid_out   = vidioc_s_fmt_vid_out,
+
+       .vidioc_reqbufs         = vidioc_reqbufs,
+       .vidioc_querybuf        = vidioc_querybuf,
+
+       .vidioc_qbuf            = vidioc_qbuf,
+       .vidioc_dqbuf           = vidioc_dqbuf,
+
+       .vidioc_streamon        = vidioc_streamon,
+       .vidioc_streamoff       = vidioc_streamoff,
+};
+
+
+/*
+ * Queue operations
+ */
+struct vb2_dc_conf {
+       struct device           *dev;
+};
+
+static int deinterlace_queue_setup(struct vb2_queue *vq,
+                               const struct v4l2_format *fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct deinterlace_ctx *ctx = vb2_get_drv_priv(vq);
+       struct deinterlace_q_data *q_data;
+       unsigned int size, count = *nbuffers;
+
+       q_data = get_q_data(vq->type);
+
+       switch (q_data->fmt->fourcc) {
+       case V4L2_PIX_FMT_YUV420:
+               size = q_data->width * q_data->height * 3 / 2;
+               break;
+       case V4L2_PIX_FMT_YUYV:
+       default:
+               size = q_data->width * q_data->height * 2;
+       }
+
+       *nplanes = 1;
+       *nbuffers = count;
+       sizes[0] = size;
+
+       alloc_ctxs[0] = ctx->dev->alloc_ctx;
+
+       dprintk(ctx->dev, "get %d buffer(s) of size %d each.\n", count, size);
+
+       return 0;
+}
+
+static int deinterlace_buf_prepare(struct vb2_buffer *vb)
+{
+       struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       struct deinterlace_q_data *q_data;
+
+       dprintk(ctx->dev, "type: %d\n", vb->vb2_queue->type);
+
+       q_data = get_q_data(vb->vb2_queue->type);
+
+       if (vb2_plane_size(vb, 0) < q_data->sizeimage) {
+               dprintk(ctx->dev, "%s data will not fit into plane (%lu < %lu)\n",
+                       __func__, vb2_plane_size(vb, 0), (long)q_data->sizeimage);
+               return -EINVAL;
+       }
+
+       vb2_set_plane_payload(vb, 0, q_data->sizeimage);
+
+       return 0;
+}
+
+static void deinterlace_buf_queue(struct vb2_buffer *vb)
+{
+       struct deinterlace_ctx *ctx = vb2_get_drv_priv(vb->vb2_queue);
+       v4l2_m2m_buf_queue(ctx->m2m_ctx, vb);
+}
+
+static struct vb2_ops deinterlace_qops = {
+       .queue_setup     = deinterlace_queue_setup,
+       .buf_prepare     = deinterlace_buf_prepare,
+       .buf_queue       = deinterlace_buf_queue,
+};
+
+static int queue_init(void *priv, struct vb2_queue *src_vq,
+                     struct vb2_queue *dst_vq)
+{
+       struct deinterlace_ctx *ctx = priv;
+       int ret;
+
+       src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
+       src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       src_vq->drv_priv = ctx;
+       src_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       src_vq->ops = &deinterlace_qops;
+       src_vq->mem_ops = &vb2_dma_contig_memops;
+       q_data[V4L2_M2M_SRC].fmt = &formats[0];
+       q_data[V4L2_M2M_SRC].width = 640;
+       q_data[V4L2_M2M_SRC].height = 480;
+       q_data[V4L2_M2M_SRC].sizeimage = (640 * 480 * 3) / 2;
+       q_data[V4L2_M2M_SRC].field = V4L2_FIELD_SEQ_TB;
+
+       ret = vb2_queue_init(src_vq);
+       if (ret)
+               return ret;
+
+       dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
+       dst_vq->drv_priv = ctx;
+       dst_vq->buf_struct_size = sizeof(struct v4l2_m2m_buffer);
+       dst_vq->ops = &deinterlace_qops;
+       dst_vq->mem_ops = &vb2_dma_contig_memops;
+       q_data[V4L2_M2M_DST].fmt = &formats[0];
+       q_data[V4L2_M2M_DST].width = 640;
+       q_data[V4L2_M2M_DST].height = 480;
+       q_data[V4L2_M2M_DST].sizeimage = (640 * 480 * 3) / 2;
+       q_data[V4L2_M2M_SRC].field = V4L2_FIELD_INTERLACED_TB;
+
+       return vb2_queue_init(dst_vq);
+}
+
+/*
+ * File operations
+ */
+static int deinterlace_open(struct file *file)
+{
+       struct deinterlace_dev *pcdev = video_drvdata(file);
+       struct deinterlace_ctx *ctx = NULL;
+
+       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       if (!ctx)
+               return -ENOMEM;
+
+       file->private_data = ctx;
+       ctx->dev = pcdev;
+
+       ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
+       if (IS_ERR(ctx->m2m_ctx)) {
+               int ret = PTR_ERR(ctx->m2m_ctx);
+
+               kfree(ctx);
+               return ret;
+       }
+
+       ctx->xt = kzalloc(sizeof(struct dma_async_tx_descriptor) +
+                               sizeof(struct data_chunk), GFP_KERNEL);
+       if (!ctx->xt) {
+               int ret = PTR_ERR(ctx->xt);
+
+               kfree(ctx);
+               return ret;
+       }
+
+       ctx->colorspace = V4L2_COLORSPACE_REC709;
+
+       dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
+
+       return 0;
+}
+
+static int deinterlace_release(struct file *file)
+{
+       struct deinterlace_dev *pcdev = video_drvdata(file);
+       struct deinterlace_ctx *ctx = file->private_data;
+
+       dprintk(pcdev, "Releasing instance %p\n", ctx);
+
+       v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       kfree(ctx->xt);
+       kfree(ctx);
+
+       return 0;
+}
+
+static unsigned int deinterlace_poll(struct file *file,
+                                struct poll_table_struct *wait)
+{
+       struct deinterlace_ctx *ctx = file->private_data;
+       int ret;
+
+       deinterlace_lock(ctx);
+       ret = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       deinterlace_unlock(ctx);
+
+       return ret;
+}
+
+static int deinterlace_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct deinterlace_ctx *ctx = file->private_data;
+
+       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+}
+
+static const struct v4l2_file_operations deinterlace_fops = {
+       .owner          = THIS_MODULE,
+       .open           = deinterlace_open,
+       .release        = deinterlace_release,
+       .poll           = deinterlace_poll,
+       .unlocked_ioctl = video_ioctl2,
+       .mmap           = deinterlace_mmap,
+};
+
+static struct video_device deinterlace_videodev = {
+       .name           = MEM2MEM_NAME,
+       .fops           = &deinterlace_fops,
+       .ioctl_ops      = &deinterlace_ioctl_ops,
+       .minor          = -1,
+       .release        = video_device_release,
+       .vfl_dir        = VFL_DIR_M2M,
+};
+
+static struct v4l2_m2m_ops m2m_ops = {
+       .device_run     = deinterlace_device_run,
+       .job_ready      = deinterlace_job_ready,
+       .job_abort      = deinterlace_job_abort,
+       .lock           = deinterlace_lock,
+       .unlock         = deinterlace_unlock,
+};
+
+static int deinterlace_probe(struct platform_device *pdev)
+{
+       struct deinterlace_dev *pcdev;
+       struct video_device *vfd;
+       dma_cap_mask_t mask;
+       int ret = 0;
+
+       pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+       if (!pcdev)
+               return -ENOMEM;
+
+       spin_lock_init(&pcdev->irqlock);
+
+       dma_cap_zero(mask);
+       dma_cap_set(DMA_INTERLEAVE, mask);
+       pcdev->dma_chan = dma_request_channel(mask, NULL, pcdev);
+       if (!pcdev->dma_chan)
+               goto free_dev;
+
+       if (!dma_has_cap(DMA_INTERLEAVE, pcdev->dma_chan->device->cap_mask)) {
+               v4l2_err(&pcdev->v4l2_dev, "DMA does not support INTERLEAVE\n");
+               goto rel_dma;
+       }
+
+       ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
+       if (ret)
+               goto rel_dma;
+
+       atomic_set(&pcdev->busy, 0);
+       mutex_init(&pcdev->dev_mutex);
+
+       vfd = video_device_alloc();
+       if (!vfd) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to allocate video device\n");
+               ret = -ENOMEM;
+               goto unreg_dev;
+       }
+
+       *vfd = deinterlace_videodev;
+       vfd->lock = &pcdev->dev_mutex;
+
+       ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
+       if (ret) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to register video device\n");
+               goto rel_vdev;
+       }
+
+       video_set_drvdata(vfd, pcdev);
+       snprintf(vfd->name, sizeof(vfd->name), "%s", deinterlace_videodev.name);
+       pcdev->vfd = vfd;
+       v4l2_info(&pcdev->v4l2_dev, MEM2MEM_TEST_MODULE_NAME
+                       " Device registered as /dev/video%d\n", vfd->num);
+
+       platform_set_drvdata(pdev, pcdev);
+
+       pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
+       if (IS_ERR(pcdev->alloc_ctx)) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to alloc vb2 context\n");
+               ret = PTR_ERR(pcdev->alloc_ctx);
+               goto err_ctx;
+       }
+
+       pcdev->m2m_dev = v4l2_m2m_init(&m2m_ops);
+       if (IS_ERR(pcdev->m2m_dev)) {
+               v4l2_err(&pcdev->v4l2_dev, "Failed to init mem2mem device\n");
+               ret = PTR_ERR(pcdev->m2m_dev);
+               goto err_m2m;
+       }
+
+       return 0;
+
+       v4l2_m2m_release(pcdev->m2m_dev);
+err_m2m:
+       video_unregister_device(pcdev->vfd);
+err_ctx:
+       vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
+rel_vdev:
+       video_device_release(vfd);
+unreg_dev:
+       v4l2_device_unregister(&pcdev->v4l2_dev);
+rel_dma:
+       dma_release_channel(pcdev->dma_chan);
+free_dev:
+       kfree(pcdev);
+
+       return ret;
+}
+
+static int deinterlace_remove(struct platform_device *pdev)
+{
+       struct deinterlace_dev *pcdev =
+               (struct deinterlace_dev *)platform_get_drvdata(pdev);
+
+       v4l2_info(&pcdev->v4l2_dev, "Removing " MEM2MEM_TEST_MODULE_NAME);
+       v4l2_m2m_release(pcdev->m2m_dev);
+       video_unregister_device(pcdev->vfd);
+       v4l2_device_unregister(&pcdev->v4l2_dev);
+       vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
+       dma_release_channel(pcdev->dma_chan);
+       kfree(pcdev);
+
+       return 0;
+}
+
+static struct platform_driver deinterlace_pdrv = {
+       .probe          = deinterlace_probe,
+       .remove         = deinterlace_remove,
+       .driver         = {
+               .name   = MEM2MEM_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static void __exit deinterlace_exit(void)
+{
+       platform_driver_unregister(&deinterlace_pdrv);
+}
+
+static int __init deinterlace_init(void)
+{
+       return platform_driver_register(&deinterlace_pdrv);
+}
+
+module_init(deinterlace_init);
+module_exit(deinterlace_exit);
+
similarity index 97%
rename from drivers/media/video/mem2mem_testdev.c
rename to drivers/media/platform/mem2mem_testdev.c
index 0b91a5cd38ebaaba2e940b7cf93244e9e5476f3c..d03637537118047a6ced26241cb55842de398d02 100644 (file)
@@ -70,7 +70,7 @@ MODULE_VERSION("0.1.1");
        v4l2_dbg(1, 1, &dev->v4l2_dev, "%s: " fmt, __func__, ## arg)
 
 
-void m2mtest_dev_release(struct device *dev)
+static void m2mtest_dev_release(struct device *dev)
 {}
 
 static struct platform_device m2mtest_pdev = {
@@ -430,7 +430,8 @@ static int vidioc_querycap(struct file *file, void *priv,
 {
        strncpy(cap->driver, MEM2MEM_NAME, sizeof(cap->driver) - 1);
        strncpy(cap->card, MEM2MEM_NAME, sizeof(cap->card) - 1);
-       strlcpy(cap->bus_info, MEM2MEM_NAME, sizeof(cap->bus_info));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                       "platform:%s", MEM2MEM_NAME);
        cap->device_caps = V4L2_CAP_VIDEO_M2M | V4L2_CAP_STREAMING;
        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
        return 0;
@@ -838,7 +839,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
        struct m2mtest_ctx *ctx = priv;
        int ret;
 
-       memset(src_vq, 0, sizeof(*src_vq));
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
        src_vq->io_modes = VB2_MMAP;
        src_vq->drv_priv = ctx;
@@ -850,7 +850,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq, struct vb2_queue *ds
        if (ret)
                return ret;
 
-       memset(dst_vq, 0, sizeof(*dst_vq));
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        dst_vq->io_modes = VB2_MMAP;
        dst_vq->drv_priv = ctx;
@@ -891,10 +890,15 @@ static int m2mtest_open(struct file *file)
        struct m2mtest_dev *dev = video_drvdata(file);
        struct m2mtest_ctx *ctx = NULL;
        struct v4l2_ctrl_handler *hdl;
+       int rc = 0;
 
+       if (mutex_lock_interruptible(&dev->dev_mutex))
+               return -ERESTARTSYS;
        ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
-       if (!ctx)
-               return -ENOMEM;
+       if (!ctx) {
+               rc = -ENOMEM;
+               goto open_unlock;
+       }
 
        v4l2_fh_init(&ctx->fh, video_devdata(file));
        file->private_data = &ctx->fh;
@@ -906,10 +910,9 @@ static int m2mtest_open(struct file *file)
        v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_time_msec, NULL);
        v4l2_ctrl_new_custom(hdl, &m2mtest_ctrl_trans_num_bufs, NULL);
        if (hdl->error) {
-               int err = hdl->error;
-
+               rc = hdl->error;
                v4l2_ctrl_handler_free(hdl);
-               return err;
+               goto open_unlock;
        }
        ctx->fh.ctrl_handler = hdl;
        v4l2_ctrl_handler_setup(hdl);
@@ -927,11 +930,11 @@ static int m2mtest_open(struct file *file)
        ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
 
        if (IS_ERR(ctx->m2m_ctx)) {
-               int ret = PTR_ERR(ctx->m2m_ctx);
+               rc = PTR_ERR(ctx->m2m_ctx);
 
                v4l2_ctrl_handler_free(hdl);
                kfree(ctx);
-               return ret;
+               goto open_unlock;
        }
 
        v4l2_fh_add(&ctx->fh);
@@ -939,7 +942,9 @@ static int m2mtest_open(struct file *file)
 
        dprintk(dev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 
-       return 0;
+open_unlock:
+       mutex_unlock(&dev->dev_mutex);
+       return rc;
 }
 
 static int m2mtest_release(struct file *file)
@@ -952,7 +957,9 @@ static int m2mtest_release(struct file *file)
        v4l2_fh_del(&ctx->fh);
        v4l2_fh_exit(&ctx->fh);
        v4l2_ctrl_handler_free(&ctx->hdl);
+       mutex_lock(&dev->dev_mutex);
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       mutex_unlock(&dev->dev_mutex);
        kfree(ctx);
 
        atomic_dec(&dev->num_inst);
@@ -970,9 +977,15 @@ static unsigned int m2mtest_poll(struct file *file,
 
 static int m2mtest_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct m2mtest_dev *dev = video_drvdata(file);
        struct m2mtest_ctx *ctx = file2ctx(file);
+       int res;
 
-       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       if (mutex_lock_interruptible(&dev->dev_mutex))
+               return -ERESTARTSYS;
+       res = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&dev->dev_mutex);
+       return res;
 }
 
 static const struct v4l2_file_operations m2mtest_fops = {
@@ -986,6 +999,7 @@ static const struct v4l2_file_operations m2mtest_fops = {
 
 static struct video_device m2mtest_videodev = {
        .name           = MEM2MEM_NAME,
+       .vfl_dir        = VFL_DIR_M2M,
        .fops           = &m2mtest_fops,
        .ioctl_ops      = &m2mtest_ioctl_ops,
        .minor          = -1,
@@ -1027,10 +1041,6 @@ static int m2mtest_probe(struct platform_device *pdev)
        }
 
        *vfd = m2mtest_videodev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->lock = &dev->dev_mutex;
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
similarity index 94%
rename from drivers/media/video/mx2_emmaprp.c
rename to drivers/media/platform/mx2_emmaprp.c
index 5f8a6f5b98f91c3af4e1bdbd06654e7b496d8d65..8f22ce543cf704315399b751371d79f8dfbd2c6e 100644 (file)
@@ -209,7 +209,7 @@ struct emmaprp_dev {
 
        int                     irq_emma;
        void __iomem            *base_emma;
-       struct clk              *clk_emma;
+       struct clk              *clk_emma_ahb, *clk_emma_ipg;
        struct resource         *res_emma;
 
        struct v4l2_m2m_dev     *m2m_dev;
@@ -757,7 +757,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        struct emmaprp_ctx *ctx = priv;
        int ret;
 
-       memset(src_vq, 0, sizeof(*src_vq));
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        src_vq->drv_priv = ctx;
@@ -769,7 +768,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        if (ret)
                return ret;
 
-       memset(dst_vq, 0, sizeof(*dst_vq));
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        dst_vq->drv_priv = ctx;
@@ -795,18 +793,26 @@ static int emmaprp_open(struct file *file)
        file->private_data = ctx;
        ctx->dev = pcdev;
 
+       if (mutex_lock_interruptible(&pcdev->dev_mutex)) {
+               kfree(ctx);
+               return -ERESTARTSYS;
+       }
+
        ctx->m2m_ctx = v4l2_m2m_ctx_init(pcdev->m2m_dev, ctx, &queue_init);
 
        if (IS_ERR(ctx->m2m_ctx)) {
                int ret = PTR_ERR(ctx->m2m_ctx);
 
+               mutex_unlock(&pcdev->dev_mutex);
                kfree(ctx);
                return ret;
        }
 
-       clk_enable(pcdev->clk_emma);
+       clk_prepare_enable(pcdev->clk_emma_ipg);
+       clk_prepare_enable(pcdev->clk_emma_ahb);
        ctx->q_data[V4L2_M2M_SRC].fmt = &formats[1];
        ctx->q_data[V4L2_M2M_DST].fmt = &formats[0];
+       mutex_unlock(&pcdev->dev_mutex);
 
        dprintk(pcdev, "Created instance %p, m2m_ctx: %p\n", ctx, ctx->m2m_ctx);
 
@@ -820,8 +826,11 @@ static int emmaprp_release(struct file *file)
 
        dprintk(pcdev, "Releasing instance %p\n", ctx);
 
-       clk_disable(pcdev->clk_emma);
+       mutex_lock(&pcdev->dev_mutex);
+       clk_disable_unprepare(pcdev->clk_emma_ahb);
+       clk_disable_unprepare(pcdev->clk_emma_ipg);
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       mutex_unlock(&pcdev->dev_mutex);
        kfree(ctx);
 
        return 0;
@@ -830,16 +839,27 @@ static int emmaprp_release(struct file *file)
 static unsigned int emmaprp_poll(struct file *file,
                                 struct poll_table_struct *wait)
 {
+       struct emmaprp_dev *pcdev = video_drvdata(file);
        struct emmaprp_ctx *ctx = file->private_data;
+       unsigned int res;
 
-       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_lock(&pcdev->dev_mutex);
+       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_unlock(&pcdev->dev_mutex);
+       return res;
 }
 
 static int emmaprp_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct emmaprp_dev *pcdev = video_drvdata(file);
        struct emmaprp_ctx *ctx = file->private_data;
+       int ret;
 
-       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       if (mutex_lock_interruptible(&pcdev->dev_mutex))
+               return -ERESTARTSYS;
+       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&pcdev->dev_mutex);
+       return ret;
 }
 
 static const struct v4l2_file_operations emmaprp_fops = {
@@ -857,6 +877,7 @@ static struct video_device emmaprp_videodev = {
        .ioctl_ops      = &emmaprp_ioctl_ops,
        .minor          = -1,
        .release        = video_device_release,
+       .vfl_dir        = VFL_DIR_M2M,
 };
 
 static struct v4l2_m2m_ops m2m_ops = {
@@ -874,29 +895,31 @@ static int emmaprp_probe(struct platform_device *pdev)
        int irq_emma;
        int ret;
 
-       pcdev = kzalloc(sizeof *pcdev, GFP_KERNEL);
+       pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
        if (!pcdev)
                return -ENOMEM;
 
        spin_lock_init(&pcdev->irqlock);
 
-       pcdev->clk_emma = clk_get(&pdev->dev, NULL);
-       if (IS_ERR(pcdev->clk_emma)) {
-               ret = PTR_ERR(pcdev->clk_emma);
-               goto free_dev;
+       pcdev->clk_emma_ipg = devm_clk_get(&pdev->dev, "ipg");
+       if (IS_ERR(pcdev->clk_emma_ipg)) {
+               return PTR_ERR(pcdev->clk_emma_ipg);
        }
 
+       pcdev->clk_emma_ahb = devm_clk_get(&pdev->dev, "ahb");
+       if (IS_ERR(pcdev->clk_emma_ahb))
+               return PTR_ERR(pcdev->clk_emma_ahb);
+
        irq_emma = platform_get_irq(pdev, 0);
        res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (irq_emma < 0 || res_emma == NULL) {
                dev_err(&pdev->dev, "Missing platform resources data\n");
-               ret = -ENODEV;
-               goto free_clk;
+               return -ENODEV;
        }
 
        ret = v4l2_device_register(&pdev->dev, &pcdev->v4l2_dev);
        if (ret)
-               goto free_clk;
+               return ret;
 
        mutex_init(&pcdev->dev_mutex);
 
@@ -908,10 +931,6 @@ static int emmaprp_probe(struct platform_device *pdev)
        }
 
        *vfd = emmaprp_videodev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->lock = &pcdev->dev_mutex;
 
        video_set_drvdata(vfd, pcdev);
@@ -922,21 +941,20 @@ static int emmaprp_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, pcdev);
 
-       if (devm_request_mem_region(&pdev->dev, res_emma->start,
-           resource_size(res_emma), MEM2MEM_NAME) == NULL)
-               goto rel_vdev;
-
-       pcdev->base_emma = devm_ioremap(&pdev->dev, res_emma->start,
-                                       resource_size(res_emma));
-       if (!pcdev->base_emma)
+       pcdev->base_emma = devm_request_and_ioremap(&pdev->dev, res_emma);
+       if (!pcdev->base_emma) {
+               ret = -ENXIO;
                goto rel_vdev;
+       }
 
        pcdev->irq_emma = irq_emma;
        pcdev->res_emma = res_emma;
 
        if (devm_request_irq(&pdev->dev, pcdev->irq_emma, emmaprp_irq,
-                            0, MEM2MEM_NAME, pcdev) < 0)
+                            0, MEM2MEM_NAME, pcdev) < 0) {
+               ret = -ENODEV;
                goto rel_vdev;
+       }
 
        pcdev->alloc_ctx = vb2_dma_contig_init_ctx(&pdev->dev);
        if (IS_ERR(pcdev->alloc_ctx)) {
@@ -969,10 +987,6 @@ rel_vdev:
        video_device_release(vfd);
 unreg_dev:
        v4l2_device_unregister(&pcdev->v4l2_dev);
-free_clk:
-       clk_put(pcdev->clk_emma);
-free_dev:
-       kfree(pcdev);
 
        return ret;
 }
@@ -987,8 +1001,6 @@ static int emmaprp_remove(struct platform_device *pdev)
        v4l2_m2m_release(pcdev->m2m_dev);
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
        v4l2_device_unregister(&pcdev->v4l2_dev);
-       clk_put(pcdev->clk_emma);
-       kfree(pcdev);
 
        return 0;
 }
similarity index 81%
rename from drivers/media/video/omap/Makefile
rename to drivers/media/platform/omap/Makefile
index fc410b438f7d6545b2d35ce19e9fb0cdf43e2333..d80df41fde2816c993b163a35c06d854ad063320 100644 (file)
@@ -3,6 +3,6 @@
 #
 
 # OMAP2/3 Display driver
-omap-vout-y := omap_vout.o omap_voutlib.o
+omap-vout-y += omap_vout.o omap_voutlib.o
 omap-vout-$(CONFIG_VIDEO_OMAP2_VOUT_VRFB) += omap_vout_vrfb.o
 obj-$(CONFIG_VIDEO_OMAP2_VOUT) += omap-vout.o
similarity index 99%
rename from drivers/media/video/omap/omap_vout.c
rename to drivers/media/platform/omap/omap_vout.c
index 88cf9d952631719293b48093459f9e74ac7cd762..196e5167005081f5d3c424928a3e71b83274fded 100644 (file)
@@ -1291,7 +1291,7 @@ static int vidioc_g_crop(struct file *file, void *fh, struct v4l2_crop *crop)
        return 0;
 }
 
-static int vidioc_s_crop(struct file *file, void *fh, struct v4l2_crop *crop)
+static int vidioc_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        int ret = -EINVAL;
        struct omap_vout_device *vout = fh;
@@ -1744,7 +1744,7 @@ static int vidioc_streamoff(struct file *file, void *fh, enum v4l2_buf_type i)
 }
 
 static int vidioc_s_fbuf(struct file *file, void *fh,
-                               struct v4l2_framebuffer *a)
+                               const struct v4l2_framebuffer *a)
 {
        int enable = 0;
        struct omap_overlay *ovl;
@@ -1951,6 +1951,7 @@ static int __init omap_vout_setup_video_data(struct omap_vout_device *vout)
 
        vfd->fops = &omap_vout_fops;
        vfd->v4l2_dev = &vout->vid_dev->v4l2_dev;
+       vfd->vfl_dir = VFL_DIR_TX;
        mutex_init(&vout->lock);
 
        vfd->minor = -1;
similarity index 99%
rename from drivers/media/video/omap24xxcam-dma.c
rename to drivers/media/platform/omap24xxcam-dma.c
index b5ae170de4a529e814b49ce824ec9cb7cd22c400..9c00776d658331a052641c043b7b3a2146fb2089 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/omap24xxcam-dma.c
+ * drivers/media/platform/omap24xxcam-dma.c
  *
  * Copyright (C) 2004 MontaVista Software, Inc.
  * Copyright (C) 2004 Texas Instruments.
similarity index 99%
rename from drivers/media/video/omap24xxcam.c
rename to drivers/media/platform/omap24xxcam.c
index e5015b0d5508cec9bd9af486c734fef3ff478179..fde2e66f6f332e3a4f7800f1b8570fe9a039a033 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/omap24xxcam.c
+ * drivers/media/platform/omap24xxcam.c
  *
  * OMAP 2 camera block driver.
  *
similarity index 99%
rename from drivers/media/video/omap24xxcam.h
rename to drivers/media/platform/omap24xxcam.h
index d59727afe8946252d8d3f81e7b67f93e93b7710e..c4395956a493a3a60ee2961407670573f1f9ef39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/omap24xxcam.h
+ * drivers/media/platform/omap24xxcam.h
  *
  * Copyright (C) 2004 MontaVista Software, Inc.
  * Copyright (C) 2004 Texas Instruments.
similarity index 91%
rename from drivers/media/video/omap3isp/cfa_coef_table.h
rename to drivers/media/platform/omap3isp/cfa_coef_table.h
index c60df0ed075aae3f42ef43460ce9b51b39b53e46..c84df0706f3e098542d822e8fefc0755b010d836 100644 (file)
@@ -23,7 +23,7 @@
  * 02110-1301 USA
  */
 
-244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
+{ 244, 0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
 248,   0,   0,   0,   0,  40,   0,   0, 244,  12, 250,   4,   0,  27,   0, 250,
 247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
 244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
@@ -31,8 +31,8 @@
 247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
 244,   0, 247,   0,  12,  27,  36, 247, 250,   0,  27,   0,   4, 250,  12, 244,
 248,   0,   0,   0,   0,  40,   0,   0, 244,  12, 250,   4,   0,  27,   0, 250,
-247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248,
-  0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
+247,  36,  27,  12,   0, 247,   0, 244,   0,   0,  40,   0,   0,   0,   0, 248 },
+{ 0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
   0,   0,   0, 248,   0,   0,  40,   0,   4, 250,  12, 244, 250,   0,  27,   0,
  12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
   0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
@@ -40,8 +40,8 @@
  12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
   0, 247,   0, 244, 247,  36,  27,  12,   0,  27,   0, 250, 244,  12, 250,   4,
   0,   0,   0, 248,   0,   0,  40,   0,   4, 250,  12, 244, 250,   0,  27,   0,
- 12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0,
-  4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
+ 12,  27,  36, 247, 244,   0, 247,   0,   0,  40,   0,   0, 248,   0,   0,   0 },
+{ 4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
   0,   0,   0, 248,   0,   0,  40,   0,   0, 247,   0, 244, 247,  36,  27,  12,
   0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
   4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
@@ -49,8 +49,8 @@
   0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
   4, 250,  12, 244, 250,   0,  27,   0,  12,  27,  36, 247, 244,   0, 247,   0,
   0,   0,   0, 248,   0,   0,  40,   0,   0, 247,   0, 244, 247,  36,  27,  12,
-  0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0,
-244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
+  0,  27,   0, 250, 244,  12, 250,   4,   0,  40,   0,   0, 248,   0,   0,   0 },
+{ 244,12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
 248,   0,   0,   0,   0,  40,   0,   0, 244,   0, 247,   0,  12,  27,  36, 247,
 250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248,
 244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
@@ -58,4 +58,4 @@
 250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248,
 244,  12, 250,   4,   0,  27,   0, 250, 247,  36,  27,  12,   0, 247,   0, 244,
 248,   0,   0,   0,   0,  40,   0,   0, 244,   0, 247,   0,  12,  27,  36, 247,
-250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248
+250,   0,  27,   0,   4, 250,  12, 244,   0,   0,  40,   0,   0,   0,   0, 248 },
similarity index 98%
rename from drivers/media/video/omap3isp/isp.c
rename to drivers/media/platform/omap3isp/isp.c
index 1c347633e663b65b1acb561ad6c2e00a868920c2..d7aa513dcc8deace0704b37c5c378968ff558b37 100644 (file)
@@ -252,13 +252,18 @@ static u32 isp_set_xclk(struct isp_device *isp, u32 xclk, u8 xclksel)
 }
 
 /*
- * isp_power_settings - Sysconfig settings, for Power Management.
+ * isp_core_init - ISP core settings
  * @isp: OMAP3 ISP device
  * @idle: Consider idle state.
  *
- * Sets the power settings for the ISP, and SBL bus.
+ * Set the power settings for the ISP and SBL bus and cConfigure the HS/VS
+ * interrupt source.
+ *
+ * We need to configure the HS/VS interrupt source before interrupts get
+ * enabled, as the sensor might be free-running and the ISP default setting
+ * (HS edge) would put an unnecessary burden on the CPU.
  */
-static void isp_power_settings(struct isp_device *isp, int idle)
+static void isp_core_init(struct isp_device *isp, int idle)
 {
        isp_reg_writel(isp,
                       ((idle ? ISP_SYSCONFIG_MIDLEMODE_SMARTSTANDBY :
@@ -268,9 +273,10 @@ static void isp_power_settings(struct isp_device *isp, int idle)
                          ISP_SYSCONFIG_AUTOIDLE : 0),
                       OMAP3_ISP_IOMEM_MAIN, ISP_SYSCONFIG);
 
-       if (isp->autoidle)
-               isp_reg_writel(isp, ISPCTRL_SBL_AUTOIDLE, OMAP3_ISP_IOMEM_MAIN,
-                              ISP_CTRL);
+       isp_reg_writel(isp,
+                      (isp->autoidle ? ISPCTRL_SBL_AUTOIDLE : 0) |
+                      ISPCTRL_SYNC_DETECT_VSRISE,
+                      OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
 }
 
 /*
@@ -287,7 +293,7 @@ static void isp_power_settings(struct isp_device *isp, int idle)
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
                               const struct isp_parallel_platform_data *pdata,
-                              unsigned int shift)
+                              unsigned int shift, unsigned int bridge)
 {
        u32 ispctrl_val;
 
@@ -296,12 +302,12 @@ void omap3isp_configure_bridge(struct isp_device *isp,
        ispctrl_val &= ~ISPCTRL_PAR_CLK_POL_INV;
        ispctrl_val &= ~ISPCTRL_PAR_SER_CLK_SEL_MASK;
        ispctrl_val &= ~ISPCTRL_PAR_BRIDGE_MASK;
+       ispctrl_val |= bridge;
 
        switch (input) {
        case CCDC_INPUT_PARALLEL:
                ispctrl_val |= ISPCTRL_PAR_SER_CLK_SEL_PARALLEL;
                ispctrl_val |= pdata->clk_pol << ISPCTRL_PAR_CLK_POL_SHIFT;
-               ispctrl_val |= pdata->bridge << ISPCTRL_PAR_BRIDGE_SHIFT;
                shift += pdata->data_lane_shift * 2;
                break;
 
@@ -323,9 +329,6 @@ void omap3isp_configure_bridge(struct isp_device *isp,
 
        ispctrl_val |= ((shift/2) << ISPCTRL_SHIFT_SHIFT) & ISPCTRL_SHIFT_MASK;
 
-       ispctrl_val &= ~ISPCTRL_SYNC_DETECT_MASK;
-       ispctrl_val |= ISPCTRL_SYNC_DETECT_VSRISE;
-
        isp_reg_writel(isp, ispctrl_val, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL);
 }
 
@@ -1281,7 +1284,9 @@ static void __isp_subclk_update(struct isp_device *isp)
 {
        u32 clk = 0;
 
-       if (isp->subclk_resources & OMAP3_ISP_SUBCLK_H3A)
+       /* AEWB and AF share the same clock. */
+       if (isp->subclk_resources &
+           (OMAP3_ISP_SUBCLK_AEWB | OMAP3_ISP_SUBCLK_AF))
                clk |= ISPCTRL_H3A_CLK_EN;
 
        if (isp->subclk_resources & OMAP3_ISP_SUBCLK_HIST)
@@ -1441,7 +1446,7 @@ static int isp_get_clocks(struct isp_device *isp)
  *
  * Return a pointer to the ISP device structure, or NULL if an error occurred.
  */
-struct isp_device *omap3isp_get(struct isp_device *isp)
+static struct isp_device *__omap3isp_get(struct isp_device *isp, bool irq)
 {
        struct isp_device *__isp = isp;
 
@@ -1460,10 +1465,9 @@ struct isp_device *omap3isp_get(struct isp_device *isp)
        /* We don't want to restore context before saving it! */
        if (isp->has_context)
                isp_restore_ctx(isp);
-       else
-               isp->has_context = 1;
 
-       isp_enable_interrupts(isp);
+       if (irq)
+               isp_enable_interrupts(isp);
 
 out:
        if (__isp != NULL)
@@ -1473,6 +1477,11 @@ out:
        return __isp;
 }
 
+struct isp_device *omap3isp_get(struct isp_device *isp)
+{
+       return __omap3isp_get(isp, true);
+}
+
 /*
  * omap3isp_put - Release the ISP
  *
@@ -1488,8 +1497,10 @@ void omap3isp_put(struct isp_device *isp)
        BUG_ON(isp->ref_count == 0);
        if (--isp->ref_count == 0) {
                isp_disable_interrupts(isp);
-               if (isp->domain)
+               if (isp->domain) {
                        isp_save_ctx(isp);
+                       isp->has_context = 1;
+               }
                /* Reset the ISP if an entity has failed to stop. This is the
                 * only way to recover from such conditions.
                 */
@@ -1973,7 +1984,7 @@ static int __devexit isp_remove(struct platform_device *pdev)
        isp_unregister_entities(isp);
        isp_cleanup_modules(isp);
 
-       omap3isp_get(isp);
+       __omap3isp_get(isp, false);
        iommu_detach_device(isp->domain, &pdev->dev);
        iommu_domain_free(isp->domain);
        isp->domain = NULL;
@@ -2091,8 +2102,10 @@ static int __devinit isp_probe(struct platform_device *pdev)
        if (ret < 0)
                goto error;
 
-       if (omap3isp_get(isp) == NULL)
+       if (__omap3isp_get(isp, false) == NULL) {
+               ret = -ENODEV;
                goto error;
+       }
 
        ret = isp_reset(isp);
        if (ret < 0)
@@ -2158,7 +2171,7 @@ static int __devinit isp_probe(struct platform_device *pdev)
        if (ret < 0)
                goto error_modules;
 
-       isp_power_settings(isp, 1);
+       isp_core_init(isp, 1);
        omap3isp_put(isp);
 
        return 0;
similarity index 97%
rename from drivers/media/video/omap3isp/isp.h
rename to drivers/media/platform/omap3isp/isp.h
index fc7af3e32efd247bd83b16f5197a8a992913e1e8..8be7487c326f7741b5de7145db939667ead5887f 100644 (file)
@@ -90,10 +90,11 @@ enum isp_sbl_resource {
 
 enum isp_subclk_resource {
        OMAP3_ISP_SUBCLK_CCDC           = (1 << 0),
-       OMAP3_ISP_SUBCLK_H3A            = (1 << 1),
-       OMAP3_ISP_SUBCLK_HIST           = (1 << 2),
-       OMAP3_ISP_SUBCLK_PREVIEW        = (1 << 3),
-       OMAP3_ISP_SUBCLK_RESIZER        = (1 << 4),
+       OMAP3_ISP_SUBCLK_AEWB           = (1 << 1),
+       OMAP3_ISP_SUBCLK_AF             = (1 << 2),
+       OMAP3_ISP_SUBCLK_HIST           = (1 << 3),
+       OMAP3_ISP_SUBCLK_PREVIEW        = (1 << 4),
+       OMAP3_ISP_SUBCLK_RESIZER        = (1 << 5),
 };
 
 /* ISP: OMAP 34xx ES 1.0 */
@@ -235,7 +236,7 @@ int omap3isp_pipeline_set_stream(struct isp_pipeline *pipe,
 void omap3isp_configure_bridge(struct isp_device *isp,
                               enum ccdc_input_entity input,
                               const struct isp_parallel_platform_data *pdata,
-                              unsigned int shift);
+                              unsigned int shift, unsigned int bridge);
 
 struct isp_device *omap3isp_get(struct isp_device *isp);
 void omap3isp_put(struct isp_device *isp);
similarity index 93%
rename from drivers/media/video/omap3isp/ispccdc.c
rename to drivers/media/platform/omap3isp/ispccdc.c
index f1220d3d4970d75fb2dec5c91ce77fc2f01f7aae..60181ab96063ea12be4f0a10f6b02e5a86e29991 100644 (file)
@@ -61,6 +61,8 @@ static const unsigned int ccdc_fmts[] = {
        V4L2_MBUS_FMT_SRGGB12_1X12,
        V4L2_MBUS_FMT_SBGGR12_1X12,
        V4L2_MBUS_FMT_SGBRG12_1X12,
+       V4L2_MBUS_FMT_YUYV8_2X8,
+       V4L2_MBUS_FMT_UYVY8_2X8,
 };
 
 /*
@@ -627,9 +629,12 @@ static void ccdc_configure_lpf(struct isp_ccdc_device *ccdc)
 static void ccdc_configure_alaw(struct isp_ccdc_device *ccdc)
 {
        struct isp_device *isp = to_isp_device(ccdc);
+       const struct isp_format_info *info;
        u32 alaw = 0;
 
-       switch (ccdc->syncif.datsz) {
+       info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
+
+       switch (info->width) {
        case 8:
                return;
 
@@ -813,6 +818,7 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
 {
        struct isp_pipeline *pipe = to_isp_pipeline(&ccdc->subdev.entity);
        struct isp_device *isp = to_isp_device(ccdc);
+       const struct isp_format_info *info;
        unsigned long l3_ick = pipe->l3_ick;
        unsigned int max_div = isp->revision == ISP_REVISION_15_0 ? 64 : 8;
        unsigned int div = 0;
@@ -821,7 +827,9 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
        fmtcfg_vp = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_FMTCFG)
                  & ~(ISPCCDC_FMTCFG_VPIN_MASK | ISPCCDC_FMTCFG_VPIF_FRQ_MASK);
 
-       switch (ccdc->syncif.datsz) {
+       info = omap3isp_video_format_info(ccdc->formats[CCDC_PAD_SINK].code);
+
+       switch (info->width) {
        case 8:
        case 10:
                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_9_0;
@@ -835,7 +843,7 @@ static void ccdc_config_vp(struct isp_ccdc_device *ccdc)
        case 13:
                fmtcfg_vp |= ISPCCDC_FMTCFG_VPIN_12_3;
                break;
-       };
+       }
 
        if (pipe->input)
                div = DIV_ROUND_UP(l3_ick, pipe->max_rate);
@@ -959,26 +967,28 @@ void omap3isp_ccdc_max_rate(struct isp_ccdc_device *ccdc,
 /*
  * ccdc_config_sync_if - Set CCDC sync interface configuration
  * @ccdc: Pointer to ISP CCDC device.
- * @syncif: Structure containing the sync parameters like field state, CCDC in
- *          master/slave mode, raw/yuv data, polarity of data, field, hs, vs
- *          signals.
+ * @pdata: Parallel interface platform data (may be NULL)
+ * @data_size: Data size
  */
 static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
-                               struct ispccdc_syncif *syncif)
+                               struct isp_parallel_platform_data *pdata,
+                               unsigned int data_size)
 {
        struct isp_device *isp = to_isp_device(ccdc);
-       u32 syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC,
-                                    ISPCCDC_SYN_MODE);
+       const struct v4l2_mbus_framefmt *format;
+       u32 syn_mode = ISPCCDC_SYN_MODE_VDHDEN;
 
-       syn_mode |= ISPCCDC_SYN_MODE_VDHDEN;
+       format = &ccdc->formats[CCDC_PAD_SINK];
 
-       if (syncif->fldstat)
-               syn_mode |= ISPCCDC_SYN_MODE_FLDSTAT;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_FLDSTAT;
+       if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+           format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
+               /* The bridge is enabled for YUV8 formats. Configure the input
+                * mode accordingly.
+                */
+               syn_mode |= ISPCCDC_SYN_MODE_INPMOD_YCBCR16;
+       }
 
-       syn_mode &= ~ISPCCDC_SYN_MODE_DATSIZ_MASK;
-       switch (syncif->datsz) {
+       switch (data_size) {
        case 8:
                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_8;
                break;
@@ -991,55 +1001,31 @@ static void ccdc_config_sync_if(struct isp_ccdc_device *ccdc,
        case 12:
                syn_mode |= ISPCCDC_SYN_MODE_DATSIZ_12;
                break;
-       };
-
-       if (syncif->fldmode)
-               syn_mode |= ISPCCDC_SYN_MODE_FLDMODE;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_FLDMODE;
+       }
 
-       if (syncif->datapol)
+       if (pdata && pdata->data_pol)
                syn_mode |= ISPCCDC_SYN_MODE_DATAPOL;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_DATAPOL;
-
-       if (syncif->fldpol)
-               syn_mode |= ISPCCDC_SYN_MODE_FLDPOL;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_FLDPOL;
 
-       if (syncif->hdpol)
+       if (pdata && pdata->hs_pol)
                syn_mode |= ISPCCDC_SYN_MODE_HDPOL;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_HDPOL;
 
-       if (syncif->vdpol)
+       if (pdata && pdata->vs_pol)
                syn_mode |= ISPCCDC_SYN_MODE_VDPOL;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_VDPOL;
-
-       if (syncif->ccdc_mastermode) {
-               syn_mode |= ISPCCDC_SYN_MODE_FLDOUT | ISPCCDC_SYN_MODE_VDHDOUT;
-               isp_reg_writel(isp,
-                              syncif->hs_width << ISPCCDC_HD_VD_WID_HDW_SHIFT
-                            | syncif->vs_width << ISPCCDC_HD_VD_WID_VDW_SHIFT,
-                              OMAP3_ISP_IOMEM_CCDC,
-                              ISPCCDC_HD_VD_WID);
-
-               isp_reg_writel(isp,
-                              syncif->ppln << ISPCCDC_PIX_LINES_PPLN_SHIFT
-                            | syncif->hlprf << ISPCCDC_PIX_LINES_HLPRF_SHIFT,
-                              OMAP3_ISP_IOMEM_CCDC,
-                              ISPCCDC_PIX_LINES);
-       } else
-               syn_mode &= ~(ISPCCDC_SYN_MODE_FLDOUT |
-                             ISPCCDC_SYN_MODE_VDHDOUT);
 
        isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
 
-       if (!syncif->bt_r656_en)
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
-                           ISPCCDC_REC656IF_R656ON);
+       /* The CCDC_CFG.Y8POS bit is used in YCbCr8 input mode only. The
+        * hardware seems to ignore it in all other input modes.
+        */
+       if (format->code == V4L2_MBUS_FMT_UYVY8_2X8)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+                           ISPCCDC_CFG_Y8POS);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+                           ISPCCDC_CFG_Y8POS);
+
+       isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_REC656IF,
+                   ISPCCDC_REC656IF_R656ON);
 }
 
 /* CCDC formats descriptions */
@@ -1128,6 +1114,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        unsigned int depth_in = 0;
        struct media_pad *pad;
        unsigned long flags;
+       unsigned int bridge;
        unsigned int shift;
        u32 syn_mode;
        u32 ccdc_pattern;
@@ -1138,28 +1125,31 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
                pdata = &((struct isp_v4l2_subdevs_group *)sensor->host_priv)
                        ->bus.parallel;
 
-       /* Compute shift value for lane shifter to configure the bridge. */
+       /* Compute the lane shifter shift value and enable the bridge when the
+        * input format is YUV.
+        */
        fmt_src.pad = pad->index;
        fmt_src.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        if (!v4l2_subdev_call(sensor, pad, get_fmt, NULL, &fmt_src)) {
                fmt_info = omap3isp_video_format_info(fmt_src.format.code);
-               depth_in = fmt_info->bpp;
+               depth_in = fmt_info->width;
        }
 
        fmt_info = omap3isp_video_format_info
                (isp->isp_ccdc.formats[CCDC_PAD_SINK].code);
-       depth_out = fmt_info->bpp;
-
+       depth_out = fmt_info->width;
        shift = depth_in - depth_out;
-       omap3isp_configure_bridge(isp, ccdc->input, pdata, shift);
 
-       ccdc->syncif.datsz = depth_out;
-       ccdc->syncif.hdpol = pdata ? pdata->hs_pol : 0;
-       ccdc->syncif.vdpol = pdata ? pdata->vs_pol : 0;
-       ccdc_config_sync_if(ccdc, &ccdc->syncif);
+       if (fmt_info->code == V4L2_MBUS_FMT_YUYV8_2X8)
+               bridge = ISPCTRL_PAR_BRIDGE_LENDIAN;
+       else if (fmt_info->code == V4L2_MBUS_FMT_UYVY8_2X8)
+               bridge = ISPCTRL_PAR_BRIDGE_BENDIAN;
+       else
+               bridge = ISPCTRL_PAR_BRIDGE_DISABLE;
+
+       omap3isp_configure_bridge(isp, ccdc->input, pdata, shift, bridge);
 
-       /* CCDC_PAD_SINK */
-       format = &ccdc->formats[CCDC_PAD_SINK];
+       ccdc_config_sync_if(ccdc, pdata, depth_out);
 
        syn_mode = isp_reg_readl(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
 
@@ -1178,13 +1168,8 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
        else
                syn_mode &= ~ISPCCDC_SYN_MODE_SDR2RSZ;
 
-       /* Use PACK8 mode for 1byte per pixel formats. */
-       if (omap3isp_video_format_info(format->code)->bpp <= 8)
-               syn_mode |= ISPCCDC_SYN_MODE_PACK8;
-       else
-               syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
-
-       isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+       /* CCDC_PAD_SINK */
+       format = &ccdc->formats[CCDC_PAD_SINK];
 
        /* Mosaic filter */
        switch (format->code) {
@@ -1215,6 +1200,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VDINT);
 
        /* CCDC_PAD_SOURCE_OF */
+       format = &ccdc->formats[CCDC_PAD_SOURCE_OF];
        crop = &ccdc->crop;
 
        isp_reg_writel(isp, (crop->left << ISPCCDC_HORZ_INFO_SPH_SHIFT) |
@@ -1228,6 +1214,24 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
 
        ccdc_config_outlineoffset(ccdc, ccdc->video_out.bpl_value, 0, 0);
 
+       /* The CCDC outputs data in UYVY order by default. Swap bytes to get
+        * YUYV.
+        */
+       if (format->code == V4L2_MBUS_FMT_YUYV8_1X16)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+                           ISPCCDC_CFG_BSWD);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_CFG,
+                           ISPCCDC_CFG_BSWD);
+
+       /* Use PACK8 mode for 1byte per pixel formats. */
+       if (omap3isp_video_format_info(format->code)->width <= 8)
+               syn_mode |= ISPCCDC_SYN_MODE_PACK8;
+       else
+               syn_mode &= ~ISPCCDC_SYN_MODE_PACK8;
+
+       isp_reg_writel(isp, syn_mode, OMAP3_ISP_IOMEM_CCDC, ISPCCDC_SYN_MODE);
+
        /* CCDC_PAD_SOURCE_VP */
        format = &ccdc->formats[CCDC_PAD_SOURCE_VP];
 
@@ -1242,6 +1246,7 @@ static void ccdc_configure(struct isp_ccdc_device *ccdc)
                       (format->height << ISPCCDC_VP_OUT_VERT_NUM_SHIFT),
                       OMAP3_ISP_IOMEM_CCDC, ISPCCDC_VP_OUT);
 
+       /* Lens shading correction. */
        spin_lock_irqsave(&ccdc->lsc.req_lock, flags);
        if (ccdc->lsc.request == NULL)
                goto unlock;
@@ -1701,7 +1706,7 @@ static long ccdc_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
 }
 
 static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                               struct v4l2_event_subscription *sub)
+                               const struct v4l2_event_subscription *sub)
 {
        if (sub->type != V4L2_EVENT_FRAME_SYNC)
                return -EINVAL;
@@ -1714,7 +1719,7 @@ static int ccdc_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
 }
 
 static int ccdc_unsubscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
-                                 struct v4l2_event_subscription *sub)
+                                 const struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
@@ -1819,8 +1824,8 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                unsigned int pad, struct v4l2_mbus_framefmt *fmt,
                enum v4l2_subdev_format_whence which)
 {
-       struct v4l2_mbus_framefmt *format;
        const struct isp_format_info *info;
+       enum v4l2_mbus_pixelcode pixelcode;
        unsigned int width = fmt->width;
        unsigned int height = fmt->height;
        struct v4l2_rect *crop;
@@ -1828,9 +1833,6 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
 
        switch (pad) {
        case CCDC_PAD_SINK:
-               /* TODO: If the CCDC output formatter pad is connected directly
-                * to the resizer, only YUV formats can be used.
-                */
                for (i = 0; i < ARRAY_SIZE(ccdc_fmts); i++) {
                        if (fmt->code == ccdc_fmts[i])
                                break;
@@ -1846,8 +1848,26 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                break;
 
        case CCDC_PAD_SOURCE_OF:
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
-               memcpy(fmt, format, sizeof(*fmt));
+               pixelcode = fmt->code;
+               *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
+
+               /* YUV formats are converted from 2X8 to 1X16 by the bridge and
+                * can be byte-swapped.
+                */
+               if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+                   fmt->code == V4L2_MBUS_FMT_UYVY8_2X8) {
+                       /* Use the user requested format if YUV. */
+                       if (pixelcode == V4L2_MBUS_FMT_YUYV8_2X8 ||
+                           pixelcode == V4L2_MBUS_FMT_UYVY8_2X8 ||
+                           pixelcode == V4L2_MBUS_FMT_YUYV8_1X16 ||
+                           pixelcode == V4L2_MBUS_FMT_UYVY8_1X16)
+                               fmt->code = pixelcode;
+
+                       if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8)
+                               fmt->code = V4L2_MBUS_FMT_YUYV8_1X16;
+                       else if (fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
+                               fmt->code = V4L2_MBUS_FMT_UYVY8_1X16;
+               }
 
                /* Hardcode the output size to the crop rectangle size. */
                crop = __ccdc_get_crop(ccdc, fh, which);
@@ -1856,13 +1876,17 @@ ccdc_try_format(struct isp_ccdc_device *ccdc, struct v4l2_subdev_fh *fh,
                break;
 
        case CCDC_PAD_SOURCE_VP:
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
-               memcpy(fmt, format, sizeof(*fmt));
+               *fmt = *__ccdc_get_format(ccdc, fh, CCDC_PAD_SINK, which);
 
                /* The video port interface truncates the data to 10 bits. */
                info = omap3isp_video_format_info(fmt->code);
                fmt->code = info->truncated;
 
+               /* YUV formats are not supported by the video port. */
+               if (fmt->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+                   fmt->code == V4L2_MBUS_FMT_UYVY8_2X8)
+                       fmt->code = 0;
+
                /* The number of lines that can be clocked out from the video
                 * port output must be at least one line less than the number
                 * of input lines.
@@ -1945,14 +1969,46 @@ static int ccdc_enum_mbus_code(struct v4l2_subdev *sd,
                break;
 
        case CCDC_PAD_SOURCE_OF:
+               format = __ccdc_get_format(ccdc, fh, code->pad,
+                                          V4L2_SUBDEV_FORMAT_TRY);
+
+               if (format->code == V4L2_MBUS_FMT_YUYV8_2X8 ||
+                   format->code == V4L2_MBUS_FMT_UYVY8_2X8) {
+                       /* In YUV mode the CCDC can swap bytes. */
+                       if (code->index == 0)
+                               code->code = V4L2_MBUS_FMT_YUYV8_1X16;
+                       else if (code->index == 1)
+                               code->code = V4L2_MBUS_FMT_UYVY8_1X16;
+                       else
+                               return -EINVAL;
+               } else {
+                       /* In raw mode, no configurable format confversion is
+                        * available.
+                        */
+                       if (code->index == 0)
+                               code->code = format->code;
+                       else
+                               return -EINVAL;
+               }
+               break;
+
        case CCDC_PAD_SOURCE_VP:
-               /* No format conversion inside CCDC */
+               /* The CCDC supports no configurable format conversion
+                * compatible with the video port. Enumerate a single output
+                * format code.
+                */
                if (code->index != 0)
                        return -EINVAL;
 
-               format = __ccdc_get_format(ccdc, fh, CCDC_PAD_SINK,
+               format = __ccdc_get_format(ccdc, fh, code->pad,
                                           V4L2_SUBDEV_FORMAT_TRY);
 
+               /* A pixel code equal to 0 means that the video port doesn't
+                * support the input format. Don't enumerate any pixel code.
+                */
+               if (format->code == 0)
+                       return -EINVAL;
+
                code->code = format->code;
                break;
 
@@ -2182,7 +2238,7 @@ static bool ccdc_is_shiftable(enum v4l2_mbus_pixelcode in,
        if (in_info->flavor != out_info->flavor)
                return false;
 
-       return in_info->bpp - out_info->bpp + additional_shift <= 6;
+       return in_info->width - out_info->width + additional_shift <= 6;
 }
 
 static int ccdc_link_validate(struct v4l2_subdev *sd,
@@ -2487,14 +2543,6 @@ int omap3isp_ccdc_init(struct isp_device *isp)
        INIT_LIST_HEAD(&ccdc->lsc.free_queue);
        spin_lock_init(&ccdc->lsc.req_lock);
 
-       ccdc->syncif.ccdc_mastermode = 0;
-       ccdc->syncif.datapol = 0;
-       ccdc->syncif.datsz = 0;
-       ccdc->syncif.fldmode = 0;
-       ccdc->syncif.fldout = 0;
-       ccdc->syncif.fldpol = 0;
-       ccdc->syncif.fldstat = 0;
-
        ccdc->clamp.oblen = 0;
        ccdc->clamp.dcsubval = 0;
 
similarity index 83%
rename from drivers/media/video/omap3isp/ispccdc.h
rename to drivers/media/platform/omap3isp/ispccdc.h
index 890f6b3a68fd04530bcdd28380f144e0539e1a12..a5da9e19edbf632e5e22bb1920944cec66157b27 100644 (file)
@@ -46,40 +46,6 @@ enum ccdc_input_entity {
 
 #define        OMAP3ISP_CCDC_NEVENTS   16
 
-/*
- * struct ispccdc_syncif - Structure for Sync Interface between sensor and CCDC
- * @ccdc_mastermode: Master mode. 1 - Master, 0 - Slave.
- * @fldstat: Field state. 0 - Odd Field, 1 - Even Field.
- * @datsz: Data size.
- * @fldmode: 0 - Progressive, 1 - Interlaced.
- * @datapol: 0 - Positive, 1 - Negative.
- * @fldpol: 0 - Positive, 1 - Negative.
- * @hdpol: 0 - Positive, 1 - Negative.
- * @vdpol: 0 - Positive, 1 - Negative.
- * @fldout: 0 - Input, 1 - Output.
- * @hs_width: Width of the Horizontal Sync pulse, used for HS/VS Output.
- * @vs_width: Width of the Vertical Sync pulse, used for HS/VS Output.
- * @ppln: Number of pixels per line, used for HS/VS Output.
- * @hlprf: Number of half lines per frame, used for HS/VS Output.
- * @bt_r656_en: 1 - Enable ITU-R BT656 mode, 0 - Sync mode.
- */
-struct ispccdc_syncif {
-       u8 ccdc_mastermode;
-       u8 fldstat;
-       u8 datsz;
-       u8 fldmode;
-       u8 datapol;
-       u8 fldpol;
-       u8 hdpol;
-       u8 vdpol;
-       u8 fldout;
-       u8 hs_width;
-       u8 vs_width;
-       u8 ppln;
-       u8 hlprf;
-       u8 bt_r656_en;
-};
-
 enum ispccdc_lsc_state {
        LSC_STATE_STOPPED = 0,
        LSC_STATE_STOPPING = 1,
@@ -153,7 +119,6 @@ struct ispccdc_lsc {
  * @lsc: Lens shading compensation configuration
  * @update: Bitmask of controls to update during the next interrupt
  * @shadow_update: Controls update in progress by userspace
- * @syncif: Interface synchronization configuration
  * @underrun: A buffer underrun occurred and a new buffer has been queued
  * @state: Streaming state
  * @lock: Serializes shadow_update with interrupt handler
@@ -182,8 +147,6 @@ struct isp_ccdc_device {
        unsigned int update;
        unsigned int shadow_update;
 
-       struct ispccdc_syncif syncif;
-
        unsigned int underrun:1;
        enum isp_pipeline_stream_state state;
        spinlock_t lock;
similarity index 98%
rename from drivers/media/video/omap3isp/ispcsi2.c
rename to drivers/media/platform/omap3isp/ispcsi2.c
index a1724362b6d5e039307eeb7849244f43da97a5a0..6a3ff792af7d6a3b07042bc2d7c582b9f9ba5b95 100644 (file)
@@ -96,11 +96,12 @@ static const unsigned int csi2_input_fmts[] = {
        V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
        V4L2_MBUS_FMT_SGBRG10_1X10,
        V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
+       V4L2_MBUS_FMT_YUYV8_2X8,
 };
 
 /* To set the format on the CSI2 requires a mapping function that takes
  * the following inputs:
- * - 2 different formats (at this time)
+ * - 3 different formats (at this time)
  * - 2 destinations (mem, vp+mem) (vp only handled separately)
  * - 2 decompression options (on, off)
  * - 2 isp revisions (certain format must be handled differently on OMAP3630)
@@ -108,7 +109,7 @@ static const unsigned int csi2_input_fmts[] = {
  * Array indices as follows: [format][dest][decompr][is_3630]
  * Not all combinations are valid. 0 means invalid.
  */
-static const u16 __csi2_fmt_map[2][2][2][2] = {
+static const u16 __csi2_fmt_map[3][2][2][2] = {
        /* RAW10 formats */
        {
                /* Output to memory */
@@ -147,6 +148,25 @@ static const u16 __csi2_fmt_map[2][2][2][2] = {
                          CSI2_USERDEF_8BIT_DATA1_DPCM10_VP },
                },
        },
+       /* YUYV8 2X8 formats */
+       {
+               /* Output to memory */
+               {
+                       /* No DPCM decompression */
+                       { CSI2_PIX_FMT_YUV422_8BIT,
+                         CSI2_PIX_FMT_YUV422_8BIT },
+                       /* DPCM decompression */
+                       { 0, 0 },
+               },
+               /* Output to both */
+               {
+                       /* No DPCM decompression */
+                       { CSI2_PIX_FMT_YUV422_8BIT_VP,
+                         CSI2_PIX_FMT_YUV422_8BIT_VP },
+                       /* DPCM decompression */
+                       { 0, 0 },
+               },
+       },
 };
 
 /*
@@ -173,6 +193,9 @@ static u16 csi2_ctx_map_format(struct isp_csi2_device *csi2)
        case V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8:
                fmtidx = 1;
                break;
+       case V4L2_MBUS_FMT_YUYV8_2X8:
+               fmtidx = 2;
+               break;
        default:
                WARN(1, KERN_ERR "CSI2: pixel format %08x unsupported!\n",
                     fmt->code);
similarity index 96%
rename from drivers/media/video/omap3isp/isph3a_aewb.c
rename to drivers/media/platform/omap3isp/isph3a_aewb.c
index a3c76bf1817585997ebe7dcad9bcdbe3c7345aa1..036e9961d0279a174f075b56dbec29fae1a9ffa3 100644 (file)
@@ -93,17 +93,11 @@ static void h3a_aewb_enable(struct ispstat *aewb, int enable)
        if (enable) {
                isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
                            ISPH3A_PCR_AEW_EN);
-               /* This bit is already set if AF is enabled */
-               if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
-                       isp_reg_set(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                                   ISPCTRL_H3A_CLK_EN);
+               omap3isp_subclk_enable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
        } else {
                isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
                            ISPH3A_PCR_AEW_EN);
-               /* This bit can't be cleared if AF is enabled */
-               if (aewb->isp->isp_af.state != ISPSTAT_ENABLED)
-                       isp_reg_clr(aewb->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                                   ISPCTRL_H3A_CLK_EN);
+               omap3isp_subclk_disable(aewb->isp, OMAP3_ISP_SUBCLK_AEWB);
        }
 }
 
similarity index 96%
rename from drivers/media/video/omap3isp/isph3a_af.c
rename to drivers/media/platform/omap3isp/isph3a_af.c
index 58e0bc41489971a16d47e0afcf6722fc318687dd..42ccce318d5d08adf107953c5662146dc56a9aeb 100644 (file)
@@ -143,17 +143,11 @@ static void h3a_af_enable(struct ispstat *af, int enable)
        if (enable) {
                isp_reg_set(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
                            ISPH3A_PCR_AF_EN);
-               /* This bit is already set if AEWB is enabled */
-               if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
-                       isp_reg_set(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                                   ISPCTRL_H3A_CLK_EN);
+               omap3isp_subclk_enable(af->isp, OMAP3_ISP_SUBCLK_AF);
        } else {
                isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_H3A, ISPH3A_PCR,
                            ISPH3A_PCR_AF_EN);
-               /* This bit can't be cleared if AEWB is enabled */
-               if (af->isp->isp_aewb.state != ISPSTAT_ENABLED)
-                       isp_reg_clr(af->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                                   ISPCTRL_H3A_CLK_EN);
+               omap3isp_subclk_disable(af->isp, OMAP3_ISP_SUBCLK_AF);
        }
 }
 
similarity index 98%
rename from drivers/media/video/omap3isp/isphist.c
rename to drivers/media/platform/omap3isp/isphist.c
index 1163907bcddcb17fcdbb3fb8070d697f0842dc98..d1a8dee5e1ca4720adb96fde8c87e6280187d862 100644 (file)
@@ -167,13 +167,11 @@ static void hist_enable(struct ispstat *hist, int enable)
        if (enable) {
                isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
                            ISPHIST_PCR_ENABLE);
-               isp_reg_set(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                           ISPCTRL_HIST_CLK_EN);
+               omap3isp_subclk_enable(hist->isp, OMAP3_ISP_SUBCLK_HIST);
        } else {
                isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_HIST, ISPHIST_PCR,
                            ISPHIST_PCR_ENABLE);
-               isp_reg_clr(hist->isp, OMAP3_ISP_IOMEM_MAIN, ISP_CTRL,
-                           ISPCTRL_HIST_CLK_EN);
+               omap3isp_subclk_disable(hist->isp, OMAP3_ISP_SUBCLK_HIST);
        }
 }
 
similarity index 89%
rename from drivers/media/video/omap3isp/isppreview.c
rename to drivers/media/platform/omap3isp/isppreview.c
index 53f5a703e31abd218692a679cd4b0ccf9b16d98a..1ae1c0909ed1c5f5302dd21982f32ec39f19044e 100644 (file)
@@ -131,7 +131,7 @@ static struct omap3isp_prev_csc flr_prev_csc = {
  * CFA Filter Coefficient Table
  *
  */
-static u32 cfa_coef_table[] = {
+static u32 cfa_coef_table[4][OMAP3ISP_PREV_CFA_BLK_SIZE] = {
 #include "cfa_coef_table.h"
 };
 
@@ -157,85 +157,74 @@ static u32 luma_enhance_table[] = {
 };
 
 /*
- * preview_enable_invalaw - Enable/Disable Inverse A-Law module in Preview.
- * @enable: 1 - Reverse the A-Law done in CCDC.
+ * preview_config_luma_enhancement - Configure the Luminance Enhancement table
  */
 static void
-preview_enable_invalaw(struct isp_prev_device *prev, u8 enable)
+preview_config_luma_enhancement(struct isp_prev_device *prev,
+                               const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
+       const struct omap3isp_prev_luma *yt = &params->luma;
+       unsigned int i;
 
-       if (enable)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
+       isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+       for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
+               isp_reg_writel(isp, yt->table[i],
+                              OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+       }
 }
 
 /*
- * preview_enable_drkframe_capture - Enable/Disable of the darkframe capture.
- * @prev -
- * @enable: 1 - Enable, 0 - Disable
- *
- * NOTE: PRV_WSDR_ADDR and PRV_WADD_OFFSET must be set also
- * The process is applied for each captured frame.
+ * preview_enable_luma_enhancement - Enable/disable Luminance Enhancement
  */
 static void
-preview_enable_drkframe_capture(struct isp_prev_device *prev, u8 enable)
+preview_enable_luma_enhancement(struct isp_prev_device *prev, bool enable)
 {
        struct isp_device *isp = to_isp_device(prev);
 
        if (enable)
                isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DRKFCAP);
+                           ISPPRV_PCR_YNENHEN);
        else
                isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DRKFCAP);
+                           ISPPRV_PCR_YNENHEN);
 }
 
 /*
- * preview_enable_drkframe - Enable/Disable of the darkframe subtract.
- * @enable: 1 - Acquires memory bandwidth since the pixels in each frame is
- *          subtracted with the pixels in the current frame.
- *
- * The process is applied for each captured frame.
+ * preview_enable_invalaw - Enable/disable Inverse A-Law decompression
  */
-static void
-preview_enable_drkframe(struct isp_prev_device *prev, u8 enable)
+static void preview_enable_invalaw(struct isp_prev_device *prev, bool enable)
 {
        struct isp_device *isp = to_isp_device(prev);
 
        if (enable)
                isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DRKFEN);
+                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
        else
                isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DRKFEN);
+                           ISPPRV_PCR_WIDTH | ISPPRV_PCR_INVALAW);
 }
 
 /*
- * preview_config_drkf_shadcomp - Configures shift value in shading comp.
- * @scomp_shtval: 3bit value of shift used in shading compensation.
+ * preview_config_hmed - Configure the Horizontal Median Filter
  */
-static void
-preview_config_drkf_shadcomp(struct isp_prev_device *prev,
-                            const void *scomp_shtval)
+static void preview_config_hmed(struct isp_prev_device *prev,
+                               const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const u32 *shtval = scomp_shtval;
+       const struct omap3isp_prev_hmed *hmed = &params->hmed;
 
-       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                       ISPPRV_PCR_SCOMP_SFT_MASK,
-                       *shtval << ISPPRV_PCR_SCOMP_SFT_SHIFT);
+       isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
+                      (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
+                      (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
 }
 
 /*
- * preview_enable_hmed - Enables/Disables of the Horizontal Median Filter.
- * @enable: 1 - Enables Horizontal Median Filter.
+ * preview_enable_hmed - Enable/disable the Horizontal Median Filter
  */
-static void
-preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
+static void preview_enable_hmed(struct isp_prev_device *prev, bool enable)
 {
        struct isp_device *isp = to_isp_device(prev);
 
@@ -248,81 +237,27 @@ preview_enable_hmed(struct isp_prev_device *prev, u8 enable)
 }
 
 /*
- * preview_config_hmed - Configures the Horizontal Median Filter.
- * @prev_hmed: Structure containing the odd and even distance between the
- *             pixels in the image along with the filter threshold.
- */
-static void
-preview_config_hmed(struct isp_prev_device *prev, const void *prev_hmed)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_hmed *hmed = prev_hmed;
-
-       isp_reg_writel(isp, (hmed->odddist == 1 ? 0 : ISPPRV_HMED_ODDDIST) |
-                      (hmed->evendist == 1 ? 0 : ISPPRV_HMED_EVENDIST) |
-                      (hmed->thres << ISPPRV_HMED_THRESHOLD_SHIFT),
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_HMED);
-}
-
-/*
- * preview_config_noisefilter - Configures the Noise Filter.
- * @prev_nf: Structure containing the noisefilter table, strength to be used
- *           for the noise filter and the defect correction enable flag.
- */
-static void
-preview_config_noisefilter(struct isp_prev_device *prev, const void *prev_nf)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_nf *nf = prev_nf;
-       unsigned int i;
-
-       isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
-       isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
-       for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
-               isp_reg_writel(isp, nf->table[i],
-                              OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
-       }
-}
-
-/*
- * preview_config_dcor - Configures the defect correction
- * @prev_dcor: Structure containing the defect correct thresholds
- */
-static void
-preview_config_dcor(struct isp_prev_device *prev, const void *prev_dcor)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_dcor *dcor = prev_dcor;
-
-       isp_reg_writel(isp, dcor->detect_correct[0],
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
-       isp_reg_writel(isp, dcor->detect_correct[1],
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
-       isp_reg_writel(isp, dcor->detect_correct[2],
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
-       isp_reg_writel(isp, dcor->detect_correct[3],
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
-       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                       ISPPRV_PCR_DCCOUP,
-                       dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
-}
-
-/*
- * preview_config_cfa - Configures the CFA Interpolation parameters.
- * @prev_cfa: Structure containing the CFA interpolation table, CFA format
- *            in the image, vertical and horizontal gradient threshold.
- */
-static void
-preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
-{
+ * preview_config_cfa - Configure CFA Interpolation for Bayer formats
+ *
+ * The CFA table is organised in four blocks, one per Bayer component. The
+ * hardware expects blocks to follow the Bayer order of the input data, while
+ * the driver stores the table in GRBG order in memory. The blocks need to be
+ * reordered to support non-GRBG Bayer patterns.
+ */
+static void preview_config_cfa(struct isp_prev_device *prev,
+                              const struct prev_params *params)
+{
+       static const unsigned int cfa_coef_order[4][4] = {
+               { 0, 1, 2, 3 }, /* GRBG */
+               { 1, 0, 3, 2 }, /* RGGB */
+               { 2, 3, 0, 1 }, /* BGGR */
+               { 3, 2, 1, 0 }, /* GBRG */
+       };
+       const unsigned int *order = cfa_coef_order[prev->params.cfa_order];
+       const struct omap3isp_prev_cfa *cfa = &params->cfa;
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_cfa *cfa = prev_cfa;
        unsigned int i;
-
-       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                       ISPPRV_PCR_CFAFMT_MASK,
-                       cfa->format << ISPPRV_PCR_CFAFMT_SHIFT);
+       unsigned int j;
 
        isp_reg_writel(isp,
                (cfa->gradthrs_vert << ISPPRV_CFA_GRADTH_VER_SHIFT) |
@@ -332,73 +267,24 @@ preview_config_cfa(struct isp_prev_device *prev, const void *prev_cfa)
        isp_reg_writel(isp, ISPPRV_CFA_TABLE_ADDR,
                       OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
 
-       for (i = 0; i < OMAP3ISP_PREV_CFA_TBL_SIZE; i++) {
-               isp_reg_writel(isp, cfa->table[i],
-                              OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
-       }
-}
-
-/*
- * preview_config_gammacorrn - Configures the Gamma Correction table values
- * @gtable: Structure containing the table for red, blue, green gamma table.
- */
-static void
-preview_config_gammacorrn(struct isp_prev_device *prev, const void *gtable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_gtables *gt = gtable;
-       unsigned int i;
-
-       isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
-       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
-               isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
-                              ISPPRV_SET_TBL_DATA);
-
-       isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
-       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
-               isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
-                              ISPPRV_SET_TBL_DATA);
-
-       isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
-       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
-               isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
-                              ISPPRV_SET_TBL_DATA);
-}
-
-/*
- * preview_config_luma_enhancement - Sets the Luminance Enhancement table.
- * @ytable: Structure containing the table for Luminance Enhancement table.
- */
-static void
-preview_config_luma_enhancement(struct isp_prev_device *prev,
-                               const void *ytable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_luma *yt = ytable;
-       unsigned int i;
+       for (i = 0; i < 4; ++i) {
+               const __u32 *block = cfa->table[order[i]];
 
-       isp_reg_writel(isp, ISPPRV_YENH_TABLE_ADDR,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
-       for (i = 0; i < OMAP3ISP_PREV_YENH_TBL_SIZE; i++) {
-               isp_reg_writel(isp, yt->table[i],
-                              OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+               for (j = 0; j < OMAP3ISP_PREV_CFA_BLK_SIZE; ++j)
+                       isp_reg_writel(isp, block[j], OMAP3_ISP_IOMEM_PREV,
+                                      ISPPRV_SET_TBL_DATA);
        }
 }
 
 /*
- * preview_config_chroma_suppression - Configures the Chroma Suppression.
- * @csup: Structure containing the threshold value for suppression
- *        and the hypass filter enable flag.
+ * preview_config_chroma_suppression - Configure Chroma Suppression
  */
 static void
 preview_config_chroma_suppression(struct isp_prev_device *prev,
-                                 const void *csup)
+                                 const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_csup *cs = csup;
+       const struct omap3isp_prev_csup *cs = &params->csup;
 
        isp_reg_writel(isp,
                       cs->gain | (cs->thres << ISPPRV_CSUP_THRES_SHIFT) |
@@ -407,80 +293,10 @@ preview_config_chroma_suppression(struct isp_prev_device *prev,
 }
 
 /*
- * preview_enable_noisefilter - Enables/Disables the Noise Filter.
- * @enable: 1 - Enables the Noise Filter.
- */
-static void
-preview_enable_noisefilter(struct isp_prev_device *prev, u8 enable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       if (enable)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_NFEN);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_NFEN);
-}
-
-/*
- * preview_enable_dcor - Enables/Disables the defect correction.
- * @enable: 1 - Enables the defect correction.
- */
-static void
-preview_enable_dcor(struct isp_prev_device *prev, u8 enable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       if (enable)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DCOREN);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_DCOREN);
-}
-
-/*
- * preview_enable_gammabypass - Enables/Disables the GammaByPass
- * @enable: 1 - Bypasses Gamma - 10bit input is cropped to 8MSB.
- *          0 - Goes through Gamma Correction. input and output is 10bit.
+ * preview_enable_chroma_suppression - Enable/disable Chrominance Suppression
  */
 static void
-preview_enable_gammabypass(struct isp_prev_device *prev, u8 enable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       if (enable)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_GAMMA_BYPASS);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_GAMMA_BYPASS);
-}
-
-/*
- * preview_enable_luma_enhancement - Enables/Disables Luminance Enhancement
- * @enable: 1 - Enable the Luminance Enhancement.
- */
-static void
-preview_enable_luma_enhancement(struct isp_prev_device *prev, u8 enable)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       if (enable)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_YNENHEN);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_YNENHEN);
-}
-
-/*
- * preview_enable_chroma_suppression - Enables/Disables Chrominance Suppr.
- * @enable: 1 - Enable the Chrominance Suppression.
- */
-static void
-preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
+preview_enable_chroma_suppression(struct isp_prev_device *prev, bool enable)
 {
        struct isp_device *isp = to_isp_device(prev);
 
@@ -493,17 +309,16 @@ preview_enable_chroma_suppression(struct isp_prev_device *prev, u8 enable)
 }
 
 /*
- * preview_config_whitebalance - Configures the White Balance parameters.
- * @prev_wbal: Structure containing the digital gain and white balance
- *             coefficient.
+ * preview_config_whitebalance - Configure White Balance parameters
  *
  * Coefficient matrix always with default values.
  */
 static void
-preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
+preview_config_whitebalance(struct isp_prev_device *prev,
+                           const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_wbal *wbal = prev_wbal;
+       const struct omap3isp_prev_wbal *wbal = &params->wbal;
        u32 val;
 
        isp_reg_writel(isp, wbal->dgain, OMAP3_ISP_IOMEM_PREV, ISPPRV_WB_DGAIN);
@@ -535,15 +350,14 @@ preview_config_whitebalance(struct isp_prev_device *prev, const void *prev_wbal)
 }
 
 /*
- * preview_config_blkadj - Configures the Black Adjustment parameters.
- * @prev_blkadj: Structure containing the black adjustment towards red, green,
- *               blue.
+ * preview_config_blkadj - Configure Black Adjustment
  */
 static void
-preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
+preview_config_blkadj(struct isp_prev_device *prev,
+                     const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_blkadj *blkadj = prev_blkadj;
+       const struct omap3isp_prev_blkadj *blkadj = &params->blkadj;
 
        isp_reg_writel(isp, (blkadj->blue << ISPPRV_BLKADJOFF_B_SHIFT) |
                       (blkadj->green << ISPPRV_BLKADJOFF_G_SHIFT) |
@@ -552,15 +366,14 @@ preview_config_blkadj(struct isp_prev_device *prev, const void *prev_blkadj)
 }
 
 /*
- * preview_config_rgb_blending - Configures the RGB-RGB Blending matrix.
- * @rgb2rgb: Structure containing the rgb to rgb blending matrix and the rgb
- *           offset.
+ * preview_config_rgb_blending - Configure RGB-RGB Blending
  */
 static void
-preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
+preview_config_rgb_blending(struct isp_prev_device *prev,
+                           const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_rgbtorgb *rgbrgb = rgb2rgb;
+       const struct omap3isp_prev_rgbtorgb *rgbrgb = &params->rgb2rgb;
        u32 val;
 
        val = (rgbrgb->matrix[0][0] & 0xfff) << ISPPRV_RGB_MAT1_MTX_RR_SHIFT;
@@ -591,15 +404,14 @@ preview_config_rgb_blending(struct isp_prev_device *prev, const void *rgb2rgb)
 }
 
 /*
- * Configures the color space conversion (RGB toYCbYCr) matrix
- * @prev_csc: Structure containing the RGB to YCbYCr matrix and the
- *            YCbCr offset.
+ * preview_config_csc - Configure Color Space Conversion (RGB to YCbYCr)
  */
 static void
-preview_config_csc(struct isp_prev_device *prev, const void *prev_csc)
+preview_config_csc(struct isp_prev_device *prev,
+                  const struct prev_params *params)
 {
        struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_csc *csc = prev_csc;
+       const struct omap3isp_prev_csc *csc = &params->csc;
        u32 val;
 
        val = (csc->matrix[0][0] & 0x3ff) << ISPPRV_CSC0_RY_SHIFT;
@@ -623,6 +435,208 @@ preview_config_csc(struct isp_prev_device *prev, const void *prev_csc)
        isp_reg_writel(isp, val, OMAP3_ISP_IOMEM_PREV, ISPPRV_CSC_OFFSET);
 }
 
+/*
+ * preview_config_yc_range - Configure the max and min Y and C values
+ */
+static void
+preview_config_yc_range(struct isp_prev_device *prev,
+                       const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+       const struct omap3isp_prev_yclimit *yc = &params->yclimit;
+
+       isp_reg_writel(isp,
+                      yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
+                      yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
+                      yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
+                      yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
+}
+
+/*
+ * preview_config_dcor - Configure Couplet Defect Correction
+ */
+static void
+preview_config_dcor(struct isp_prev_device *prev,
+                   const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+       const struct omap3isp_prev_dcor *dcor = &params->dcor;
+
+       isp_reg_writel(isp, dcor->detect_correct[0],
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR0);
+       isp_reg_writel(isp, dcor->detect_correct[1],
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR1);
+       isp_reg_writel(isp, dcor->detect_correct[2],
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR2);
+       isp_reg_writel(isp, dcor->detect_correct[3],
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_CDC_THR3);
+       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                       ISPPRV_PCR_DCCOUP,
+                       dcor->couplet_mode_en ? ISPPRV_PCR_DCCOUP : 0);
+}
+
+/*
+ * preview_enable_dcor - Enable/disable Couplet Defect Correction
+ */
+static void preview_enable_dcor(struct isp_prev_device *prev, bool enable)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       if (enable)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DCOREN);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DCOREN);
+}
+
+/*
+ * preview_enable_drkframe_capture - Enable/disable Dark Frame Capture
+ */
+static void
+preview_enable_drkframe_capture(struct isp_prev_device *prev, bool enable)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       if (enable)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DRKFCAP);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DRKFCAP);
+}
+
+/*
+ * preview_enable_drkframe - Enable/disable Dark Frame Subtraction
+ */
+static void preview_enable_drkframe(struct isp_prev_device *prev, bool enable)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       if (enable)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DRKFEN);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_DRKFEN);
+}
+
+/*
+ * preview_config_noisefilter - Configure the Noise Filter
+ */
+static void
+preview_config_noisefilter(struct isp_prev_device *prev,
+                          const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+       const struct omap3isp_prev_nf *nf = &params->nf;
+       unsigned int i;
+
+       isp_reg_writel(isp, nf->spread, OMAP3_ISP_IOMEM_PREV, ISPPRV_NF);
+       isp_reg_writel(isp, ISPPRV_NF_TABLE_ADDR,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+       for (i = 0; i < OMAP3ISP_PREV_NF_TBL_SIZE; i++) {
+               isp_reg_writel(isp, nf->table[i],
+                              OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_DATA);
+       }
+}
+
+/*
+ * preview_enable_noisefilter - Enable/disable the Noise Filter
+ */
+static void
+preview_enable_noisefilter(struct isp_prev_device *prev, bool enable)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       if (enable)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_NFEN);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_NFEN);
+}
+
+/*
+ * preview_config_gammacorrn - Configure the Gamma Correction tables
+ */
+static void
+preview_config_gammacorrn(struct isp_prev_device *prev,
+                         const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+       const struct omap3isp_prev_gtables *gt = &params->gamma;
+       unsigned int i;
+
+       isp_reg_writel(isp, ISPPRV_REDGAMMA_TABLE_ADDR,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+               isp_reg_writel(isp, gt->red[i], OMAP3_ISP_IOMEM_PREV,
+                              ISPPRV_SET_TBL_DATA);
+
+       isp_reg_writel(isp, ISPPRV_GREENGAMMA_TABLE_ADDR,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+               isp_reg_writel(isp, gt->green[i], OMAP3_ISP_IOMEM_PREV,
+                              ISPPRV_SET_TBL_DATA);
+
+       isp_reg_writel(isp, ISPPRV_BLUEGAMMA_TABLE_ADDR,
+                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SET_TBL_ADDR);
+       for (i = 0; i < OMAP3ISP_PREV_GAMMA_TBL_SIZE; i++)
+               isp_reg_writel(isp, gt->blue[i], OMAP3_ISP_IOMEM_PREV,
+                              ISPPRV_SET_TBL_DATA);
+}
+
+/*
+ * preview_enable_gammacorrn - Enable/disable Gamma Correction
+ *
+ * When gamma correction is disabled, the module is bypassed and its output is
+ * the 8 MSB of the 10-bit input .
+ */
+static void
+preview_enable_gammacorrn(struct isp_prev_device *prev, bool enable)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       if (enable)
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_GAMMA_BYPASS);
+       else
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_GAMMA_BYPASS);
+}
+
+/*
+ * preview_config_contrast - Configure the Contrast
+ *
+ * Value should be programmed before enabling the module.
+ */
+static void
+preview_config_contrast(struct isp_prev_device *prev,
+                       const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
+                       0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
+                       params->contrast << ISPPRV_CNT_BRT_CNT_SHIFT);
+}
+
+/*
+ * preview_config_brightness - Configure the Brightness
+ */
+static void
+preview_config_brightness(struct isp_prev_device *prev,
+                         const struct prev_params *params)
+{
+       struct isp_device *isp = to_isp_device(prev);
+
+       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
+                       0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
+                       params->brightness << ISPPRV_CNT_BRT_BRT_SHIFT);
+}
+
 /*
  * preview_update_contrast - Updates the contrast.
  * @contrast: Pointer to hold the current programmed contrast value.
@@ -646,22 +660,6 @@ preview_update_contrast(struct isp_prev_device *prev, u8 contrast)
        spin_unlock_irqrestore(&prev->params.lock, flags);
 }
 
-/*
- * preview_config_contrast - Configures the Contrast.
- * @params: Contrast value (u8 pointer, U8Q0 format).
- *
- * Value should be programmed before enabling the module.
- */
-static void
-preview_config_contrast(struct isp_prev_device *prev, const void *params)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
-                       0xff << ISPPRV_CNT_BRT_CNT_SHIFT,
-                       *(u8 *)params << ISPPRV_CNT_BRT_CNT_SHIFT);
-}
-
 /*
  * preview_update_brightness - Updates the brightness in preview module.
  * @brightness: Pointer to hold the current programmed brightness value.
@@ -684,38 +682,6 @@ preview_update_brightness(struct isp_prev_device *prev, u8 brightness)
        spin_unlock_irqrestore(&prev->params.lock, flags);
 }
 
-/*
- * preview_config_brightness - Configures the brightness.
- * @params: Brightness value (u8 pointer, U8Q0 format).
- */
-static void
-preview_config_brightness(struct isp_prev_device *prev, const void *params)
-{
-       struct isp_device *isp = to_isp_device(prev);
-
-       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_CNT_BRT,
-                       0xff << ISPPRV_CNT_BRT_BRT_SHIFT,
-                       *(u8 *)params << ISPPRV_CNT_BRT_BRT_SHIFT);
-}
-
-/*
- * preview_config_yc_range - Configures the max and min Y and C values.
- * @yclimit: Structure containing the range of Y and C values.
- */
-static void
-preview_config_yc_range(struct isp_prev_device *prev, const void *yclimit)
-{
-       struct isp_device *isp = to_isp_device(prev);
-       const struct omap3isp_prev_yclimit *yc = yclimit;
-
-       isp_reg_writel(isp,
-                      yc->maxC << ISPPRV_SETUP_YC_MAXC_SHIFT |
-                      yc->maxY << ISPPRV_SETUP_YC_MAXY_SHIFT |
-                      yc->minC << ISPPRV_SETUP_YC_MINC_SHIFT |
-                      yc->minY << ISPPRV_SETUP_YC_MINY_SHIFT,
-                      OMAP3_ISP_IOMEM_PREV, ISPPRV_SETUP_YC);
-}
-
 static u32
 preview_params_lock(struct isp_prev_device *prev, u32 update, bool shadow)
 {
@@ -787,8 +753,8 @@ static void preview_params_switch(struct isp_prev_device *prev)
 
 /* preview parameters update structure */
 struct preview_update {
-       void (*config)(struct isp_prev_device *, const void *);
-       void (*enable)(struct isp_prev_device *, u8);
+       void (*config)(struct isp_prev_device *, const struct prev_params *);
+       void (*enable)(struct isp_prev_device *, bool);
        unsigned int param_offset;
        unsigned int param_size;
        unsigned int config_offset;
@@ -860,9 +826,9 @@ static const struct preview_update update_attrs[] = {
                offsetof(struct prev_params, dcor),
                FIELD_SIZEOF(struct prev_params, dcor),
                offsetof(struct omap3isp_prev_update_config, dcor),
-       }, /* OMAP3ISP_PREV_GAMMABYPASS */ {
+       }, /* Previously OMAP3ISP_PREV_GAMMABYPASS, not used anymore */ {
+               NULL,
                NULL,
-               preview_enable_gammabypass,
        }, /* OMAP3ISP_PREV_DRK_FRM_CAPTURE */ {
                NULL,
                preview_enable_drkframe_capture,
@@ -870,7 +836,7 @@ static const struct preview_update update_attrs[] = {
                NULL,
                preview_enable_drkframe,
        }, /* OMAP3ISP_PREV_LENS_SHADING */ {
-               preview_config_drkf_shadcomp,
+               NULL,
                preview_enable_drkframe,
        }, /* OMAP3ISP_PREV_NF */ {
                preview_config_noisefilter,
@@ -880,20 +846,18 @@ static const struct preview_update update_attrs[] = {
                offsetof(struct omap3isp_prev_update_config, nf),
        }, /* OMAP3ISP_PREV_GAMMA */ {
                preview_config_gammacorrn,
-               NULL,
+               preview_enable_gammacorrn,
                offsetof(struct prev_params, gamma),
                FIELD_SIZEOF(struct prev_params, gamma),
                offsetof(struct omap3isp_prev_update_config, gamma),
        }, /* OMAP3ISP_PREV_CONTRAST */ {
                preview_config_contrast,
                NULL,
-               offsetof(struct prev_params, contrast),
-               0, 0, true,
+               0, 0, 0, true,
        }, /* OMAP3ISP_PREV_BRIGHTNESS */ {
                preview_config_brightness,
                NULL,
-               offsetof(struct prev_params, brightness),
-               0, 0, true,
+               0, 0, 0, true,
        },
 };
 
@@ -988,7 +952,6 @@ static void preview_setup_hw(struct isp_prev_device *prev, u32 update,
                const struct preview_update *attr = &update_attrs[i];
                struct prev_params *params;
                unsigned int bit = 1 << i;
-               void *param_ptr;
 
                if (!(update & bit))
                        continue;
@@ -996,15 +959,13 @@ static void preview_setup_hw(struct isp_prev_device *prev, u32 update,
                params = &prev->params.params[!(active & bit)];
 
                if (params->features & bit) {
-                       if (attr->config) {
-                               param_ptr = (void *)params + attr->param_offset;
-                               attr->config(prev, param_ptr);
-                       }
+                       if (attr->config)
+                               attr->config(prev, params);
                        if (attr->enable)
-                               attr->enable(prev, 1);
+                               attr->enable(prev, true);
                } else {
                        if (attr->enable)
-                               attr->enable(prev, 0);
+                               attr->enable(prev, false);
                }
        }
 }
@@ -1043,42 +1004,60 @@ preview_config_ycpos(struct isp_prev_device *prev,
 static void preview_config_averager(struct isp_prev_device *prev, u8 average)
 {
        struct isp_device *isp = to_isp_device(prev);
-       struct prev_params *params;
-       int reg = 0;
-
-       params = (prev->params.active & OMAP3ISP_PREV_CFA)
-              ? &prev->params.params[0] : &prev->params.params[1];
 
-       if (params->cfa.format == OMAP3ISP_CFAFMT_BAYER)
-               reg = ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
-                     ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
-                     average;
-       else if (params->cfa.format == OMAP3ISP_CFAFMT_RGBFOVEON)
-               reg = ISPPRV_AVE_EVENDIST_3 << ISPPRV_AVE_EVENDIST_SHIFT |
-                     ISPPRV_AVE_ODDDIST_3 << ISPPRV_AVE_ODDDIST_SHIFT |
-                     average;
-       isp_reg_writel(isp, reg, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
+       isp_reg_writel(isp, ISPPRV_AVE_EVENDIST_2 << ISPPRV_AVE_EVENDIST_SHIFT |
+                      ISPPRV_AVE_ODDDIST_2 << ISPPRV_AVE_ODDDIST_SHIFT |
+                      average, OMAP3_ISP_IOMEM_PREV, ISPPRV_AVE);
 }
 
+
 /*
  * preview_config_input_format - Configure the input format
  * @prev: The preview engine
  * @format: Format on the preview engine sink pad
  *
- * Enable CFA interpolation for Bayer formats and disable it for greyscale
- * formats.
+ * Enable and configure CFA interpolation for Bayer formats and disable it for
+ * greyscale formats.
+ *
+ * The CFA table is organised in four blocks, one per Bayer component. The
+ * hardware expects blocks to follow the Bayer order of the input data, while
+ * the driver stores the table in GRBG order in memory. The blocks need to be
+ * reordered to support non-GRBG Bayer patterns.
  */
 static void preview_config_input_format(struct isp_prev_device *prev,
                                        const struct v4l2_mbus_framefmt *format)
 {
        struct isp_device *isp = to_isp_device(prev);
+       struct prev_params *params;
 
-       if (format->code != V4L2_MBUS_FMT_Y10_1X10)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_CFAEN);
-       else
+       switch (format->code) {
+       case V4L2_MBUS_FMT_SGRBG10_1X10:
+               prev->params.cfa_order = 0;
+               break;
+       case V4L2_MBUS_FMT_SRGGB10_1X10:
+               prev->params.cfa_order = 1;
+               break;
+       case V4L2_MBUS_FMT_SBGGR10_1X10:
+               prev->params.cfa_order = 2;
+               break;
+       case V4L2_MBUS_FMT_SGBRG10_1X10:
+               prev->params.cfa_order = 3;
+               break;
+       default:
+               /* Disable CFA for non-Bayer formats. */
                isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
                            ISPPRV_PCR_CFAEN);
+               return;
+       }
+
+       isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR, ISPPRV_PCR_CFAEN);
+       isp_reg_clr_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                       ISPPRV_PCR_CFAFMT_MASK, ISPPRV_PCR_CFAFMT_BAYER);
+
+       params = (prev->params.active & OMAP3ISP_PREV_CFA)
+              ? &prev->params.params[0] : &prev->params.params[1];
+
+       preview_config_cfa(prev, params);
 }
 
 /*
@@ -1421,22 +1400,6 @@ static void preview_configure(struct isp_prev_device *prev)
        active = prev->params.active;
        spin_unlock_irqrestore(&prev->params.lock, flags);
 
-       preview_setup_hw(prev, update, active);
-
-       if (prev->output & PREVIEW_OUTPUT_MEMORY)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_SDRPORT);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_SDRPORT);
-
-       if (prev->output & PREVIEW_OUTPUT_RESIZER)
-               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_RSZPORT);
-       else
-               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
-                           ISPPRV_PCR_RSZPORT);
-
        /* PREV_PAD_SINK */
        format = &prev->formats[PREV_PAD_SINK];
 
@@ -1451,9 +1414,25 @@ static void preview_configure(struct isp_prev_device *prev)
                preview_config_inlineoffset(prev,
                                ALIGN(format->width, 0x20) * 2);
 
+       preview_setup_hw(prev, update, active);
+
        /* PREV_PAD_SOURCE */
        format = &prev->formats[PREV_PAD_SOURCE];
 
+       if (prev->output & PREVIEW_OUTPUT_MEMORY)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_SDRPORT);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_SDRPORT);
+
+       if (prev->output & PREVIEW_OUTPUT_RESIZER)
+               isp_reg_set(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_RSZPORT);
+       else
+               isp_reg_clr(isp, OMAP3_ISP_IOMEM_PREV, ISPPRV_PCR,
+                           ISPPRV_PCR_RSZPORT);
+
        if (prev->output & PREVIEW_OUTPUT_MEMORY)
                preview_config_outlineoffset(prev,
                                ALIGN(format->width, 0x10) * 2);
similarity index 99%
rename from drivers/media/video/omap3isp/isppreview.h
rename to drivers/media/platform/omap3isp/isppreview.h
index 6663ab64e4b1bbca413e96c77a9868ff7356a663..f66923407f8c5a90f2a4280201cb21460ad2fab6 100644 (file)
@@ -144,6 +144,7 @@ struct isp_prev_device {
        struct isp_video video_out;
 
        struct {
+               unsigned int cfa_order;
                struct prev_params params[2];
                u32 active;
                spinlock_t lock;
similarity index 98%
rename from drivers/media/video/omap3isp/ispqueue.c
rename to drivers/media/platform/omap3isp/ispqueue.c
index 9bebb1e57aab0dac17e8bccbb6e55cf1566661df..15bf3eab2224ab3d835380c4a55b1e83e1269636 100644 (file)
@@ -647,7 +647,7 @@ static int isp_video_queue_alloc(struct isp_video_queue *queue,
        if (ret < 0)
                return ret;
 
-       /* Bail out of no buffers should be allocated. */
+       /* Bail out if no buffers should be allocated. */
        if (nbuffers == 0)
                return 0;
 
@@ -908,13 +908,14 @@ done:
  *
  * This function is intended to be used as a VIDIOC_DQBUF ioctl handler.
  *
- * The v4l2_buffer structure passed from userspace is first sanity tested. If
- * sane, the buffer is then processed and added to the main queue and, if the
- * queue is streaming, to the IRQ queue.
+ * Wait until a buffer is ready to be dequeued, remove it from the queue and
+ * copy its information to the v4l2_buffer structure.
  *
- * Before being enqueued, USERPTR buffers are checked for address changes. If
- * the buffer has a different userspace address, the old memory area is unlocked
- * and the new memory area is locked.
+ * If the nonblocking argument is not zero and no buffer is ready, return
+ * -EAGAIN immediately instead of waiting.
+ *
+ * If no buffer has been enqueued, or if the requested buffer type doesn't match
+ * the queue type, return -EINVAL.
  */
 int omap3isp_video_queue_dqbuf(struct isp_video_queue *queue,
                               struct v4l2_buffer *vbuf, int nonblocking)
similarity index 99%
rename from drivers/media/video/omap3isp/ispresizer.c
rename to drivers/media/platform/omap3isp/ispresizer.c
index ae17d917f77b3657ef4553e26ea039768b9bc3e3..d11fb261d53070a131b4a3fbbd6cd2195bb3f574 100644 (file)
@@ -690,7 +690,7 @@ static void resizer_print_status(struct isp_res_device *res)
 }
 
 /*
- * resizer_calc_ratios - Helper function for calculate resizer ratios
+ * resizer_calc_ratios - Helper function for calculating resizer ratios
  * @res: pointer to resizer private data structure
  * @input: input frame size
  * @output: output frame size
@@ -734,7 +734,7 @@ static void resizer_print_status(struct isp_res_device *res)
  * value will still satisfy the original inequality, as b will disappear when
  * the expression will be shifted right by 8.
  *
- * The reverted the equations thus become
+ * The reverted equations thus become
  *
  * - 8-phase, 4-tap mode
  *     hrsz = ((iw - 7) * 256 + 255 - 16 - 32 * sph) / (ow - 1)
@@ -759,7 +759,7 @@ static void resizer_print_status(struct isp_res_device *res)
  * loop', the smallest of the ratio values will be used, never exceeding the
  * requested input size.
  *
- * We first clamp the output size according to the hardware capabilitie to avoid
+ * We first clamp the output size according to the hardware capability to avoid
  * auto-cropping the input more than required to satisfy the TRM equations. The
  * minimum output size is achieved with a scaling factor of 1024. It is thus
  * computed using the 7-tap equations.
@@ -1730,6 +1730,8 @@ static int resizer_init_entities(struct isp_res_device *res)
        if (ret < 0)
                goto error_video_out;
 
+       res->video_out.video.entity.flags |= MEDIA_ENT_FL_DEFAULT;
+
        /* Connect the video nodes to the resizer subdev. */
        ret = media_entity_create_link(&res->video_in.video.entity, 0,
                        &res->subdev.entity, RESZ_PAD_SINK, 0);
similarity index 99%
rename from drivers/media/video/omap3isp/ispstat.c
rename to drivers/media/platform/omap3isp/ispstat.c
index b8640be692f1aef7f093b6364ddb62c15a881504..d7ac76b5c2aee4d38916057b1757d2366b27b188 100644 (file)
@@ -1025,7 +1025,7 @@ void omap3isp_stat_dma_isr(struct ispstat *stat)
 
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 struct v4l2_event_subscription *sub)
+                                 const struct v4l2_event_subscription *sub)
 {
        struct ispstat *stat = v4l2_get_subdevdata(subdev);
 
@@ -1037,7 +1037,7 @@ int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
 
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   struct v4l2_event_subscription *sub)
+                                   const struct v4l2_event_subscription *sub)
 {
        return v4l2_event_unsubscribe(fh, sub);
 }
similarity index 97%
rename from drivers/media/video/omap3isp/ispstat.h
rename to drivers/media/platform/omap3isp/ispstat.h
index 9b7c8654dc8a4cadea05dd1ff629ad35b8ebae85..a6fe653eb237dc171c6aef71f31d62ddc1a30550 100644 (file)
@@ -147,10 +147,10 @@ int omap3isp_stat_init(struct ispstat *stat, const char *name,
 void omap3isp_stat_cleanup(struct ispstat *stat);
 int omap3isp_stat_subscribe_event(struct v4l2_subdev *subdev,
                                  struct v4l2_fh *fh,
-                                 struct v4l2_event_subscription *sub);
+                                 const struct v4l2_event_subscription *sub);
 int omap3isp_stat_unsubscribe_event(struct v4l2_subdev *subdev,
                                    struct v4l2_fh *fh,
-                                   struct v4l2_event_subscription *sub);
+                                   const struct v4l2_event_subscription *sub);
 int omap3isp_stat_s_stream(struct v4l2_subdev *subdev, int enable);
 
 int omap3isp_stat_busy(struct ispstat *stat);
similarity index 96%
rename from drivers/media/video/omap3isp/ispvideo.c
rename to drivers/media/platform/omap3isp/ispvideo.c
index b37379d39cdd888c72731377bb49886361b285e8..a0b737fecf138e61413fca9ca6c36443b5b452f4 100644 (file)
 static struct isp_format_info formats[] = {
        { V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
          V4L2_MBUS_FMT_Y8_1X8, V4L2_MBUS_FMT_Y8_1X8,
-         V4L2_PIX_FMT_GREY, 8, },
+         V4L2_PIX_FMT_GREY, 8, 1, },
        { V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y10_1X10,
          V4L2_MBUS_FMT_Y10_1X10, V4L2_MBUS_FMT_Y8_1X8,
-         V4L2_PIX_FMT_Y10, 10, },
+         V4L2_PIX_FMT_Y10, 10, 2, },
        { V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y10_1X10,
          V4L2_MBUS_FMT_Y12_1X12, V4L2_MBUS_FMT_Y8_1X8,
-         V4L2_PIX_FMT_Y12, 12, },
+         V4L2_PIX_FMT_Y12, 12, 2, },
        { V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
          V4L2_MBUS_FMT_SBGGR8_1X8, V4L2_MBUS_FMT_SBGGR8_1X8,
-         V4L2_PIX_FMT_SBGGR8, 8, },
+         V4L2_PIX_FMT_SBGGR8, 8, 1, },
        { V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
          V4L2_MBUS_FMT_SGBRG8_1X8, V4L2_MBUS_FMT_SGBRG8_1X8,
-         V4L2_PIX_FMT_SGBRG8, 8, },
+         V4L2_PIX_FMT_SGBRG8, 8, 1, },
        { V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
          V4L2_MBUS_FMT_SGRBG8_1X8, V4L2_MBUS_FMT_SGRBG8_1X8,
-         V4L2_PIX_FMT_SGRBG8, 8, },
+         V4L2_PIX_FMT_SGRBG8, 8, 1, },
        { V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
          V4L2_MBUS_FMT_SRGGB8_1X8, V4L2_MBUS_FMT_SRGGB8_1X8,
-         V4L2_PIX_FMT_SRGGB8, 8, },
+         V4L2_PIX_FMT_SRGGB8, 8, 1, },
        { V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8, V4L2_MBUS_FMT_SBGGR10_DPCM8_1X8,
          V4L2_MBUS_FMT_SBGGR10_1X10, 0,
-         V4L2_PIX_FMT_SBGGR10DPCM8, 8, },
+         V4L2_PIX_FMT_SBGGR10DPCM8, 8, 1, },
        { V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8, V4L2_MBUS_FMT_SGBRG10_DPCM8_1X8,
          V4L2_MBUS_FMT_SGBRG10_1X10, 0,
-         V4L2_PIX_FMT_SGBRG10DPCM8, 8, },
+         V4L2_PIX_FMT_SGBRG10DPCM8, 8, 1, },
        { V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8, V4L2_MBUS_FMT_SGRBG10_DPCM8_1X8,
          V4L2_MBUS_FMT_SGRBG10_1X10, 0,
-         V4L2_PIX_FMT_SGRBG10DPCM8, 8, },
+         V4L2_PIX_FMT_SGRBG10DPCM8, 8, 1, },
        { V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8, V4L2_MBUS_FMT_SRGGB10_DPCM8_1X8,
          V4L2_MBUS_FMT_SRGGB10_1X10, 0,
-         V4L2_PIX_FMT_SRGGB10DPCM8, 8, },
+         V4L2_PIX_FMT_SRGGB10DPCM8, 8, 1, },
        { V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR10_1X10,
          V4L2_MBUS_FMT_SBGGR10_1X10, V4L2_MBUS_FMT_SBGGR8_1X8,
-         V4L2_PIX_FMT_SBGGR10, 10, },
+         V4L2_PIX_FMT_SBGGR10, 10, 2, },
        { V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG10_1X10,
          V4L2_MBUS_FMT_SGBRG10_1X10, V4L2_MBUS_FMT_SGBRG8_1X8,
-         V4L2_PIX_FMT_SGBRG10, 10, },
+         V4L2_PIX_FMT_SGBRG10, 10, 2, },
        { V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG10_1X10,
          V4L2_MBUS_FMT_SGRBG10_1X10, V4L2_MBUS_FMT_SGRBG8_1X8,
-         V4L2_PIX_FMT_SGRBG10, 10, },
+         V4L2_PIX_FMT_SGRBG10, 10, 2, },
        { V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB10_1X10,
          V4L2_MBUS_FMT_SRGGB10_1X10, V4L2_MBUS_FMT_SRGGB8_1X8,
-         V4L2_PIX_FMT_SRGGB10, 10, },
+         V4L2_PIX_FMT_SRGGB10, 10, 2, },
        { V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR10_1X10,
          V4L2_MBUS_FMT_SBGGR12_1X12, V4L2_MBUS_FMT_SBGGR8_1X8,
-         V4L2_PIX_FMT_SBGGR12, 12, },
+         V4L2_PIX_FMT_SBGGR12, 12, 2, },
        { V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG10_1X10,
          V4L2_MBUS_FMT_SGBRG12_1X12, V4L2_MBUS_FMT_SGBRG8_1X8,
-         V4L2_PIX_FMT_SGBRG12, 12, },
+         V4L2_PIX_FMT_SGBRG12, 12, 2, },
        { V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG10_1X10,
          V4L2_MBUS_FMT_SGRBG12_1X12, V4L2_MBUS_FMT_SGRBG8_1X8,
-         V4L2_PIX_FMT_SGRBG12, 12, },
+         V4L2_PIX_FMT_SGRBG12, 12, 2, },
        { V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB10_1X10,
          V4L2_MBUS_FMT_SRGGB12_1X12, V4L2_MBUS_FMT_SRGGB8_1X8,
-         V4L2_PIX_FMT_SRGGB12, 12, },
+         V4L2_PIX_FMT_SRGGB12, 12, 2, },
        { V4L2_MBUS_FMT_UYVY8_1X16, V4L2_MBUS_FMT_UYVY8_1X16,
          V4L2_MBUS_FMT_UYVY8_1X16, 0,
-         V4L2_PIX_FMT_UYVY, 16, },
+         V4L2_PIX_FMT_UYVY, 16, 2, },
        { V4L2_MBUS_FMT_YUYV8_1X16, V4L2_MBUS_FMT_YUYV8_1X16,
          V4L2_MBUS_FMT_YUYV8_1X16, 0,
-         V4L2_PIX_FMT_YUYV, 16, },
+         V4L2_PIX_FMT_YUYV, 16, 2, },
+       { V4L2_MBUS_FMT_UYVY8_2X8, V4L2_MBUS_FMT_UYVY8_2X8,
+         V4L2_MBUS_FMT_UYVY8_2X8, 0,
+         V4L2_PIX_FMT_UYVY, 8, 2, },
+       { V4L2_MBUS_FMT_YUYV8_2X8, V4L2_MBUS_FMT_YUYV8_2X8,
+         V4L2_MBUS_FMT_YUYV8_2X8, 0,
+         V4L2_PIX_FMT_YUYV, 8, 2, },
+       /* Empty entry to catch the unsupported pixel code (0) used by the CCDC
+        * module and avoid NULL pointer dereferences.
+        */
+       { 0, }
 };
 
 const struct isp_format_info *
@@ -161,7 +171,7 @@ static unsigned int isp_video_mbus_to_pix(const struct isp_video *video,
        if (WARN_ON(i == ARRAY_SIZE(formats)))
                return 0;
 
-       min_bpl = pix->width * ALIGN(formats[i].bpp, 8) / 8;
+       min_bpl = pix->width * formats[i].bpp;
 
        /* Clamp the requested bytes per line value. If the maximum bytes per
         * line value is zero, the module doesn't support user configurable line
@@ -723,7 +733,7 @@ isp_video_try_format(struct file *file, void *fh, struct v4l2_format *format)
        fmt.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &fmt);
        if (ret)
-               return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+               return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 
        isp_video_mbus_to_pix(video, &fmt.format, &format->fmt.pix);
        return 0;
@@ -744,7 +754,7 @@ isp_video_cropcap(struct file *file, void *fh, struct v4l2_cropcap *cropcap)
        ret = v4l2_subdev_call(subdev, video, cropcap, cropcap);
        mutex_unlock(&video->mutex);
 
-       return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 }
 
 static int
@@ -771,7 +781,7 @@ isp_video_get_crop(struct file *file, void *fh, struct v4l2_crop *crop)
        format.which = V4L2_SUBDEV_FORMAT_ACTIVE;
        ret = v4l2_subdev_call(subdev, pad, get_fmt, NULL, &format);
        if (ret < 0)
-               return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+               return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 
        crop->c.left = 0;
        crop->c.top = 0;
@@ -796,7 +806,7 @@ isp_video_set_crop(struct file *file, void *fh, struct v4l2_crop *crop)
        ret = v4l2_subdev_call(subdev, video, s_crop, crop);
        mutex_unlock(&video->mutex);
 
-       return ret == -ENOIOCTLCMD ? -EINVAL : ret;
+       return ret == -ENOIOCTLCMD ? -ENOTTY : ret;
 }
 
 static int
@@ -921,7 +931,8 @@ static int isp_video_check_external_subdevs(struct isp_video *video,
                return ret;
        }
 
-       pipe->external_bpp = omap3isp_video_format_info(fmt.format.code)->bpp;
+       pipe->external_width =
+               omap3isp_video_format_info(fmt.format.code)->width;
 
        memset(&ctrls, 0, sizeof(ctrls));
        memset(&ctrl, 0, sizeof(ctrl));
@@ -1331,6 +1342,7 @@ int omap3isp_video_init(struct isp_video *video, const char *name)
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
                direction = "input";
                video->pad.flags = MEDIA_PAD_FL_SOURCE;
+               video->video.vfl_dir = VFL_DIR_TX;
                break;
 
        default:
similarity index 97%
rename from drivers/media/video/omap3isp/ispvideo.h
rename to drivers/media/platform/omap3isp/ispvideo.h
index 5acc909500ec0c52db0537201c88d01b2ca612d7..1ad470ec2b9d5ab5f4cd212f11d0b3d412d93b20 100644 (file)
@@ -51,7 +51,8 @@ struct v4l2_pix_format;
  * @flavor: V4L2 media bus format code for the same pixel layout but
  *     shifted to be 8 bits per pixel. =0 if format is not shiftable.
  * @pixelformat: V4L2 pixel format FCC identifier
- * @bpp: Bits per pixel
+ * @width: Bits per pixel (when transferred over a bus)
+ * @bpp: Bytes per pixel (when stored in memory)
  */
 struct isp_format_info {
        enum v4l2_mbus_pixelcode code;
@@ -59,6 +60,7 @@ struct isp_format_info {
        enum v4l2_mbus_pixelcode uncompressed;
        enum v4l2_mbus_pixelcode flavor;
        u32 pixelformat;
+       unsigned int width;
        unsigned int bpp;
 };
 
@@ -106,7 +108,7 @@ struct isp_pipeline {
        struct v4l2_fract max_timeperframe;
        struct v4l2_subdev *external;
        unsigned int external_rate;
-       unsigned int external_bpp;
+       unsigned int external_width;
 };
 
 #define to_isp_pipeline(__e) \
similarity index 96%
rename from drivers/media/video/s5p-fimc/Kconfig
rename to drivers/media/platform/s5p-fimc/Kconfig
index a564f7eeb064a337643f9d6c44b0a713e75fd3c1..8f090a8f270e7465b018940a2eb9fd6dba33eeaf 100644 (file)
@@ -31,7 +31,7 @@ config VIDEO_S5P_MIPI_CSIS
          To compile this driver as a module, choose M here: the
          module will be called s5p-csis.
 
-if ARCH_EXYNOS
+if SOC_EXYNOS4212 || SOC_EXYNOS4412 || SOC_EXYNOS5250
 
 config VIDEO_EXYNOS_FIMC_LITE
        tristate "EXYNOS FIMC-LITE camera interface driver"
similarity index 90%
rename from drivers/media/video/s5p-fimc/fimc-capture.c
rename to drivers/media/platform/s5p-fimc/fimc-capture.c
index 8e413dd3c0b098a5811f87add3113efc5bd2844e..367efd164d0f1c9580111b12b51c8e2a9f225bfa 100644 (file)
@@ -50,9 +50,9 @@ static int fimc_capture_hw_init(struct fimc_dev *fimc)
        fimc_prepare_dma_offset(ctx, &ctx->d_frame);
        fimc_set_yuv_order(ctx);
 
-       fimc_hw_set_camera_polarity(fimc, sensor->pdata);
-       fimc_hw_set_camera_type(fimc, sensor->pdata);
-       fimc_hw_set_camera_source(fimc, sensor->pdata);
+       fimc_hw_set_camera_polarity(fimc, &sensor->pdata);
+       fimc_hw_set_camera_type(fimc, &sensor->pdata);
+       fimc_hw_set_camera_source(fimc, &sensor->pdata);
        fimc_hw_set_camera_offset(fimc, &ctx->s_frame);
 
        ret = fimc_set_scaler_info(ctx);
@@ -118,7 +118,8 @@ static int fimc_capture_state_cleanup(struct fimc_dev *fimc, bool suspend)
        spin_unlock_irqrestore(&fimc->slock, flags);
 
        if (streaming)
-               return fimc_pipeline_s_stream(&fimc->pipeline, 0);
+               return fimc_pipeline_call(fimc, set_stream,
+                                         &fimc->pipeline, 0);
        else
                return 0;
 }
@@ -176,7 +177,9 @@ static int fimc_capture_config_update(struct fimc_ctx *ctx)
 
 void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
 {
+       struct v4l2_subdev *csis = fimc->pipeline.subdevs[IDX_CSIS];
        struct fimc_vid_cap *cap = &fimc->vid_cap;
+       struct fimc_frame *f = &cap->ctx->d_frame;
        struct fimc_vid_buffer *v_buf;
        struct timeval *tv;
        struct timespec ts;
@@ -215,6 +218,25 @@ void fimc_capture_irq_handler(struct fimc_dev *fimc, int deq_buf)
                if (++cap->buf_index >= FIMC_MAX_OUT_BUFS)
                        cap->buf_index = 0;
        }
+       /*
+        * Set up a buffer at MIPI-CSIS if current image format
+        * requires the frame embedded data capture.
+        */
+       if (f->fmt->mdataplanes && !list_empty(&cap->active_buf_q)) {
+               unsigned int plane = ffs(f->fmt->mdataplanes) - 1;
+               unsigned int size = f->payload[plane];
+               s32 index = fimc_hw_get_frame_index(fimc);
+               void *vaddr;
+
+               list_for_each_entry(v_buf, &cap->active_buf_q, list) {
+                       if (v_buf->index != index)
+                               continue;
+                       vaddr = vb2_plane_vaddr(&v_buf->vb, plane);
+                       v4l2_subdev_call(csis, video, s_rx_buffer,
+                                        vaddr, &size);
+                       break;
+               }
+       }
 
        if (cap->active_buf_cnt == 0) {
                if (deq_buf)
@@ -264,7 +286,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
                fimc_activate_capture(ctx);
 
                if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
        }
 
        return 0;
@@ -288,7 +311,7 @@ int fimc_capture_suspend(struct fimc_dev *fimc)
        int ret = fimc_stop_capture(fimc, suspend);
        if (ret)
                return ret;
-       return fimc_pipeline_shutdown(&fimc->pipeline);
+       return fimc_pipeline_call(fimc, close, &fimc->pipeline);
 }
 
 static void buffer_queue(struct vb2_buffer *vb);
@@ -304,8 +327,8 @@ int fimc_capture_resume(struct fimc_dev *fimc)
 
        INIT_LIST_HEAD(&fimc->vid_cap.active_buf_q);
        vid_cap->buf_index = 0;
-       fimc_pipeline_initialize(&fimc->pipeline, &vid_cap->vfd->entity,
-                                false);
+       fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                          &vid_cap->vfd.entity, false);
        fimc_capture_hw_init(fimc);
 
        clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
@@ -349,6 +372,8 @@ static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *pfmt,
                unsigned int size = (wh * fmt->depth[i]) / 8;
                if (pixm)
                        sizes[i] = max(size, pixm->plane_fmt[i].sizeimage);
+               else if (fimc_fmt_is_user_defined(fmt->color))
+                       sizes[i] = frame->payload[i];
                else
                        sizes[i] = max_t(u32, size, frame->payload[i]);
 
@@ -371,7 +396,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
                unsigned long size = ctx->d_frame.payload[i];
 
                if (vb2_plane_size(vb, i) < size) {
-                       v4l2_err(ctx->fimc_dev->vid_cap.vfd,
+                       v4l2_err(&ctx->fimc_dev->vid_cap.vfd,
                                 "User buffer too small (%ld < %ld)\n",
                                 vb2_plane_size(vb, i), size);
                        return -EINVAL;
@@ -422,7 +447,8 @@ static void buffer_queue(struct vb2_buffer *vb)
                spin_unlock_irqrestore(&fimc->slock, flags);
 
                if (!test_and_set_bit(ST_CAPT_ISP_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
                return;
        }
        spin_unlock_irqrestore(&fimc->slock, flags);
@@ -472,7 +498,7 @@ int fimc_capture_ctrls_create(struct fimc_dev *fimc)
                return ret;
 
        return v4l2_ctrl_add_handler(&vid_cap->ctx->ctrls.handler,
-                   fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler);
+                   fimc->pipeline.subdevs[IDX_SENSOR]->ctrl_handler, NULL);
 }
 
 static int fimc_capture_set_default_format(struct fimc_dev *fimc);
@@ -502,8 +528,8 @@ static int fimc_capture_open(struct file *file)
        }
 
        if (++fimc->vid_cap.refcnt == 1) {
-               ret = fimc_pipeline_initialize(&fimc->pipeline,
-                                      &fimc->vid_cap.vfd->entity, true);
+               ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                                        &fimc->vid_cap.vfd.entity, true);
 
                if (!ret && !fimc->vid_cap.user_subdev_api)
                        ret = fimc_capture_set_default_format(fimc);
@@ -536,7 +562,7 @@ static int fimc_capture_close(struct file *file)
        if (--fimc->vid_cap.refcnt == 0) {
                clear_bit(ST_CAPT_BUSY, &fimc->state);
                fimc_stop_capture(fimc, false);
-               fimc_pipeline_shutdown(&fimc->pipeline);
+               fimc_pipeline_call(fimc, close, &fimc->pipeline);
                clear_bit(ST_CAPT_SUSPENDED, &fimc->state);
        }
 
@@ -608,10 +634,10 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
        u32 mask = FMT_FLAGS_CAM;
        struct fimc_fmt *ffmt;
 
-       /* Color conversion from/to JPEG is not supported */
+       /* Conversion from/to JPEG or User Defined format is not supported */
        if (code && ctx->s_frame.fmt && pad == FIMC_SD_PAD_SOURCE &&
-           fimc_fmt_is_jpeg(ctx->s_frame.fmt->color))
-               *code = V4L2_MBUS_FMT_JPEG_1X8;
+           fimc_fmt_is_user_defined(ctx->s_frame.fmt->color))
+               *code = ctx->s_frame.fmt->mbus_code;
 
        if (fourcc && *fourcc != V4L2_PIX_FMT_JPEG && pad != FIMC_SD_PAD_SINK)
                mask |= FMT_FLAGS_M2M;
@@ -625,18 +651,19 @@ static struct fimc_fmt *fimc_capture_try_format(struct fimc_ctx *ctx,
                *fourcc = ffmt->fourcc;
 
        if (pad == FIMC_SD_PAD_SINK) {
-               max_w = fimc_fmt_is_jpeg(ffmt->color) ?
+               max_w = fimc_fmt_is_user_defined(ffmt->color) ?
                        pl->scaler_dis_w : pl->scaler_en_w;
                /* Apply the camera input interface pixel constraints */
                v4l_bound_align_image(width, max_t(u32, *width, 32), max_w, 4,
                                      height, max_t(u32, *height, 32),
                                      FIMC_CAMIF_MAX_HEIGHT,
-                                     fimc_fmt_is_jpeg(ffmt->color) ? 3 : 1,
+                                     fimc_fmt_is_user_defined(ffmt->color) ?
+                                     3 : 1,
                                      0);
                return ffmt;
        }
        /* Can't scale or crop in transparent (JPEG) transfer mode */
-       if (fimc_fmt_is_jpeg(ffmt->color)) {
+       if (fimc_fmt_is_user_defined(ffmt->color)) {
                *width  = ctx->s_frame.f_width;
                *height = ctx->s_frame.f_height;
                return ffmt;
@@ -681,7 +708,7 @@ static void fimc_capture_try_selection(struct fimc_ctx *ctx,
        u32 max_sc_h, max_sc_v;
 
        /* In JPEG transparent transfer mode cropping is not supported */
-       if (fimc_fmt_is_jpeg(ctx->d_frame.fmt->color)) {
+       if (fimc_fmt_is_user_defined(ctx->d_frame.fmt->color)) {
                r->width  = sink->f_width;
                r->height = sink->f_height;
                r->left   = r->top = 0;
@@ -844,6 +871,48 @@ static int fimc_pipeline_try_format(struct fimc_ctx *ctx,
        return 0;
 }
 
+/**
+ * fimc_get_sensor_frame_desc - query the sensor for media bus frame parameters
+ * @sensor: pointer to the sensor subdev
+ * @plane_fmt: provides plane sizes corresponding to the frame layout entries
+ * @try: true to set the frame parameters, false to query only
+ *
+ * This function is used by this driver only for compressed/blob data formats.
+ */
+static int fimc_get_sensor_frame_desc(struct v4l2_subdev *sensor,
+                                     struct v4l2_plane_pix_format *plane_fmt,
+                                     unsigned int num_planes, bool try)
+{
+       struct v4l2_mbus_frame_desc fd;
+       int i, ret;
+
+       for (i = 0; i < num_planes; i++)
+               fd.entry[i].length = plane_fmt[i].sizeimage;
+
+       if (try)
+               ret = v4l2_subdev_call(sensor, pad, set_frame_desc, 0, &fd);
+       else
+               ret = v4l2_subdev_call(sensor, pad, get_frame_desc, 0, &fd);
+
+       if (ret < 0)
+               return ret;
+
+       if (num_planes != fd.num_entries)
+               return -EINVAL;
+
+       for (i = 0; i < num_planes; i++)
+               plane_fmt[i].sizeimage = fd.entry[i].length;
+
+       if (fd.entry[0].length > FIMC_MAX_JPEG_BUF_SIZE) {
+               v4l2_err(sensor->v4l2_dev,  "Unsupported buffer size: %u\n",
+                        fd.entry[0].length);
+
+               return -EINVAL;
+       }
+
+       return 0;
+}
+
 static int fimc_cap_g_fmt_mplane(struct file *file, void *fh,
                                 struct v4l2_format *f)
 {
@@ -862,7 +931,7 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
        struct v4l2_mbus_framefmt mf;
        struct fimc_fmt *ffmt = NULL;
 
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -876,25 +945,32 @@ static int fimc_cap_try_fmt_mplane(struct file *file, void *fh,
                return -EINVAL;
 
        if (!fimc->vid_cap.user_subdev_api) {
-               mf.width  = pix->width;
+               mf.width = pix->width;
                mf.height = pix->height;
-               mf.code   = ffmt->mbus_code;
+               mf.code = ffmt->mbus_code;
                fimc_md_graph_lock(fimc);
                fimc_pipeline_try_format(ctx, &mf, &ffmt, false);
                fimc_md_graph_unlock(fimc);
-
-               pix->width       = mf.width;
-               pix->height      = mf.height;
+               pix->width = mf.width;
+               pix->height = mf.height;
                if (ffmt)
                        pix->pixelformat = ffmt->fourcc;
        }
 
        fimc_adjust_mplane_format(ffmt, pix->width, pix->height, pix);
+
+       if (ffmt->flags & FMT_FLAGS_COMPRESSED)
+               fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ffmt->memplanes, true);
+
        return 0;
 }
 
-static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx, bool jpeg)
+static void fimc_capture_mark_jpeg_xfer(struct fimc_ctx *ctx,
+                                       enum fimc_color_fmt color)
 {
+       bool jpeg = fimc_fmt_is_user_defined(color);
+
        ctx->scaler.enabled = !jpeg;
        fimc_ctrls_activate(ctx, !jpeg);
 
@@ -917,7 +993,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
                return -EBUSY;
 
        /* Pre-configure format at camera interface input, for JPEG only */
-       if (pix->pixelformat == V4L2_PIX_FMT_JPEG) {
+       if (fimc_jpeg_fourcc(pix->pixelformat)) {
                fimc_capture_try_format(ctx, &pix->width, &pix->height,
                                        NULL, &pix->pixelformat,
                                        FIMC_SD_PAD_SINK);
@@ -950,7 +1026,16 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        }
 
        fimc_adjust_mplane_format(ff->fmt, pix->width, pix->height, pix);
-       for (i = 0; i < ff->fmt->colplanes; i++)
+
+       if (ff->fmt->flags & FMT_FLAGS_COMPRESSED) {
+               ret = fimc_get_sensor_frame_desc(fimc->pipeline.subdevs[IDX_SENSOR],
+                                       pix->plane_fmt, ff->fmt->memplanes,
+                                       true);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 0; i < ff->fmt->memplanes; i++)
                ff->payload[i] = pix->plane_fmt[i].sizeimage;
 
        set_frame_bounds(ff, pix->width, pix->height);
@@ -958,7 +1043,7 @@ static int fimc_capture_set_format(struct fimc_dev *fimc, struct v4l2_format *f)
        if (!(ctx->state & FIMC_COMPOSE))
                set_frame_crop(ff, 0, 0, pix->width, pix->height);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ff->fmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ff->fmt->color);
 
        /* Reset cropping and set format at the camera interface input */
        if (!fimc->vid_cap.user_subdev_api) {
@@ -1060,6 +1145,23 @@ static int fimc_pipeline_validate(struct fimc_dev *fimc)
                    src_fmt.format.height != sink_fmt.format.height ||
                    src_fmt.format.code != sink_fmt.format.code)
                        return -EPIPE;
+
+               if (sd == fimc->pipeline.subdevs[IDX_SENSOR] &&
+                   fimc_user_defined_mbus_fmt(src_fmt.format.code)) {
+                       struct v4l2_plane_pix_format plane_fmt[FIMC_MAX_PLANES];
+                       struct fimc_frame *frame = &vid_cap->ctx->d_frame;
+                       unsigned int i;
+
+                       ret = fimc_get_sensor_frame_desc(sd, plane_fmt,
+                                                        frame->fmt->memplanes,
+                                                        false);
+                       if (ret < 0)
+                               return -EPIPE;
+
+                       for (i = 0; i < frame->fmt->memplanes; i++)
+                               if (frame->payload[i] < plane_fmt[i].sizeimage)
+                                       return -EPIPE;
+               }
        }
        return 0;
 }
@@ -1421,7 +1523,7 @@ static int fimc_subdev_set_fmt(struct v4l2_subdev *sd,
        /* Update RGB Alpha control state and value range */
        fimc_alpha_ctrl_update(ctx);
 
-       fimc_capture_mark_jpeg_xfer(ctx, fimc_fmt_is_jpeg(ffmt->color));
+       fimc_capture_mark_jpeg_xfer(ctx, ffmt->color);
 
        ff = fmt->pad == FIMC_SD_PAD_SINK ?
                &ctx->s_frame : &ctx->d_frame;
@@ -1587,13 +1689,13 @@ static int fimc_capture_set_default_format(struct fimc_dev *fimc)
 static int fimc_register_capture_device(struct fimc_dev *fimc,
                                 struct v4l2_device *v4l2_dev)
 {
-       struct video_device *vfd;
+       struct video_device *vfd = &fimc->vid_cap.vfd;
        struct fimc_vid_cap *vid_cap;
        struct fimc_ctx *ctx;
        struct vb2_queue *q;
        int ret = -ENOMEM;
 
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
@@ -1604,25 +1706,19 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
        ctx->s_frame.fmt = fimc_find_format(NULL, NULL, FMT_FLAGS_CAM, 0);
        ctx->d_frame.fmt = ctx->s_frame.fmt;
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(v4l2_dev, "Failed to allocate video device\n");
-               goto err_vd_alloc;
-       }
-
+       memset(vfd, 0, sizeof(*vfd));
        snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.capture", fimc->id);
 
        vfd->fops       = &fimc_capture_fops;
        vfd->ioctl_ops  = &fimc_capture_ioctl_ops;
        vfd->v4l2_dev   = v4l2_dev;
        vfd->minor      = -1;
-       vfd->release    = video_device_release;
+       vfd->release    = video_device_release_empty;
        vfd->lock       = &fimc->lock;
 
        video_set_drvdata(vfd, fimc);
 
        vid_cap = &fimc->vid_cap;
-       vid_cap->vfd = vfd;
        vid_cap->active_buf_cnt = 0;
        vid_cap->reqbufs_count  = 0;
        vid_cap->refcnt = 0;
@@ -1660,8 +1756,6 @@ static int fimc_register_capture_device(struct fimc_dev *fimc,
 err_vd:
        media_entity_cleanup(&vfd->entity);
 err_ent:
-       video_device_release(vfd);
-err_vd_alloc:
        kfree(ctx);
        return ret;
 }
@@ -1671,6 +1765,9 @@ static int fimc_capture_subdev_registered(struct v4l2_subdev *sd)
        struct fimc_dev *fimc = v4l2_get_subdevdata(sd);
        int ret;
 
+       if (fimc == NULL)
+               return -ENXIO;
+
        ret = fimc_register_m2m_device(fimc, sd->v4l2_dev);
        if (ret)
                return ret;
@@ -1691,12 +1788,10 @@ static void fimc_capture_subdev_unregistered(struct v4l2_subdev *sd)
 
        fimc_unregister_m2m_device(fimc);
 
-       if (fimc->vid_cap.vfd) {
-               media_entity_cleanup(&fimc->vid_cap.vfd->entity);
-               video_unregister_device(fimc->vid_cap.vfd);
-               fimc->vid_cap.vfd = NULL;
+       if (video_is_registered(&fimc->vid_cap.vfd)) {
+               video_unregister_device(&fimc->vid_cap.vfd);
+               media_entity_cleanup(&fimc->vid_cap.vfd.entity);
        }
-
        kfree(fimc->vid_cap.ctx);
        fimc->vid_cap.ctx = NULL;
 }
similarity index 98%
rename from drivers/media/video/s5p-fimc/fimc-core.c
rename to drivers/media/platform/s5p-fimc/fimc-core.c
index 1a445404e73d2bea57a2e788e21717a7f21fb6ac..8d0d2b94a135f45b0d8fa2c1378fd287aff7ef27 100644 (file)
@@ -184,7 +184,17 @@ static struct fimc_fmt fimc_formats[] = {
                .memplanes      = 1,
                .colplanes      = 1,
                .mbus_code      = V4L2_MBUS_FMT_JPEG_1X8,
-               .flags          = FMT_FLAGS_CAM,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
+       }, {
+               .name           = "S5C73MX interleaved UYVY/JPEG",
+               .fourcc         = V4L2_PIX_FMT_S5C_UYVY_JPG,
+               .color          = FIMC_FMT_YUYV_JPEG,
+               .depth          = { 8 },
+               .memplanes      = 2,
+               .colplanes      = 1,
+               .mdataplanes    = 0x2, /* plane 1 holds frame meta data */
+               .mbus_code      = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .flags          = FMT_FLAGS_CAM | FMT_FLAGS_COMPRESSED,
        },
 };
 
@@ -371,7 +381,7 @@ int fimc_prepare_addr(struct fimc_ctx *ctx, struct vb2_buffer *vb,
                default:
                        return -EINVAL;
                }
-       } else {
+       } else if (!frame->fmt->mdataplanes) {
                if (frame->fmt->memplanes >= 2)
                        paddr->cb = vb2_dma_contig_plane_dma_addr(vb, 1);
 
@@ -698,6 +708,11 @@ int fimc_fill_format(struct fimc_frame *frame, struct v4l2_format *f)
                if (frame->fmt->colplanes == 1) /* packed formats */
                        bpl = (bpl * frame->fmt->depth[0]) / 8;
                pixm->plane_fmt[i].bytesperline = bpl;
+
+               if (frame->fmt->flags & FMT_FLAGS_COMPRESSED) {
+                       pixm->plane_fmt[i].sizeimage = frame->payload[i];
+                       continue;
+               }
                pixm->plane_fmt[i].sizeimage = (frame->o_width *
                        frame->o_height * frame->fmt->depth[i]) / 8;
        }
similarity index 96%
rename from drivers/media/video/s5p-fimc/fimc-core.h
rename to drivers/media/platform/s5p-fimc/fimc-core.h
index 808ccc621846fee63d2c4aa762e4a81e63f4490e..c0040d7924995051e71faaed70942cb2b74ec7c6 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/types.h>
 #include <linux/videodev2.h>
 #include <linux/io.h>
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 
 #include <media/media-entity.h>
 #include <media/videobuf2-core.h>
@@ -40,6 +40,8 @@
 #define SCALER_MAX_VRATIO      64
 #define DMA_MIN_SIZE           8
 #define FIMC_CAMIF_MAX_HEIGHT  0x2000
+#define FIMC_MAX_JPEG_BUF_SIZE (10 * SZ_1M)
+#define FIMC_MAX_PLANES                3
 
 /* indices to the clocks array */
 enum {
@@ -83,7 +85,7 @@ enum fimc_datapath {
 };
 
 enum fimc_color_fmt {
-       FIMC_FMT_RGB444 = 0x10,
+       FIMC_FMT_RGB444 = 0x10,
        FIMC_FMT_RGB555,
        FIMC_FMT_RGB565,
        FIMC_FMT_RGB666,
@@ -95,14 +97,15 @@ enum fimc_color_fmt {
        FIMC_FMT_CBYCRY422,
        FIMC_FMT_CRYCBY422,
        FIMC_FMT_YCBCR444_LOCAL,
-       FIMC_FMT_JPEG = 0x40,
-       FIMC_FMT_RAW8 = 0x80,
+       FIMC_FMT_RAW8 = 0x40,
        FIMC_FMT_RAW10,
        FIMC_FMT_RAW12,
+       FIMC_FMT_JPEG = 0x80,
+       FIMC_FMT_YUYV_JPEG = 0x100,
 };
 
+#define fimc_fmt_is_user_defined(x) (!!((x) & 0x180))
 #define fimc_fmt_is_rgb(x) (!!((x) & 0x10))
-#define fimc_fmt_is_jpeg(x) (!!((x) & 0x40))
 
 #define IS_M2M(__strt) ((__strt) == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE || \
                        __strt == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
@@ -139,6 +142,7 @@ enum fimc_color_fmt {
  * @memplanes: number of physically non-contiguous data planes
  * @colplanes: number of physically contiguous data planes
  * @depth: per plane driver's private 'number of bits per pixel'
+ * @mdataplanes: bitmask indicating meta data plane(s), (1 << plane_no)
  * @flags: flags indicating which operation mode format applies to
  */
 struct fimc_fmt {
@@ -149,12 +153,14 @@ struct fimc_fmt {
        u16     memplanes;
        u16     colplanes;
        u8      depth[VIDEO_MAX_PLANES];
+       u16     mdataplanes;
        u16     flags;
 #define FMT_FLAGS_CAM          (1 << 0)
 #define FMT_FLAGS_M2M_IN       (1 << 1)
 #define FMT_FLAGS_M2M_OUT      (1 << 2)
 #define FMT_FLAGS_M2M          (1 << 1 | 1 << 2)
 #define FMT_HAS_ALPHA          (1 << 3)
+#define FMT_FLAGS_COMPRESSED   (1 << 4)
 };
 
 /**
@@ -272,7 +278,7 @@ struct fimc_frame {
        u32     offs_v;
        u32     width;
        u32     height;
-       unsigned long           payload[VIDEO_MAX_PLANES];
+       unsigned int            payload[VIDEO_MAX_PLANES];
        struct fimc_addr        paddr;
        struct fimc_dma_offset  dma_offset;
        struct fimc_fmt         *fmt;
@@ -287,7 +293,7 @@ struct fimc_frame {
  * @refcnt: the reference counter
  */
 struct fimc_m2m_device {
-       struct video_device     *vfd;
+       struct video_device     vfd;
        struct v4l2_m2m_dev     *m2m_dev;
        struct fimc_ctx         *ctx;
        int                     refcnt;
@@ -320,7 +326,7 @@ struct fimc_m2m_device {
 struct fimc_vid_cap {
        struct fimc_ctx                 *ctx;
        struct vb2_alloc_ctx            *alloc_ctx;
-       struct video_device             *vfd;
+       struct video_device             vfd;
        struct v4l2_subdev              subdev;
        struct media_pad                vd_pad;
        struct v4l2_mbus_framefmt       mf;
@@ -440,6 +446,7 @@ struct fimc_dev {
        unsigned long                   state;
        struct vb2_alloc_ctx            *alloc_ctx;
        struct fimc_pipeline            pipeline;
+       const struct fimc_pipeline_ops  *pipeline_ops;
 };
 
 /**
@@ -576,6 +583,18 @@ static inline int tiled_fmt(struct fimc_fmt *fmt)
        return fmt->fourcc == V4L2_PIX_FMT_NV12MT;
 }
 
+static inline bool fimc_jpeg_fourcc(u32 pixelformat)
+{
+       return (pixelformat == V4L2_PIX_FMT_JPEG ||
+               pixelformat == V4L2_PIX_FMT_S5C_UYVY_JPG);
+}
+
+static inline bool fimc_user_defined_mbus_fmt(u32 code)
+{
+       return (code == V4L2_MBUS_FMT_JPEG_1X8 ||
+               code == V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8);
+}
+
 /* Return the alpha component bit mask */
 static inline int fimc_get_alpha_mask(struct fimc_fmt *fmt)
 {
similarity index 97%
rename from drivers/media/video/s5p-fimc/fimc-lite-reg.c
rename to drivers/media/platform/s5p-fimc/fimc-lite-reg.c
index f996e94873f68d3d03803997497ff4458c9166bb..a22d7eb05c828b56f6083bd8782be258d98a8443 100644 (file)
@@ -118,9 +118,9 @@ static const u32 src_pixfmt_map[8][3] = {
          FLITE_REG_CIGCTRL_YUV422_1P },
        { V4L2_MBUS_FMT_VYUY8_2X8, FLITE_REG_CISRCSIZE_ORDER422_IN_CRYCBY,
          FLITE_REG_CIGCTRL_YUV422_1P },
-       { V4L2_PIX_FMT_SGRBG8, 0, FLITE_REG_CIGCTRL_RAW8 },
-       { V4L2_PIX_FMT_SGRBG10, 0, FLITE_REG_CIGCTRL_RAW10 },
-       { V4L2_PIX_FMT_SGRBG12, 0, FLITE_REG_CIGCTRL_RAW12 },
+       { V4L2_MBUS_FMT_SGRBG8_1X8, 0, FLITE_REG_CIGCTRL_RAW8 },
+       { V4L2_MBUS_FMT_SGRBG10_1X10, 0, FLITE_REG_CIGCTRL_RAW10 },
+       { V4L2_MBUS_FMT_SGRBG12_1X12, 0, FLITE_REG_CIGCTRL_RAW12 },
        { V4L2_MBUS_FMT_JPEG_1X8, 0, FLITE_REG_CIGCTRL_USER(1) },
 };
 
@@ -137,7 +137,7 @@ void flite_hw_set_source_format(struct fimc_lite *dev, struct flite_frame *f)
        }
 
        if (i == 0 && src_pixfmt_map[i][0] != pixelcode) {
-               v4l2_err(dev->vfd,
+               v4l2_err(&dev->vfd,
                         "Unsupported pixel code, falling back to %#08x\n",
                         src_pixfmt_map[i][0]);
        }
similarity index 97%
rename from drivers/media/video/s5p-fimc/fimc-lite.c
rename to drivers/media/platform/s5p-fimc/fimc-lite.c
index c5b57e805b683d072577ddfa242ea6f9a365583c..70bcf39de87994f99dc38ae11c1a2c115d56433d 100644 (file)
 #include <media/v4l2-mem2mem.h>
 #include <media/videobuf2-core.h>
 #include <media/videobuf2-dma-contig.h>
+#include <media/s5p_fimc.h>
 
 #include "fimc-mdevice.h"
 #include "fimc-core.h"
+#include "fimc-lite.h"
 #include "fimc-lite-reg.h"
 
 static int debug;
@@ -133,7 +135,7 @@ static int fimc_lite_hw_init(struct fimc_lite *fimc)
        sensor = v4l2_get_subdev_hostdata(pipeline->subdevs[IDX_SENSOR]);
        spin_lock_irqsave(&fimc->slock, flags);
 
-       flite_hw_set_camera_bus(fimc, sensor->pdata);
+       flite_hw_set_camera_bus(fimc, &sensor->pdata);
        flite_hw_set_source_format(fimc, &fimc->inp_frame);
        flite_hw_set_window_offset(fimc, &fimc->inp_frame);
        flite_hw_set_output_dma(fimc, &fimc->out_frame, true);
@@ -193,7 +195,7 @@ static int fimc_lite_reinit(struct fimc_lite *fimc, bool suspend)
        if (!streaming)
                return 0;
 
-       return fimc_pipeline_s_stream(&fimc->pipeline, 0);
+       return fimc_pipeline_call(fimc, set_stream, &fimc->pipeline, 0);
 }
 
 static int fimc_lite_stop_capture(struct fimc_lite *fimc, bool suspend)
@@ -307,7 +309,8 @@ static int start_streaming(struct vb2_queue *q, unsigned int count)
                flite_hw_capture_start(fimc);
 
                if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
        }
        if (debug > 0)
                flite_hw_dump_regs(fimc, __func__);
@@ -374,7 +377,7 @@ static int buffer_prepare(struct vb2_buffer *vb)
                unsigned long size = fimc->payload[i];
 
                if (vb2_plane_size(vb, i) < size) {
-                       v4l2_err(fimc->vfd,
+                       v4l2_err(&fimc->vfd,
                                 "User buffer too small (%ld < %ld)\n",
                                 vb2_plane_size(vb, i), size);
                        return -EINVAL;
@@ -411,7 +414,8 @@ static void buffer_queue(struct vb2_buffer *vb)
                spin_unlock_irqrestore(&fimc->slock, flags);
 
                if (!test_and_set_bit(ST_SENSOR_STREAM, &fimc->state))
-                       fimc_pipeline_s_stream(&fimc->pipeline, 1);
+                       fimc_pipeline_call(fimc, set_stream,
+                                          &fimc->pipeline, 1);
                return;
        }
        spin_unlock_irqrestore(&fimc->slock, flags);
@@ -466,8 +470,8 @@ static int fimc_lite_open(struct file *file)
                goto done;
 
        if (++fimc->ref_count == 1 && fimc->out_path == FIMC_IO_DMA) {
-               ret = fimc_pipeline_initialize(&fimc->pipeline,
-                                              &fimc->vfd->entity, true);
+               ret = fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                                        &fimc->vfd.entity, true);
                if (ret < 0) {
                        pm_runtime_put_sync(&fimc->pdev->dev);
                        fimc->ref_count--;
@@ -493,7 +497,7 @@ static int fimc_lite_close(struct file *file)
        if (--fimc->ref_count == 0 && fimc->out_path == FIMC_IO_DMA) {
                clear_bit(ST_FLITE_IN_USE, &fimc->state);
                fimc_lite_stop_capture(fimc, false);
-               fimc_pipeline_shutdown(&fimc->pipeline);
+               fimc_pipeline_call(fimc, close, &fimc->pipeline);
                clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
        }
 
@@ -825,7 +829,7 @@ static int fimc_lite_reqbufs(struct file *file, void *priv,
 
        reqbufs->count = max_t(u32, FLITE_REQ_BUFS_MIN, reqbufs->count);
        ret = vb2_reqbufs(&fimc->vb_queue, reqbufs);
-       if (!ret < 0)
+       if (!ret)
                fimc->reqbufs_count = reqbufs->count;
 
        return ret;
@@ -1064,6 +1068,7 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
        struct v4l2_mbus_framefmt *mf = &fmt->format;
        struct flite_frame *sink = &fimc->inp_frame;
+       struct flite_frame *source = &fimc->out_frame;
        const struct fimc_fmt *ffmt;
 
        v4l2_dbg(1, debug, sd, "pad%d: code: 0x%x, %dx%d",
@@ -1097,8 +1102,10 @@ static int fimc_lite_subdev_set_fmt(struct v4l2_subdev *sd,
                sink->rect.height = mf->height;
                sink->rect.left = 0;
                sink->rect.top = 0;
-               /* Reset source crop rectangle */
-               fimc->out_frame.rect = sink->rect;
+               /* Reset source format and crop rectangle */
+               source->rect = sink->rect;
+               source->f_width = mf->width;
+               source->f_height = mf->height;
        } else {
                /* Allow changing format only on sink pad */
                mf->code = fimc->fmt->mbus_code;
@@ -1215,18 +1222,14 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 {
        struct fimc_lite *fimc = v4l2_get_subdevdata(sd);
        struct vb2_queue *q = &fimc->vb_queue;
-       struct video_device *vfd;
+       struct video_device *vfd = &fimc->vfd;
        int ret;
 
+       memset(vfd, 0, sizeof(*vfd));
+
        fimc->fmt = &fimc_lite_formats[0];
        fimc->out_path = FIMC_IO_DMA;
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(sd->v4l2_dev, "Failed to allocate video device\n");
-               return -ENOMEM;
-       }
-
        snprintf(vfd->name, sizeof(vfd->name), "fimc-lite.%d.capture",
                 fimc->index);
 
@@ -1234,9 +1237,8 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
        vfd->ioctl_ops = &fimc_lite_ioctl_ops;
        vfd->v4l2_dev = sd->v4l2_dev;
        vfd->minor = -1;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &fimc->lock;
-       fimc->vfd = vfd;
        fimc->ref_count = 0;
        fimc->reqbufs_count = 0;
 
@@ -1255,24 +1257,20 @@ static int fimc_lite_subdev_registered(struct v4l2_subdev *sd)
 
        fimc->vd_pad.flags = MEDIA_PAD_FL_SINK;
        ret = media_entity_init(&vfd->entity, 1, &fimc->vd_pad, 0);
-       if (ret)
-               goto err;
+       if (ret < 0)
+               return ret;
 
        video_set_drvdata(vfd, fimc);
 
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, -1);
-       if (ret)
-               goto err_vd;
+       if (ret < 0) {
+               media_entity_cleanup(&vfd->entity);
+               return ret;
+       }
 
        v4l2_info(sd->v4l2_dev, "Registered %s as /dev/%s\n",
                  vfd->name, video_device_node_name(vfd));
        return 0;
-
- err_vd:
-       media_entity_cleanup(&vfd->entity);
- err:
-       video_device_release(vfd);
-       return ret;
 }
 
 static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
@@ -1282,10 +1280,9 @@ static void fimc_lite_subdev_unregistered(struct v4l2_subdev *sd)
        if (fimc == NULL)
                return;
 
-       if (fimc->vfd) {
-               video_unregister_device(fimc->vfd);
-               media_entity_cleanup(&fimc->vfd->entity);
-               fimc->vfd = NULL;
+       if (video_is_registered(&fimc->vfd)) {
+               video_unregister_device(&fimc->vfd);
+               media_entity_cleanup(&fimc->vfd.entity);
        }
 }
 
@@ -1515,7 +1512,8 @@ static int fimc_lite_resume(struct device *dev)
                return 0;
 
        INIT_LIST_HEAD(&fimc->active_buf_q);
-       fimc_pipeline_initialize(&fimc->pipeline, &fimc->vfd->entity, false);
+       fimc_pipeline_call(fimc, open, &fimc->pipeline,
+                          &fimc->vfd.entity, false);
        fimc_lite_hw_init(fimc);
        clear_bit(ST_FLITE_SUSPENDED, &fimc->state);
 
@@ -1541,7 +1539,7 @@ static int fimc_lite_suspend(struct device *dev)
        if (ret < 0 || !fimc_lite_active(fimc))
                return ret;
 
-       return fimc_pipeline_shutdown(&fimc->pipeline);
+       return fimc_pipeline_call(fimc, close, &fimc->pipeline);
 }
 #endif /* CONFIG_PM_SLEEP */
 
similarity index 97%
rename from drivers/media/video/s5p-fimc/fimc-lite.h
rename to drivers/media/platform/s5p-fimc/fimc-lite.h
index 44424eee81d89b63278f7ded8382d7a62b47241e..3081db35c5b0bfd60001f1e92483c22241adf1b7 100644 (file)
@@ -9,7 +9,7 @@
 #ifndef FIMC_LITE_H_
 #define FIMC_LITE_H_
 
-#include <asm/sizes.h>
+#include <linux/sizes.h>
 #include <linux/io.h>
 #include <linux/irqreturn.h>
 #include <linux/platform_device.h>
@@ -108,6 +108,7 @@ struct flite_buffer {
  * @test_pattern: test pattern controls
  * @index: FIMC-LITE platform device index
  * @pipeline: video capture pipeline data structure
+ * @pipeline_ops: media pipeline ops for the video node driver
  * @slock: spinlock protecting this data structure and the hw registers
  * @lock: mutex serializing video device and the subdev operations
  * @clock: FIMC-LITE gate clock
@@ -132,7 +133,7 @@ struct fimc_lite {
        struct platform_device  *pdev;
        struct flite_variant    *variant;
        struct v4l2_device      *v4l2_dev;
-       struct video_device     *vfd;
+       struct video_device     vfd;
        struct v4l2_fh          fh;
        struct vb2_alloc_ctx    *alloc_ctx;
        struct v4l2_subdev      subdev;
@@ -142,6 +143,7 @@ struct fimc_lite {
        struct v4l2_ctrl        *test_pattern;
        u32                     index;
        struct fimc_pipeline    pipeline;
+       const struct fimc_pipeline_ops *pipeline_ops;
 
        struct mutex            lock;
        spinlock_t              slock;
similarity index 93%
rename from drivers/media/video/s5p-fimc/fimc-m2m.c
rename to drivers/media/platform/s5p-fimc/fimc-m2m.c
index c587011d80eff668c8e1347d099e91d1fb33d427..4500e44f6857c909adcbd74cb13ad4dc2ac85cbc 100644 (file)
@@ -370,7 +370,7 @@ static int fimc_m2m_s_fmt_mplane(struct file *file, void *fh,
        vq = v4l2_m2m_get_vq(ctx->m2m_ctx, f->type);
 
        if (vb2_is_busy(vq)) {
-               v4l2_err(fimc->m2m.vfd, "queue (%d) busy\n", f->type);
+               v4l2_err(&fimc->m2m.vfd, "queue (%d) busy\n", f->type);
                return -EBUSY;
        }
 
@@ -507,7 +507,7 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
        int i;
 
        if (cr->c.top < 0 || cr->c.left < 0) {
-               v4l2_err(fimc->m2m.vfd,
+               v4l2_err(&fimc->m2m.vfd,
                        "doesn't support negative values for top & left\n");
                return -EINVAL;
        }
@@ -551,41 +551,42 @@ static int fimc_m2m_try_crop(struct fimc_ctx *ctx, struct v4l2_crop *cr)
        return 0;
 }
 
-static int fimc_m2m_s_crop(struct file *file, void *fh, struct v4l2_crop *cr)
+static int fimc_m2m_s_crop(struct file *file, void *fh, const struct v4l2_crop *crop)
 {
        struct fimc_ctx *ctx = fh_to_ctx(fh);
        struct fimc_dev *fimc = ctx->fimc_dev;
+       struct v4l2_crop cr = *crop;
        struct fimc_frame *f;
        int ret;
 
-       ret = fimc_m2m_try_crop(ctx, cr);
+       ret = fimc_m2m_try_crop(ctx, &cr);
        if (ret)
                return ret;
 
-       f = (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
+       f = (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) ?
                &ctx->s_frame : &ctx->d_frame;
 
        /* Check to see if scaling ratio is within supported range */
        if (fimc_ctx_state_is_set(FIMC_DST_FMT | FIMC_SRC_FMT, ctx)) {
-               if (cr->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
-                       ret = fimc_check_scaler_ratio(ctx, cr->c.width,
-                                       cr->c.height, ctx->d_frame.width,
+               if (cr.type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+                       ret = fimc_check_scaler_ratio(ctx, cr.c.width,
+                                       cr.c.height, ctx->d_frame.width,
                                        ctx->d_frame.height, ctx->rotation);
                } else {
                        ret = fimc_check_scaler_ratio(ctx, ctx->s_frame.width,
-                                       ctx->s_frame.height, cr->c.width,
-                                       cr->c.height, ctx->rotation);
+                                       ctx->s_frame.height, cr.c.width,
+                                       cr.c.height, ctx->rotation);
                }
                if (ret) {
-                       v4l2_err(fimc->m2m.vfd, "Out of scaler range\n");
+                       v4l2_err(&fimc->m2m.vfd, "Out of scaler range\n");
                        return -EINVAL;
                }
        }
 
-       f->offs_h = cr->c.left;
-       f->offs_v = cr->c.top;
-       f->width  = cr->c.width;
-       f->height = cr->c.height;
+       f->offs_h = cr.c.left;
+       f->offs_v = cr.c.top;
+       f->width  = cr.c.width;
+       f->height = cr.c.height;
 
        fimc_ctx_state_set(FIMC_PARAMS, ctx);
 
@@ -620,7 +621,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        struct fimc_ctx *ctx = priv;
        int ret;
 
-       memset(src_vq, 0, sizeof(*src_vq));
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE;
        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        src_vq->drv_priv = ctx;
@@ -632,7 +632,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        if (ret)
                return ret;
 
-       memset(dst_vq, 0, sizeof(*dst_vq));
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE;
        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        dst_vq->drv_priv = ctx;
@@ -661,12 +660,12 @@ static int fimc_m2m_open(struct file *file)
        if (fimc->vid_cap.refcnt > 0)
                goto unlock;
 
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                ret = -ENOMEM;
                goto unlock;
        }
-       v4l2_fh_init(&ctx->fh, fimc->m2m.vfd);
+       v4l2_fh_init(&ctx->fh, &fimc->m2m.vfd);
        ctx->fimc_dev = fimc;
 
        /* Default color format */
@@ -784,38 +783,27 @@ static struct v4l2_m2m_ops m2m_ops = {
 int fimc_register_m2m_device(struct fimc_dev *fimc,
                             struct v4l2_device *v4l2_dev)
 {
-       struct video_device *vfd;
-       struct platform_device *pdev;
-       int ret = 0;
-
-       if (!fimc)
-               return -ENODEV;
+       struct video_device *vfd = &fimc->m2m.vfd;
+       int ret;
 
-       pdev = fimc->pdev;
        fimc->v4l2_dev = v4l2_dev;
 
-       vfd = video_device_alloc();
-       if (!vfd) {
-               v4l2_err(v4l2_dev, "Failed to allocate video device\n");
-               return -ENOMEM;
-       }
-
+       memset(vfd, 0, sizeof(*vfd));
        vfd->fops = &fimc_m2m_fops;
        vfd->ioctl_ops = &fimc_m2m_ioctl_ops;
        vfd->v4l2_dev = v4l2_dev;
        vfd->minor = -1;
-       vfd->release = video_device_release;
+       vfd->release = video_device_release_empty;
        vfd->lock = &fimc->lock;
+       vfd->vfl_dir = VFL_DIR_M2M;
 
        snprintf(vfd->name, sizeof(vfd->name), "fimc.%d.m2m", fimc->id);
        video_set_drvdata(vfd, fimc);
 
-       fimc->m2m.vfd = vfd;
        fimc->m2m.m2m_dev = v4l2_m2m_init(&m2m_ops);
        if (IS_ERR(fimc->m2m.m2m_dev)) {
                v4l2_err(v4l2_dev, "failed to initialize v4l2-m2m device\n");
-               ret = PTR_ERR(fimc->m2m.m2m_dev);
-               goto err_init;
+               return PTR_ERR(fimc->m2m.m2m_dev);
        }
 
        ret = media_entity_init(&vfd->entity, 0, NULL, 0);
@@ -834,8 +822,6 @@ err_vd:
        media_entity_cleanup(&vfd->entity);
 err_me:
        v4l2_m2m_release(fimc->m2m.m2m_dev);
-err_init:
-       video_device_release(fimc->m2m.vfd);
        return ret;
 }
 
@@ -846,9 +832,9 @@ void fimc_unregister_m2m_device(struct fimc_dev *fimc)
 
        if (fimc->m2m.m2m_dev)
                v4l2_m2m_release(fimc->m2m.m2m_dev);
-       if (fimc->m2m.vfd) {
-               media_entity_cleanup(&fimc->m2m.vfd->entity);
-               /* Can also be called if video device wasn't registered */
-               video_unregister_device(fimc->m2m.vfd);
+
+       if (video_is_registered(&fimc->m2m.vfd)) {
+               video_unregister_device(&fimc->m2m.vfd);
+               media_entity_cleanup(&fimc->m2m.vfd.entity);
        }
 }
similarity index 92%
rename from drivers/media/video/s5p-fimc/fimc-mdevice.c
rename to drivers/media/platform/s5p-fimc/fimc-mdevice.c
index e65bb283fd8abfede983e8146d59df6085619aea..80ada5882f62c8156c74265a7279eca9e6fbc35c 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/slab.h>
 #include <media/v4l2-ctrls.h>
 #include <media/media-device.h>
+#include <media/s5p_fimc.h>
 
 #include "fimc-core.h"
 #include "fimc-lite.h"
@@ -38,7 +39,8 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
  *
  * Caller holds the graph mutex.
  */
-void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me)
+static void fimc_pipeline_prepare(struct fimc_pipeline *p,
+                                 struct media_entity *me)
 {
        struct media_pad *pad = &me->pads[0];
        struct v4l2_subdev *sd;
@@ -114,7 +116,7 @@ static int __subdev_set_power(struct v4l2_subdev *sd, int on)
  *
  * Needs to be called with the graph mutex held.
  */
-int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
+static int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
 {
        unsigned int i;
        int ret;
@@ -134,15 +136,15 @@ int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state)
 }
 
 /**
- * __fimc_pipeline_initialize - update the pipeline information, enable power
- *                              of all pipeline subdevs and the sensor clock
+ * __fimc_pipeline_open - update the pipeline information, enable power
+ *                        of all pipeline subdevs and the sensor clock
  * @me: media entity to start graph walk with
  * @prep: true to acquire sensor (and csis) subdevs
  *
  * This function must be called with the graph mutex held.
  */
-static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
-                                     struct media_entity *me, bool prep)
+static int __fimc_pipeline_open(struct fimc_pipeline *p,
+                               struct media_entity *me, bool prep)
 {
        int ret;
 
@@ -159,28 +161,27 @@ static int __fimc_pipeline_initialize(struct fimc_pipeline *p,
        return fimc_pipeline_s_power(p, 1);
 }
 
-int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
-                            bool prep)
+static int fimc_pipeline_open(struct fimc_pipeline *p,
+                             struct media_entity *me, bool prep)
 {
        int ret;
 
        mutex_lock(&me->parent->graph_mutex);
-       ret =  __fimc_pipeline_initialize(p, me, prep);
+       ret =  __fimc_pipeline_open(p, me, prep);
        mutex_unlock(&me->parent->graph_mutex);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_initialize);
 
 /**
- * __fimc_pipeline_shutdown - disable the sensor clock and pipeline power
+ * __fimc_pipeline_close - disable the sensor clock and pipeline power
  * @fimc: fimc device terminating the pipeline
  *
  * Disable power of all subdevs in the pipeline and turn off the external
  * sensor clock.
  * Called with the graph mutex held.
  */
-static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
+static int __fimc_pipeline_close(struct fimc_pipeline *p)
 {
        int ret = 0;
 
@@ -191,7 +192,7 @@ static int __fimc_pipeline_shutdown(struct fimc_pipeline *p)
        return ret == -ENXIO ? 0 : ret;
 }
 
-int fimc_pipeline_shutdown(struct fimc_pipeline *p)
+static int fimc_pipeline_close(struct fimc_pipeline *p)
 {
        struct media_entity *me;
        int ret;
@@ -201,12 +202,11 @@ int fimc_pipeline_shutdown(struct fimc_pipeline *p)
 
        me = &p->subdevs[IDX_SENSOR]->entity;
        mutex_lock(&me->parent->graph_mutex);
-       ret = __fimc_pipeline_shutdown(p);
+       ret = __fimc_pipeline_close(p);
        mutex_unlock(&me->parent->graph_mutex);
 
        return ret;
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_shutdown);
 
 /**
  * fimc_pipeline_s_stream - invoke s_stream on pipeline subdevs
@@ -232,7 +232,13 @@ int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool on)
        return 0;
 
 }
-EXPORT_SYMBOL_GPL(fimc_pipeline_s_stream);
+
+/* Media pipeline operations for the FIMC/FIMC-LITE video device driver */
+static const struct fimc_pipeline_ops fimc_pipeline_ops = {
+       .open           = fimc_pipeline_open,
+       .close          = fimc_pipeline_close,
+       .set_stream     = fimc_pipeline_s_stream,
+};
 
 /*
  * Sensor subdevice helper functions
@@ -246,27 +252,27 @@ static struct v4l2_subdev *fimc_md_register_sensor(struct fimc_md *fmd,
        if (!s_info || !fmd)
                return NULL;
 
-       adapter = i2c_get_adapter(s_info->pdata->i2c_bus_num);
+       adapter = i2c_get_adapter(s_info->pdata.i2c_bus_num);
        if (!adapter) {
                v4l2_warn(&fmd->v4l2_dev,
                          "Failed to get I2C adapter %d, deferring probe\n",
-                         s_info->pdata->i2c_bus_num);
+                         s_info->pdata.i2c_bus_num);
                return ERR_PTR(-EPROBE_DEFER);
        }
        sd = v4l2_i2c_new_subdev_board(&fmd->v4l2_dev, adapter,
-                                      s_info->pdata->board_info, NULL);
+                                      s_info->pdata.board_info, NULL);
        if (IS_ERR_OR_NULL(sd)) {
                i2c_put_adapter(adapter);
                v4l2_warn(&fmd->v4l2_dev,
                          "Failed to acquire subdev %s, deferring probe\n",
-                         s_info->pdata->board_info->type);
+                         s_info->pdata.board_info->type);
                return ERR_PTR(-EPROBE_DEFER);
        }
        v4l2_set_subdev_hostdata(sd, s_info);
        sd->grp_id = SENSOR_GROUP_ID;
 
        v4l2_info(&fmd->v4l2_dev, "Registered sensor subdevice %s\n",
-                 s_info->pdata->board_info->type);
+                 s_info->pdata.board_info->type);
        return sd;
 }
 
@@ -310,7 +316,7 @@ static int fimc_md_register_sensor_entities(struct fimc_md *fmd)
        for (i = 0; i < num_clients; i++) {
                struct v4l2_subdev *sd;
 
-               fmd->sensor[i].pdata = &pdata->isp_info[i];
+               fmd->sensor[i].pdata = pdata->isp_info[i];
                ret = __fimc_md_set_camclk(fmd, &fmd->sensor[i], true);
                if (ret)
                        break;
@@ -347,6 +353,7 @@ static int fimc_register_callback(struct device *dev, void *p)
        if (fimc->pdev->id < 0 || fimc->pdev->id >= FIMC_MAX_DEVS)
                return 0;
 
+       fimc->pipeline_ops = &fimc_pipeline_ops;
        fmd->fimc[fimc->pdev->id] = fimc;
        sd->grp_id = FIMC_GROUP_ID;
 
@@ -372,6 +379,7 @@ static int fimc_lite_register_callback(struct device *dev, void *p)
        if (fimc->index >= FIMC_LITE_MAX_DEVS)
                return 0;
 
+       fimc->pipeline_ops = &fimc_pipeline_ops;
        fmd->fimc_lite[fimc->index] = fimc;
        sd->grp_id = FLITE_GROUP_ID;
 
@@ -473,12 +481,14 @@ static void fimc_md_unregister_entities(struct fimc_md *fmd)
                if (fmd->fimc[i] == NULL)
                        continue;
                v4l2_device_unregister_subdev(&fmd->fimc[i]->vid_cap.subdev);
+               fmd->fimc[i]->pipeline_ops = NULL;
                fmd->fimc[i] = NULL;
        }
        for (i = 0; i < FIMC_LITE_MAX_DEVS; i++) {
                if (fmd->fimc_lite[i] == NULL)
                        continue;
                v4l2_device_unregister_subdev(&fmd->fimc_lite[i]->subdev);
+               fmd->fimc[i]->pipeline_ops = NULL;
                fmd->fimc_lite[i] = NULL;
        }
        for (i = 0; i < CSIS_MAX_ENTITIES; i++) {
@@ -591,7 +601,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
                if (fimc == NULL)
                        continue;
                source = &fimc->subdev.entity;
-               sink = &fimc->vfd->entity;
+               sink = &fimc->vfd.entity;
                /* FIMC-LITE's subdev and video node */
                ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
                                               sink, 0, flags);
@@ -617,6 +627,7 @@ static int __fimc_md_create_flite_source_links(struct fimc_md *fmd)
  */
 static int fimc_md_create_links(struct fimc_md *fmd)
 {
+       struct v4l2_subdev *csi_sensors[2] = { NULL };
        struct v4l2_subdev *sensor, *csis;
        struct s5p_fimc_isp_info *pdata;
        struct fimc_sensor_info *s_info;
@@ -630,11 +641,11 @@ static int fimc_md_create_links(struct fimc_md *fmd)
 
                sensor = fmd->sensor[i].subdev;
                s_info = v4l2_get_subdev_hostdata(sensor);
-               if (!s_info || !s_info->pdata)
+               if (!s_info)
                        continue;
 
                source = NULL;
-               pdata = s_info->pdata;
+               pdata = &s_info->pdata;
 
                switch (pdata->bus_type) {
                case FIMC_MIPI_CSI2:
@@ -659,6 +670,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
                                  sensor->entity.name, csis->entity.name);
 
                        source = NULL;
+                       csi_sensors[pdata->mux_id] = sensor;
                        break;
 
                case FIMC_ITU_601...FIMC_ITU_656:
@@ -684,9 +696,10 @@ static int fimc_md_create_links(struct fimc_md *fmd)
                        continue;
                source = &fmd->csis[i].sd->entity;
                pad = CSIS_PAD_SOURCE;
+               sensor = csi_sensors[i];
 
                link_mask = 1 << fimc_id++;
-               ret = __fimc_md_create_fimc_sink_links(fmd, source, NULL,
+               ret = __fimc_md_create_fimc_sink_links(fmd, source, sensor,
                                                       pad, link_mask);
        }
 
@@ -696,7 +709,7 @@ static int fimc_md_create_links(struct fimc_md *fmd)
                if (!fmd->fimc[i])
                        continue;
                source = &fmd->fimc[i]->vid_cap.subdev.entity;
-               sink = &fmd->fimc[i]->vid_cap.vfd->entity;
+               sink = &fmd->fimc[i]->vid_cap.vfd.entity;
                ret = media_entity_create_link(source, FIMC_SD_PAD_SOURCE,
                                              sink, 0, flags);
                if (ret)
@@ -744,7 +757,7 @@ static int __fimc_md_set_camclk(struct fimc_md *fmd,
                                struct fimc_sensor_info *s_info,
                                bool on)
 {
-       struct s5p_fimc_isp_info *pdata = s_info->pdata;
+       struct s5p_fimc_isp_info *pdata = &s_info->pdata;
        struct fimc_camclk_info *camclk;
        int ret = 0;
 
@@ -829,7 +842,7 @@ static int fimc_md_link_notify(struct media_pad *source,
        }
 
        if (!(flags & MEDIA_LNK_FL_ENABLED)) {
-               ret = __fimc_pipeline_shutdown(pipeline);
+               ret = __fimc_pipeline_close(pipeline);
                pipeline->subdevs[IDX_SENSOR] = NULL;
                pipeline->subdevs[IDX_CSIS] = NULL;
 
@@ -848,8 +861,8 @@ static int fimc_md_link_notify(struct media_pad *source,
        if (fimc) {
                mutex_lock(&fimc->lock);
                if (fimc->vid_cap.refcnt > 0) {
-                       ret = __fimc_pipeline_initialize(pipeline,
-                                                        source->entity, true);
+                       ret = __fimc_pipeline_open(pipeline,
+                                                  source->entity, true);
                if (!ret)
                        ret = fimc_capture_ctrls_create(fimc);
                }
@@ -857,8 +870,8 @@ static int fimc_md_link_notify(struct media_pad *source,
        } else {
                mutex_lock(&fimc_lite->lock);
                if (fimc_lite->ref_count > 0) {
-                       ret = __fimc_pipeline_initialize(pipeline,
-                                                        source->entity, true);
+                       ret = __fimc_pipeline_open(pipeline,
+                                                  source->entity, true);
                }
                mutex_unlock(&fimc_lite->lock);
        }
similarity index 83%
rename from drivers/media/video/s5p-fimc/fimc-mdevice.h
rename to drivers/media/platform/s5p-fimc/fimc-mdevice.h
index 1f5dbaff5442a7df686b4e6dc023952b8436939f..2d8d41d8262042c156d834d24b8649cff0f268b1 100644 (file)
@@ -51,7 +51,7 @@ struct fimc_camclk_info {
  * This data structure applies to image sensor and the writeback subdevs.
  */
 struct fimc_sensor_info {
-       struct s5p_fimc_isp_info *pdata;
+       struct s5p_fimc_isp_info pdata;
        struct v4l2_subdev *subdev;
        struct fimc_dev *host;
 };
@@ -99,22 +99,14 @@ static inline struct fimc_md *entity_to_fimc_mdev(struct media_entity *me)
 
 static inline void fimc_md_graph_lock(struct fimc_dev *fimc)
 {
-       BUG_ON(fimc->vid_cap.vfd == NULL);
-       mutex_lock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+       mutex_lock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
 }
 
 static inline void fimc_md_graph_unlock(struct fimc_dev *fimc)
 {
-       BUG_ON(fimc->vid_cap.vfd == NULL);
-       mutex_unlock(&fimc->vid_cap.vfd->entity.parent->graph_mutex);
+       mutex_unlock(&fimc->vid_cap.vfd.entity.parent->graph_mutex);
 }
 
 int fimc_md_set_camclk(struct v4l2_subdev *sd, bool on);
-void fimc_pipeline_prepare(struct fimc_pipeline *p, struct media_entity *me);
-int fimc_pipeline_initialize(struct fimc_pipeline *p, struct media_entity *me,
-                            bool resume);
-int fimc_pipeline_shutdown(struct fimc_pipeline *p);
-int fimc_pipeline_s_power(struct fimc_pipeline *p, bool state);
-int fimc_pipeline_s_stream(struct fimc_pipeline *p, bool state);
 
 #endif
similarity index 97%
rename from drivers/media/video/s5p-fimc/fimc-reg.c
rename to drivers/media/platform/s5p-fimc/fimc-reg.c
index 0e3eb9ce4f981857a805e80fed82629fd4c88100..2c9d0c06c9e8faef0be5645508ad8495b9356844 100644 (file)
@@ -612,7 +612,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
                }
 
                if (i == ARRAY_SIZE(pix_desc)) {
-                       v4l2_err(fimc->vid_cap.vfd,
+                       v4l2_err(&fimc->vid_cap.vfd,
                                 "Camera color format not supported: %d\n",
                                 fimc->vid_cap.mf.code);
                        return -EINVAL;
@@ -625,7 +625,7 @@ int fimc_hw_set_camera_source(struct fimc_dev *fimc,
                                cfg |= FIMC_REG_CISRCFMT_ITU601_16BIT;
                } /* else defaults to ITU-R BT.656 8-bit */
        } else if (cam->bus_type == FIMC_MIPI_CSI2) {
-               if (fimc_fmt_is_jpeg(f->fmt->color))
+               if (fimc_fmt_is_user_defined(f->fmt->color))
                        cfg |= FIMC_REG_CISRCFMT_ITU601_8BIT;
        }
 
@@ -680,11 +680,12 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
                        tmp = FIMC_REG_CSIIMGFMT_YCBCR422_8BIT;
                        break;
                case V4L2_MBUS_FMT_JPEG_1X8:
+               case V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8:
                        tmp = FIMC_REG_CSIIMGFMT_USER(1);
                        cfg |= FIMC_REG_CIGCTRL_CAM_JPEG;
                        break;
                default:
-                       v4l2_err(vid_cap->vfd,
+                       v4l2_err(&vid_cap->vfd,
                                 "Not supported camera pixel format: %#x\n",
                                 vid_cap->mf.code);
                        return -EINVAL;
@@ -701,7 +702,7 @@ int fimc_hw_set_camera_type(struct fimc_dev *fimc,
                cfg |= FIMC_REG_CIGCTRL_CAMIF_SELWB;
                break;
        default:
-               v4l2_err(vid_cap->vfd, "Invalid camera bus type selected\n");
+               v4l2_err(&vid_cap->vfd, "Invalid camera bus type selected\n");
                return -EINVAL;
        }
        writel(cfg, fimc->regs + FIMC_REG_CIGCTRL);
@@ -744,13 +745,13 @@ void fimc_hw_dis_capture(struct fimc_dev *dev)
 }
 
 /* Return an index to the buffer actually being written. */
-u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
+s32 fimc_hw_get_frame_index(struct fimc_dev *dev)
 {
-       u32 reg;
+       s32 reg;
 
        if (dev->variant->has_cistatus2) {
-               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3F;
-               return reg > 0 ? --reg : reg;
+               reg = readl(dev->regs + FIMC_REG_CISTATUS2) & 0x3f;
+               return reg - 1;
        }
 
        reg = readl(dev->regs + FIMC_REG_CISTATUS);
@@ -759,6 +760,18 @@ u32 fimc_hw_get_frame_index(struct fimc_dev *dev)
                FIMC_REG_CISTATUS_FRAMECNT_SHIFT;
 }
 
+/* Return an index to the buffer being written previously. */
+s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev)
+{
+       s32 reg;
+
+       if (!dev->variant->has_cistatus2)
+               return -1;
+
+       reg = readl(dev->regs + FIMC_REG_CISTATUS2);
+       return ((reg >> 7) & 0x3f) - 1;
+}
+
 /* Locking: the caller holds fimc->slock */
 void fimc_activate_capture(struct fimc_ctx *ctx)
 {
similarity index 99%
rename from drivers/media/video/s5p-fimc/fimc-reg.h
rename to drivers/media/platform/s5p-fimc/fimc-reg.h
index 579ac8ac03deb76c2f78ef5f63ac63a35676f545..b6abfc7b72ace7472c7caea9d398500f3402be08 100644 (file)
@@ -307,7 +307,8 @@ void fimc_hw_clear_irq(struct fimc_dev *dev);
 void fimc_hw_enable_scaler(struct fimc_dev *dev, bool on);
 void fimc_hw_activate_input_dma(struct fimc_dev *dev, bool on);
 void fimc_hw_dis_capture(struct fimc_dev *dev);
-u32 fimc_hw_get_frame_index(struct fimc_dev *dev);
+s32 fimc_hw_get_frame_index(struct fimc_dev *dev);
+s32 fimc_hw_get_prev_frame_index(struct fimc_dev *dev);
 void fimc_activate_capture(struct fimc_ctx *ctx);
 void fimc_deactivate_capture(struct fimc_dev *fimc);
 
similarity index 77%
rename from drivers/media/video/s5p-fimc/mipi-csis.c
rename to drivers/media/platform/s5p-fimc/mipi-csis.c
index 5e898432883a28a848ea206be03453ad051d8fed..22bdf211a2ac8544f6b5a25dfffe9cd9b5bb5909 100644 (file)
@@ -2,7 +2,7 @@
  * Samsung S5P/EXYNOS4 SoC series MIPI-CSI receiver driver
  *
  * Copyright (C) 2011 - 2012 Samsung Electronics Co., Ltd.
- * Sylwester Nawrocki, <s.nawrocki@samsung.com>
+ * Sylwester Nawrocki <s.nawrocki@samsung.com>
  *
  * 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
@@ -31,7 +31,7 @@
 
 static int debug;
 module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug level (0-1)");
+MODULE_PARM_DESC(debug, "Debug level (0-2)");
 
 /* Register map definition */
 
@@ -60,16 +60,49 @@ MODULE_PARM_DESC(debug, "Debug level (0-1)");
 #define S5PCSIS_CFG_FMT_MASK           (0x3f << 2)
 #define S5PCSIS_CFG_NR_LANE_MASK       3
 
-/* Interrupt mask. */
+/* Interrupt mask */
 #define S5PCSIS_INTMSK                 0x10
-#define S5PCSIS_INTMSK_EN_ALL          0xf000003f
+#define S5PCSIS_INTMSK_EN_ALL          0xf000103f
+#define S5PCSIS_INTMSK_EVEN_BEFORE     (1 << 31)
+#define S5PCSIS_INTMSK_EVEN_AFTER      (1 << 30)
+#define S5PCSIS_INTMSK_ODD_BEFORE      (1 << 29)
+#define S5PCSIS_INTMSK_ODD_AFTER       (1 << 28)
+#define S5PCSIS_INTMSK_ERR_SOT_HS      (1 << 12)
+#define S5PCSIS_INTMSK_ERR_LOST_FS     (1 << 5)
+#define S5PCSIS_INTMSK_ERR_LOST_FE     (1 << 4)
+#define S5PCSIS_INTMSK_ERR_OVER                (1 << 3)
+#define S5PCSIS_INTMSK_ERR_ECC         (1 << 2)
+#define S5PCSIS_INTMSK_ERR_CRC         (1 << 1)
+#define S5PCSIS_INTMSK_ERR_UNKNOWN     (1 << 0)
+
+/* Interrupt source */
 #define S5PCSIS_INTSRC                 0x14
+#define S5PCSIS_INTSRC_EVEN_BEFORE     (1 << 31)
+#define S5PCSIS_INTSRC_EVEN_AFTER      (1 << 30)
+#define S5PCSIS_INTSRC_EVEN            (0x3 << 30)
+#define S5PCSIS_INTSRC_ODD_BEFORE      (1 << 29)
+#define S5PCSIS_INTSRC_ODD_AFTER       (1 << 28)
+#define S5PCSIS_INTSRC_ODD             (0x3 << 28)
+#define S5PCSIS_INTSRC_NON_IMAGE_DATA  (0xff << 28)
+#define S5PCSIS_INTSRC_ERR_SOT_HS      (0xf << 12)
+#define S5PCSIS_INTSRC_ERR_LOST_FS     (1 << 5)
+#define S5PCSIS_INTSRC_ERR_LOST_FE     (1 << 4)
+#define S5PCSIS_INTSRC_ERR_OVER                (1 << 3)
+#define S5PCSIS_INTSRC_ERR_ECC         (1 << 2)
+#define S5PCSIS_INTSRC_ERR_CRC         (1 << 1)
+#define S5PCSIS_INTSRC_ERR_UNKNOWN     (1 << 0)
+#define S5PCSIS_INTSRC_ERRORS          0xf03f
 
 /* Pixel resolution */
 #define S5PCSIS_RESOL                  0x2c
 #define CSIS_MAX_PIX_WIDTH             0xffff
 #define CSIS_MAX_PIX_HEIGHT            0xffff
 
+/* Non-image packet data buffers */
+#define S5PCSIS_PKTDATA_ODD            0x2000
+#define S5PCSIS_PKTDATA_EVEN           0x3000
+#define S5PCSIS_PKTDATA_SIZE           SZ_4K
+
 enum {
        CSIS_CLK_MUX,
        CSIS_CLK_GATE,
@@ -82,8 +115,8 @@ static char *csi_clock_name[] = {
 #define NUM_CSIS_CLOCKS        ARRAY_SIZE(csi_clock_name)
 
 static const char * const csis_supply_name[] = {
-       "vdd11", /* 1.1V or 1.2V (s5pc100) MIPI CSI suppply */
-       "vdd18", /* VDD 1.8V and MIPI CSI PLL supply */
+       "vddcore",  /* CSIS Core (1.0V, 1.1V or 1.2V) suppply */
+       "vddio",    /* CSIS I/O and PLL (1.8V) supply */
 };
 #define CSIS_NUM_SUPPLIES ARRAY_SIZE(csis_supply_name)
 
@@ -93,6 +126,34 @@ enum {
        ST_SUSPENDED    = 4,
 };
 
+struct s5pcsis_event {
+       u32 mask;
+       const char * const name;
+       unsigned int counter;
+};
+
+static const struct s5pcsis_event s5pcsis_events[] = {
+       /* Errors */
+       { S5PCSIS_INTSRC_ERR_SOT_HS,    "SOT Error" },
+       { S5PCSIS_INTSRC_ERR_LOST_FS,   "Lost Frame Start Error" },
+       { S5PCSIS_INTSRC_ERR_LOST_FE,   "Lost Frame End Error" },
+       { S5PCSIS_INTSRC_ERR_OVER,      "FIFO Overflow Error" },
+       { S5PCSIS_INTSRC_ERR_ECC,       "ECC Error" },
+       { S5PCSIS_INTSRC_ERR_CRC,       "CRC Error" },
+       { S5PCSIS_INTSRC_ERR_UNKNOWN,   "Unknown Error" },
+       /* Non-image data receive events */
+       { S5PCSIS_INTSRC_EVEN_BEFORE,   "Non-image data before even frame" },
+       { S5PCSIS_INTSRC_EVEN_AFTER,    "Non-image data after even frame" },
+       { S5PCSIS_INTSRC_ODD_BEFORE,    "Non-image data before odd frame" },
+       { S5PCSIS_INTSRC_ODD_AFTER,     "Non-image data after odd frame" },
+};
+#define S5PCSIS_NUM_EVENTS ARRAY_SIZE(s5pcsis_events)
+
+struct csis_pktbuf {
+       u32 *data;
+       unsigned int len;
+};
+
 /**
  * struct csis_state - the driver's internal state data structure
  * @lock: mutex serializing the subdev and power management operations,
@@ -101,11 +162,15 @@ enum {
  * @sd: v4l2_subdev associated with CSIS device instance
  * @pdev: CSIS platform device
  * @regs: mmaped I/O registers memory
+ * @supplies: CSIS regulator supplies
  * @clock: CSIS clocks
  * @irq: requested s5p-mipi-csis irq number
  * @flags: the state variable for power and streaming control
  * @csis_fmt: current CSIS pixel format
  * @format: common media bus format for the source and sink pad
+ * @slock: spinlock protecting structure members below
+ * @pkt_buf: the frame embedded (non-image) data buffer
+ * @events: MIPI-CSIS event (error) counters
  */
 struct csis_state {
        struct mutex lock;
@@ -119,6 +184,10 @@ struct csis_state {
        u32 flags;
        const struct csis_pix_format *csis_fmt;
        struct v4l2_mbus_framefmt format;
+
+       struct spinlock slock;
+       struct csis_pktbuf pkt_buf;
+       struct s5pcsis_event events[S5PCSIS_NUM_EVENTS];
 };
 
 /**
@@ -145,7 +214,11 @@ static const struct csis_pix_format s5pcsis_formats[] = {
                .code = V4L2_MBUS_FMT_JPEG_1X8,
                .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
                .data_alignment = 32,
-       },
+       }, {
+               .code = V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8,
+               .fmt_reg = S5PCSIS_CFG_FMT_USER(1),
+               .data_alignment = 32,
+       }
 };
 
 #define s5pcsis_write(__csis, __r, __v) writel(__v, __csis->regs + __r)
@@ -209,7 +282,7 @@ static void __s5pcsis_set_format(struct csis_state *state)
        struct v4l2_mbus_framefmt *mf = &state->format;
        u32 val;
 
-       v4l2_dbg(1, debug, &state->sd, "fmt: %d, %d x %d\n",
+       v4l2_dbg(1, debug, &state->sd, "fmt: %#x, %d x %d\n",
                 mf->code, mf->width, mf->height);
 
        /* Color format */
@@ -292,17 +365,6 @@ err:
        return -ENXIO;
 }
 
-static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
-{
-       struct csis_state *state = sd_to_csis_state(sd);
-       struct device *dev = &state->pdev->dev;
-
-       if (on)
-               return pm_runtime_get_sync(dev);
-
-       return pm_runtime_put_sync(dev);
-}
-
 static void s5pcsis_start_stream(struct csis_state *state)
 {
        s5pcsis_reset(state);
@@ -317,7 +379,47 @@ static void s5pcsis_stop_stream(struct csis_state *state)
        s5pcsis_system_enable(state, false);
 }
 
-/* v4l2_subdev operations */
+static void s5pcsis_clear_counters(struct csis_state *state)
+{
+       unsigned long flags;
+       int i;
+
+       spin_lock_irqsave(&state->slock, flags);
+       for (i = 0; i < S5PCSIS_NUM_EVENTS; i++)
+               state->events[i].counter = 0;
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+static void s5pcsis_log_counters(struct csis_state *state, bool non_errors)
+{
+       int i = non_errors ? S5PCSIS_NUM_EVENTS : S5PCSIS_NUM_EVENTS - 4;
+       unsigned long flags;
+
+       spin_lock_irqsave(&state->slock, flags);
+
+       for (i--; i >= 0; i--)
+               if (state->events[i].counter >= 0)
+                       v4l2_info(&state->sd, "%s events: %d\n",
+                                 state->events[i].name,
+                                 state->events[i].counter);
+
+       spin_unlock_irqrestore(&state->slock, flags);
+}
+
+/*
+ * V4L2 subdev operations
+ */
+static int s5pcsis_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct csis_state *state = sd_to_csis_state(sd);
+       struct device *dev = &state->pdev->dev;
+
+       if (on)
+               return pm_runtime_get_sync(dev);
+
+       return pm_runtime_put_sync(dev);
+}
+
 static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
 {
        struct csis_state *state = sd_to_csis_state(sd);
@@ -327,10 +429,12 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
                 __func__, enable, state->flags);
 
        if (enable) {
+               s5pcsis_clear_counters(state);
                ret = pm_runtime_get_sync(&state->pdev->dev);
                if (ret && ret != 1)
                        return ret;
        }
+
        mutex_lock(&state->lock);
        if (enable) {
                if (state->flags & ST_SUSPENDED) {
@@ -342,6 +446,8 @@ static int s5pcsis_s_stream(struct v4l2_subdev *sd, int enable)
        } else {
                s5pcsis_stop_stream(state);
                state->flags &= ~ST_STREAMING;
+               if (debug > 0)
+                       s5pcsis_log_counters(state, true);
        }
 unlock:
        mutex_unlock(&state->lock);
@@ -439,6 +545,30 @@ static int s5pcsis_get_fmt(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
        return 0;
 }
 
+static int s5pcsis_s_rx_buffer(struct v4l2_subdev *sd, void *buf,
+                              unsigned int *size)
+{
+       struct csis_state *state = sd_to_csis_state(sd);
+       unsigned long flags;
+
+       *size = min_t(unsigned int, *size, S5PCSIS_PKTDATA_SIZE);
+
+       spin_lock_irqsave(&state->slock, flags);
+       state->pkt_buf.data = buf;
+       state->pkt_buf.len = *size;
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       return 0;
+}
+
+static int s5pcsis_log_status(struct v4l2_subdev *sd)
+{
+       struct csis_state *state = sd_to_csis_state(sd);
+
+       s5pcsis_log_counters(state, true);
+       return 0;
+}
+
 static int s5pcsis_open(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh)
 {
        struct v4l2_mbus_framefmt *format = v4l2_subdev_get_try_format(fh, 0);
@@ -458,6 +588,7 @@ static const struct v4l2_subdev_internal_ops s5pcsis_sd_internal_ops = {
 
 static struct v4l2_subdev_core_ops s5pcsis_core_ops = {
        .s_power = s5pcsis_s_power,
+       .log_status = s5pcsis_log_status,
 };
 
 static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
@@ -467,6 +598,7 @@ static struct v4l2_subdev_pad_ops s5pcsis_pad_ops = {
 };
 
 static struct v4l2_subdev_video_ops s5pcsis_video_ops = {
+       .s_rx_buffer = s5pcsis_s_rx_buffer,
        .s_stream = s5pcsis_s_stream,
 };
 
@@ -479,12 +611,42 @@ static struct v4l2_subdev_ops s5pcsis_subdev_ops = {
 static irqreturn_t s5pcsis_irq_handler(int irq, void *dev_id)
 {
        struct csis_state *state = dev_id;
-       u32 val;
+       struct csis_pktbuf *pktbuf = &state->pkt_buf;
+       unsigned long flags;
+       u32 status;
 
-       /* Just clear the interrupt pending bits. */
-       val = s5pcsis_read(state, S5PCSIS_INTSRC);
-       s5pcsis_write(state, S5PCSIS_INTSRC, val);
+       status = s5pcsis_read(state, S5PCSIS_INTSRC);
+       spin_lock_irqsave(&state->slock, flags);
 
+       if ((status & S5PCSIS_INTSRC_NON_IMAGE_DATA) && pktbuf->data) {
+               u32 offset;
+
+               if (status & S5PCSIS_INTSRC_EVEN)
+                       offset = S5PCSIS_PKTDATA_EVEN;
+               else
+                       offset = S5PCSIS_PKTDATA_ODD;
+
+               memcpy(pktbuf->data, state->regs + offset, pktbuf->len);
+               pktbuf->data = NULL;
+               rmb();
+       }
+
+       /* Update the event/error counters */
+       if ((status & S5PCSIS_INTSRC_ERRORS) || debug) {
+               int i;
+               for (i = 0; i < S5PCSIS_NUM_EVENTS; i++) {
+                       if (!(status & state->events[i].mask))
+                               continue;
+                       state->events[i].counter++;
+                       v4l2_dbg(2, debug, &state->sd, "%s: %d\n",
+                                state->events[i].name,
+                                state->events[i].counter);
+               }
+               v4l2_dbg(2, debug, &state->sd, "status: %08x\n", status);
+       }
+       spin_unlock_irqrestore(&state->slock, flags);
+
+       s5pcsis_write(state, S5PCSIS_INTSRC, status);
        return IRQ_HANDLED;
 }
 
@@ -501,6 +663,8 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        mutex_init(&state->lock);
+       spin_lock_init(&state->slock);
+
        state->pdev = pdev;
 
        pdata = pdev->dev.platform_data;
@@ -577,6 +741,8 @@ static int __devinit s5pcsis_probe(struct platform_device *pdev)
        /* .. and a pointer to the subdev. */
        platform_set_drvdata(pdev, &state->sd);
 
+       memcpy(state->events, s5pcsis_events, sizeof(state->events));
+
        pm_runtime_enable(&pdev->dev);
        return 0;
 
similarity index 96%
rename from drivers/media/video/s5p-g2d/g2d.c
rename to drivers/media/platform/s5p-g2d/g2d.c
index 7c22004352068ffeec6493b2594710ad184438e5..1bfbc325836b7077b9609da1af8f9958b92d4608 100644 (file)
@@ -151,7 +151,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        struct g2d_ctx *ctx = priv;
        int ret;
 
-       memset(src_vq, 0, sizeof(*src_vq));
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        src_vq->drv_priv = ctx;
@@ -163,7 +162,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        if (ret)
                return ret;
 
-       memset(dst_vq, 0, sizeof(*dst_vq));
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        dst_vq->drv_priv = ctx;
@@ -248,9 +246,14 @@ static int g2d_open(struct file *file)
        ctx->in         = def_frame;
        ctx->out        = def_frame;
 
+       if (mutex_lock_interruptible(&dev->mutex)) {
+               kfree(ctx);
+               return -ERESTARTSYS;
+       }
        ctx->m2m_ctx = v4l2_m2m_ctx_init(dev->m2m_dev, ctx, &queue_init);
        if (IS_ERR(ctx->m2m_ctx)) {
                ret = PTR_ERR(ctx->m2m_ctx);
+               mutex_unlock(&dev->mutex);
                kfree(ctx);
                return ret;
        }
@@ -264,6 +267,7 @@ static int g2d_open(struct file *file)
        v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
 
        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
+       mutex_unlock(&dev->mutex);
 
        v4l2_info(&dev->v4l2_dev, "instance opened\n");
        return 0;
@@ -406,13 +410,26 @@ static int vidioc_s_fmt(struct file *file, void *prv, struct v4l2_format *f)
 static unsigned int g2d_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct g2d_ctx *ctx = fh2ctx(file->private_data);
-       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       struct g2d_dev *dev = ctx->dev;
+       unsigned int res;
+
+       mutex_lock(&dev->mutex);
+       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_unlock(&dev->mutex);
+       return res;
 }
 
 static int g2d_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct g2d_ctx *ctx = fh2ctx(file->private_data);
-       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       struct g2d_dev *dev = ctx->dev;
+       int ret;
+
+       if (mutex_lock_interruptible(&dev->mutex))
+               return -ERESTARTSYS;
+       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&dev->mutex);
+       return ret;
 }
 
 static int vidioc_reqbufs(struct file *file, void *priv,
@@ -490,7 +507,7 @@ static int vidioc_g_crop(struct file *file, void *prv, struct v4l2_crop *cr)
        return 0;
 }
 
-static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+static int vidioc_try_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
 {
        struct g2d_ctx *ctx = prv;
        struct g2d_dev *dev = ctx->dev;
@@ -509,7 +526,7 @@ static int vidioc_try_crop(struct file *file, void *prv, struct v4l2_crop *cr)
        return 0;
 }
 
-static int vidioc_s_crop(struct file *file, void *prv, struct v4l2_crop *cr)
+static int vidioc_s_crop(struct file *file, void *prv, const struct v4l2_crop *cr)
 {
        struct g2d_ctx *ctx = prv;
        struct g2d_frame *f;
@@ -663,6 +680,7 @@ static struct video_device g2d_videodev = {
        .ioctl_ops      = &g2d_ioctl_ops,
        .minor          = -1,
        .release        = video_device_release,
+       .vfl_dir        = VFL_DIR_M2M,
 };
 
 static struct v4l2_m2m_ops g2d_m2m_ops = {
@@ -753,10 +771,6 @@ static int g2d_probe(struct platform_device *pdev)
                goto unreg_v4l2_dev;
        }
        *vfd = g2d_videodev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->lock = &dev->mutex;
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
        if (ret) {
similarity index 97%
rename from drivers/media/video/s5p-jpeg/jpeg-core.c
rename to drivers/media/platform/s5p-jpeg/jpeg-core.c
index 813b801238d1f72e910ab8eea63feeb586b477bb..17983c4c9a9aca9a12e63e60853bde15a0f5f6ca 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/drivers/media/video/s5p-jpeg/jpeg-core.c
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.c
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
@@ -288,10 +288,15 @@ static int s5p_jpeg_open(struct file *file)
        struct s5p_jpeg_fmt *out_fmt;
        int ret = 0;
 
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx)
                return -ENOMEM;
 
+       if (mutex_lock_interruptible(&jpeg->lock)) {
+               ret = -ERESTARTSYS;
+               goto free;
+       }
+
        v4l2_fh_init(&ctx->fh, vfd);
        /* Use separate control handler per file handle */
        ctx->fh.ctrl_handler = &ctx->ctrl_handler;
@@ -319,20 +324,26 @@ static int s5p_jpeg_open(struct file *file)
 
        ctx->out_q.fmt = out_fmt;
        ctx->cap_q.fmt = s5p_jpeg_find_format(ctx->mode, V4L2_PIX_FMT_YUYV);
+       mutex_unlock(&jpeg->lock);
        return 0;
 
 error:
        v4l2_fh_del(&ctx->fh);
        v4l2_fh_exit(&ctx->fh);
+       mutex_unlock(&jpeg->lock);
+free:
        kfree(ctx);
        return ret;
 }
 
 static int s5p_jpeg_release(struct file *file)
 {
+       struct s5p_jpeg *jpeg = video_drvdata(file);
        struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
 
+       mutex_lock(&jpeg->lock);
        v4l2_m2m_ctx_release(ctx->m2m_ctx);
+       mutex_unlock(&jpeg->lock);
        v4l2_ctrl_handler_free(&ctx->ctrl_handler);
        v4l2_fh_del(&ctx->fh);
        v4l2_fh_exit(&ctx->fh);
@@ -344,16 +355,27 @@ static int s5p_jpeg_release(struct file *file)
 static unsigned int s5p_jpeg_poll(struct file *file,
                                 struct poll_table_struct *wait)
 {
+       struct s5p_jpeg *jpeg = video_drvdata(file);
        struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+       unsigned int res;
 
-       return v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_lock(&jpeg->lock);
+       res = v4l2_m2m_poll(file, ctx->m2m_ctx, wait);
+       mutex_unlock(&jpeg->lock);
+       return res;
 }
 
 static int s5p_jpeg_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct s5p_jpeg *jpeg = video_drvdata(file);
        struct s5p_jpeg_ctx *ctx = fh_to_ctx(file->private_data);
+       int ret;
 
-       return v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       if (mutex_lock_interruptible(&jpeg->lock))
+               return -ERESTARTSYS;
+       ret = v4l2_m2m_mmap(file, ctx->m2m_ctx, vma);
+       mutex_unlock(&jpeg->lock);
+       return ret;
 }
 
 static const struct v4l2_file_operations s5p_jpeg_fops = {
@@ -1201,7 +1223,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        struct s5p_jpeg_ctx *ctx = priv;
        int ret;
 
-       memset(src_vq, 0, sizeof(*src_vq));
        src_vq->type = V4L2_BUF_TYPE_VIDEO_OUTPUT;
        src_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        src_vq->drv_priv = ctx;
@@ -1213,7 +1234,6 @@ static int queue_init(void *priv, struct vb2_queue *src_vq,
        if (ret)
                return ret;
 
-       memset(dst_vq, 0, sizeof(*dst_vq));
        dst_vq->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        dst_vq->io_modes = VB2_MMAP | VB2_USERPTR;
        dst_vq->drv_priv = ctx;
@@ -1333,7 +1353,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
                return ret;
        }
        dev_dbg(&pdev->dev, "clock source %p\n", jpeg->clk);
-       clk_enable(jpeg->clk);
+       clk_prepare_enable(jpeg->clk);
 
        /* v4l2 device */
        ret = v4l2_device_register(&pdev->dev, &jpeg->v4l2_dev);
@@ -1372,10 +1392,7 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
        jpeg->vfd_encoder->release      = video_device_release;
        jpeg->vfd_encoder->lock         = &jpeg->lock;
        jpeg->vfd_encoder->v4l2_dev     = &jpeg->v4l2_dev;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_encoder->flags);
+       jpeg->vfd_encoder->vfl_dir      = VFL_DIR_M2M;
 
        ret = video_register_device(jpeg->vfd_encoder, VFL_TYPE_GRABBER, -1);
        if (ret) {
@@ -1403,10 +1420,6 @@ static int s5p_jpeg_probe(struct platform_device *pdev)
        jpeg->vfd_decoder->release      = video_device_release;
        jpeg->vfd_decoder->lock         = &jpeg->lock;
        jpeg->vfd_decoder->v4l2_dev     = &jpeg->v4l2_dev;
-       /* Locking in file operations other than ioctl should be done by the driver,
-          not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &jpeg->vfd_decoder->flags);
 
        ret = video_register_device(jpeg->vfd_decoder, VFL_TYPE_GRABBER, -1);
        if (ret) {
@@ -1447,7 +1460,7 @@ device_register_rollback:
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
 clk_get_rollback:
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return ret;
@@ -1467,7 +1480,7 @@ static int s5p_jpeg_remove(struct platform_device *pdev)
        v4l2_m2m_release(jpeg->m2m_dev);
        v4l2_device_unregister(&jpeg->v4l2_dev);
 
-       clk_disable(jpeg->clk);
+       clk_disable_unprepare(jpeg->clk);
        clk_put(jpeg->clk);
 
        return 0;
similarity index 98%
rename from drivers/media/video/s5p-jpeg/jpeg-core.h
rename to drivers/media/platform/s5p-jpeg/jpeg-core.h
index 9d0cd2b76f619e9d7b0c6321ae0c38b2ddeed28a..022b9b9baff933c9303b7b1be42226137ab5cb64 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/drivers/media/video/s5p-jpeg/jpeg-core.h
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-core.h
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
similarity index 99%
rename from drivers/media/video/s5p-jpeg/jpeg-hw.h
rename to drivers/media/platform/s5p-jpeg/jpeg-hw.h
index f12f0fdbde7c7870b2e9f1c148f9f44d83379981..b47e887b61381c8f952a99d04935d571c410e308 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/drivers/media/video/s5p-jpeg/jpeg-hw.h
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-hw.h
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com
similarity index 98%
rename from drivers/media/video/s5p-jpeg/jpeg-regs.h
rename to drivers/media/platform/s5p-jpeg/jpeg-regs.h
index 91f4dd5f86dd9d49ac6573eb3796a25df4b875af..38e50815668c23e7616a7b15cb39921962005c3c 100644 (file)
@@ -1,4 +1,4 @@
-/* linux/drivers/media/video/s5p-jpeg/jpeg-regs.h
+/* linux/drivers/media/platform/s5p-jpeg/jpeg-regs.h
  *
  * Register definition file for Samsung JPEG codec driver
  *
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc.c
index 9bb68e7b5ae80833b827586fbf09a5642495d050..5587ef15ca4fa3d34a3db0e7fe70039ccbc62fc7 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/sched.h>
 #include <linux/slab.h>
 #include <linux/videodev2.h>
+#include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <media/videobuf2-core.h>
 #include "regs-mfc.h"
@@ -40,16 +41,49 @@ module_param(debug, int, S_IRUGO | S_IWUSR);
 MODULE_PARM_DESC(debug, "Debug level - higher value produces more verbose messages");
 
 /* Helper functions for interrupt processing */
+
 /* Remove from hw execution round robin */
-static void clear_work_bit(struct s5p_mfc_ctx *ctx)
+void clear_work_bit(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+
+       spin_lock(&dev->condlock);
+       __clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock(&dev->condlock);
+}
+
+/* Add to hw execution round robin */
+void set_work_bit(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
 
        spin_lock(&dev->condlock);
-       clear_bit(ctx->num, &dev->ctx_work_bits);
+       __set_bit(ctx->num, &dev->ctx_work_bits);
        spin_unlock(&dev->condlock);
 }
 
+/* Remove from hw execution round robin */
+void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       __clear_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+}
+
+/* Add to hw execution round robin */
+void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       unsigned long flags;
+
+       spin_lock_irqsave(&dev->condlock, flags);
+       __set_bit(ctx->num, &dev->ctx_work_bits);
+       spin_unlock_irqrestore(&dev->condlock, flags);
+}
+
 /* Wake up context wait_queue */
 static void wake_up_ctx(struct s5p_mfc_ctx *ctx, unsigned int reason,
                        unsigned int err)
@@ -503,9 +537,7 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
        ctx->int_type = reason;
        ctx->int_err = err;
        ctx->int_cond = 1;
-       spin_lock(&dev->condlock);
-       clear_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock(&dev->condlock);
+       clear_work_bit(ctx);
        if (err == 0) {
                ctx->state = MFCINST_RUNNING;
                if (!ctx->dpb_flush_flag) {
@@ -539,6 +571,40 @@ static void s5p_mfc_handle_init_buffers(struct s5p_mfc_ctx *ctx,
        }
 }
 
+static void s5p_mfc_handle_stream_complete(struct s5p_mfc_ctx *ctx,
+                                unsigned int reason, unsigned int err)
+{
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *mb_entry;
+
+       mfc_debug(2, "Stream completed");
+
+       s5p_mfc_clear_int_flags(dev);
+       ctx->int_type = reason;
+       ctx->int_err = err;
+       ctx->state = MFCINST_FINISHED;
+
+       spin_lock(&dev->irqlock);
+       if (!list_empty(&ctx->dst_queue)) {
+               mb_entry = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               list_del(&mb_entry->list);
+               ctx->dst_queue_cnt--;
+               vb2_set_plane_payload(mb_entry->b, 0, 0);
+               vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
+       }
+       spin_unlock(&dev->irqlock);
+
+       clear_work_bit(ctx);
+
+       if (test_and_clear_bit(0, &dev->hw_lock) == 0)
+               WARN_ON(1);
+
+       s5p_mfc_clock_off();
+       wake_up(&ctx->queue);
+       s5p_mfc_try_run(dev);
+}
+
 /* Interrupt processing */
 static irqreturn_t s5p_mfc_irq(int irq, void *priv)
 {
@@ -614,6 +680,11 @@ static irqreturn_t s5p_mfc_irq(int irq, void *priv)
        case S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET:
                s5p_mfc_handle_init_buffers(ctx, reason, err);
                break;
+
+       case S5P_FIMV_R2H_CMD_ENC_COMPLETE_RET:
+               s5p_mfc_handle_stream_complete(ctx, reason, err);
+               break;
+
        default:
                mfc_debug(2, "Unknown int reason\n");
                s5p_mfc_clear_int_flags(dev);
@@ -641,13 +712,14 @@ static int s5p_mfc_open(struct file *file)
        struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_ctx *ctx = NULL;
        struct vb2_queue *q;
-       unsigned long flags;
        int ret = 0;
 
        mfc_debug_enter();
+       if (mutex_lock_interruptible(&dev->mfc_mutex))
+               return -ERESTARTSYS;
        dev->num_inst++;        /* It is guarded by mfc_mutex in vfd */
        /* Allocate memory for context */
-       ctx = kzalloc(sizeof *ctx, GFP_KERNEL);
+       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                mfc_err("Not enough memory\n");
                ret = -ENOMEM;
@@ -672,9 +744,7 @@ static int s5p_mfc_open(struct file *file)
                }
        }
        /* Mark context as idle */
-       spin_lock_irqsave(&dev->condlock, flags);
-       clear_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock_irqrestore(&dev->condlock, flags);
+       clear_work_bit_irqsave(ctx);
        dev->ctx[ctx->num] = ctx;
        if (s5p_mfc_get_node_type(file) == MFCNODE_DECODER) {
                ctx->type = MFCINST_DECODER;
@@ -765,6 +835,7 @@ static int s5p_mfc_open(struct file *file)
                goto err_queue_init;
        }
        init_waitqueue_head(&ctx->queue);
+       mutex_unlock(&dev->mfc_mutex);
        mfc_debug_leave();
        return ret;
        /* Deinit when failure occured */
@@ -790,6 +861,7 @@ err_no_ctx:
        kfree(ctx);
 err_alloc:
        dev->num_inst--;
+       mutex_unlock(&dev->mfc_mutex);
        mfc_debug_leave();
        return ret;
 }
@@ -799,24 +871,20 @@ static int s5p_mfc_release(struct file *file)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
        struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
 
        mfc_debug_enter();
+       mutex_lock(&dev->mfc_mutex);
        s5p_mfc_clock_on();
        vb2_queue_release(&ctx->vq_src);
        vb2_queue_release(&ctx->vq_dst);
        /* Mark context as idle */
-       spin_lock_irqsave(&dev->condlock, flags);
-       clear_bit(ctx->num, &dev->ctx_work_bits);
-       spin_unlock_irqrestore(&dev->condlock, flags);
+       clear_work_bit_irqsave(ctx);
        /* If instance was initialised then
         * return instance and free reosurces */
        if (ctx->inst_no != MFC_NO_INSTANCE_SET) {
                mfc_debug(2, "Has to free instance\n");
                ctx->state = MFCINST_RETURN_INST;
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
+               set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_try_run(dev);
                /* Wait until instance is returned or timeout occured */
@@ -855,6 +923,7 @@ static int s5p_mfc_release(struct file *file)
        v4l2_fh_exit(&ctx->fh);
        kfree(ctx);
        mfc_debug_leave();
+       mutex_unlock(&dev->mfc_mutex);
        return 0;
 }
 
@@ -869,6 +938,7 @@ static unsigned int s5p_mfc_poll(struct file *file,
        unsigned int rc = 0;
        unsigned long flags;
 
+       mutex_lock(&dev->mfc_mutex);
        src_q = &ctx->vq_src;
        dst_q = &ctx->vq_dst;
        /*
@@ -882,9 +952,12 @@ static unsigned int s5p_mfc_poll(struct file *file,
                goto end;
        }
        mutex_unlock(&dev->mfc_mutex);
+       poll_wait(file, &ctx->fh.wait, wait);
        poll_wait(file, &src_q->done_wq, wait);
        poll_wait(file, &dst_q->done_wq, wait);
        mutex_lock(&dev->mfc_mutex);
+       if (v4l2_event_pending(&ctx->fh))
+               rc |= POLLPRI;
        spin_lock_irqsave(&src_q->done_lock, flags);
        if (!list_empty(&src_q->done_list))
                src_vb = list_first_entry(&src_q->done_list, struct vb2_buffer,
@@ -902,6 +975,7 @@ static unsigned int s5p_mfc_poll(struct file *file,
                rc |= POLLIN | POLLRDNORM;
        spin_unlock_irqrestore(&dst_q->done_lock, flags);
 end:
+       mutex_unlock(&dev->mfc_mutex);
        return rc;
 }
 
@@ -909,8 +983,12 @@ end:
 static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(file->private_data);
+       struct s5p_mfc_dev *dev = ctx->dev;
        unsigned long offset = vma->vm_pgoff << PAGE_SHIFT;
        int ret;
+
+       if (mutex_lock_interruptible(&dev->mfc_mutex))
+               return -ERESTARTSYS;
        if (offset < DST_QUEUE_OFF_BASE) {
                mfc_debug(2, "mmaping source\n");
                ret = vb2_mmap(&ctx->vq_src, vma);
@@ -919,6 +997,7 @@ static int s5p_mfc_mmap(struct file *file, struct vm_area_struct *vma)
                vma->vm_pgoff -= (DST_QUEUE_OFF_BASE >> PAGE_SHIFT);
                ret = vb2_mmap(&ctx->vq_dst, vma);
        }
+       mutex_unlock(&dev->mfc_mutex);
        return ret;
 }
 
@@ -948,7 +1027,7 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        int ret;
 
        pr_debug("%s++\n", __func__);
-       dev = devm_kzalloc(&pdev->dev, sizeof *dev, GFP_KERNEL);
+       dev = devm_kzalloc(&pdev->dev, sizeof(*dev), GFP_KERNEL);
        if (!dev) {
                dev_err(&pdev->dev, "Not enough memory for MFC device\n");
                return -ENOMEM;
@@ -1034,11 +1113,8 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->ioctl_ops  = get_dec_v4l2_ioctl_ops();
        vfd->release    = video_device_release,
        vfd->lock       = &dev->mfc_mutex;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->v4l2_dev   = &dev->v4l2_dev;
+       vfd->vfl_dir    = VFL_DIR_M2M;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_DEC_NAME);
        dev->vfd_dec    = vfd;
        ret = video_register_device(vfd, VFL_TYPE_GRABBER, 0);
@@ -1062,8 +1138,6 @@ static int s5p_mfc_probe(struct platform_device *pdev)
        vfd->ioctl_ops  = get_enc_v4l2_ioctl_ops();
        vfd->release    = video_device_release,
        vfd->lock       = &dev->mfc_mutex;
-       /* This should not be necessary */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
        vfd->v4l2_dev   = &dev->v4l2_dev;
        snprintf(vfd->name, sizeof(vfd->name), "%s", S5P_MFC_ENC_NAME);
        dev->vfd_enc    = vfd;
@@ -1141,7 +1215,7 @@ static int s5p_mfc_suspend(struct device *dev)
 
        if (m_dev->num_inst == 0)
                return 0;
-       return s5p_mfc_sleep(m_dev);
+
        if (test_and_set_bit(0, &m_dev->enter_suspend) != 0) {
                mfc_err("Error: going to suspend for a second time\n");
                return -EIO;
@@ -1160,7 +1234,8 @@ static int s5p_mfc_suspend(struct device *dev)
                        return -EIO;
                }
        }
-       return 0;
+
+       return s5p_mfc_sleep(m_dev);
 }
 
 static int s5p_mfc_resume(struct device *dev)
similarity index 98%
rename from drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
index f0665ed1a52990391cef749081212de47a394b9e..91a415573bd2a1a19233ef05429c7d632b7f2942 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.c
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
index 5ceebfe6131a83b3494f56eafef9fcadedec3eb8..8b090d3723e7d5f8fd2f84a1373c91e4b59379ea 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_cmd.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_cmd.h
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 98%
rename from drivers/media/video/s5p-mfc/s5p_mfc_common.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_common.h
index bd5706a6bad18dbd591ab7223a2f748c89430b79..519b0d66d8d1263e52e170e387647ba3962b3fbe 100644 (file)
@@ -146,6 +146,9 @@ enum s5p_mfc_decode_arg {
        MFC_DEC_RES_CHANGE,
 };
 
+#define MFC_BUF_FLAG_USED      (1 << 0)
+#define MFC_BUF_FLAG_EOS       (1 << 1)
+
 struct s5p_mfc_ctx;
 
 /**
@@ -161,7 +164,7 @@ struct s5p_mfc_buf {
                } raw;
                size_t stream;
        } cookie;
-       int used;
+       int flags;
 };
 
 /**
@@ -567,4 +570,9 @@ struct mfc_control {
 #define ctrl_to_ctx(__ctrl) \
        container_of((__ctrl)->handler, struct s5p_mfc_ctx, ctrl_handler)
 
+void clear_work_bit(struct s5p_mfc_ctx *ctx);
+void set_work_bit(struct s5p_mfc_ctx *ctx);
+void clear_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
+void set_work_bit_irqsave(struct s5p_mfc_ctx *ctx);
+
 #endif /* S5P_MFC_COMMON_H_ */
similarity index 95%
rename from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
index 08a5cfeaa59ea47aa1bfc5ca193a71ce49f579e3..0deba6bc687c7a357ba37ff40de904afb1bebb94 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
@@ -78,7 +78,7 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
        }
        dev->bank1 = s5p_mfc_bitproc_phys;
        b_base = vb2_dma_contig_memops.alloc(
-               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BANK2_ALIGN_ORDER);
+               dev->alloc_ctx[MFC_BANK2_ALLOC_CTX], 1 << MFC_BASE_ALIGN_ORDER);
        if (IS_ERR(b_base)) {
                vb2_dma_contig_memops.put(s5p_mfc_bitproc_buf);
                s5p_mfc_bitproc_phys = 0;
@@ -98,7 +98,11 @@ int s5p_mfc_alloc_and_load_firmware(struct s5p_mfc_dev *dev)
                release_firmware(fw_blob);
                return -EIO;
        }
-       dev->bank2 = bank2_base_phys;
+       /* Valid buffers passed to MFC encoder with LAST_FRAME command
+        * should not have address of bank2 - MFC will treat it as a null frame.
+        * To avoid such situation we set bank2 address below the pool address.
+        */
+       dev->bank2 = bank2_base_phys - (1 << MFC_BASE_ALIGN_ORDER);
        memcpy(s5p_mfc_bitproc_virt, fw_blob->data, fw_blob->size);
        wmb();
        release_firmware(fw_blob);
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
index 61dc23b7ee5a8546e374da778d693016525db2fb..e1e0c544b6a2ccb675c6f445ba6ff758dbd54898 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_ctrl.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_ctrl.h
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 95%
rename from drivers/media/video/s5p-mfc/s5p_mfc_debug.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_debug.h
index ecb8616a492aacfd63c8c84ce2643f64d1381ea9..bd5cd4ae993ce778b066395259f9dce3a04cce31 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/samsung/mfc5/s5p_mfc_debug.h
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_debug.h
  *
  * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
  * This file contains debug macros
similarity index 97%
rename from drivers/media/video/s5p-mfc/s5p_mfc_dec.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
index c5d567f87d77acad3a335683946877757c3adce7..6ee21bb713980ac840b1c87d175f898b380d46db 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.c
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
@@ -415,7 +415,6 @@ static int vidioc_reqbufs(struct file *file, void *priv,
        struct s5p_mfc_dev *dev = video_drvdata(file);
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
        int ret = 0;
-       unsigned long flags;
 
        if (reqbufs->memory != V4L2_MEMORY_MMAP) {
                mfc_err("Only V4L2_MEMORY_MAP is supported\n");
@@ -497,11 +496,8 @@ static int vidioc_reqbufs(struct file *file, void *priv,
                        s5p_mfc_clock_off();
                        return -ENOMEM;
                }
-               if (s5p_mfc_ctx_ready(ctx)) {
-                       spin_lock_irqsave(&dev->condlock, flags);
-                       set_bit(ctx->num, &dev->ctx_work_bits);
-                       spin_unlock_irqrestore(&dev->condlock, flags);
-               }
+               if (s5p_mfc_ctx_ready(ctx))
+                       set_work_bit_irqsave(ctx);
                s5p_mfc_try_run(dev);
                s5p_mfc_wait_for_done_ctx(ctx,
                                         S5P_FIMV_R2H_CMD_INIT_BUFFERS_RET, 0);
@@ -576,7 +572,6 @@ static int vidioc_streamon(struct file *file, void *priv,
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
        struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
        int ret = -EINVAL;
 
        mfc_debug_enter();
@@ -589,9 +584,7 @@ static int vidioc_streamon(struct file *file, void *priv,
                        ctx->output_state = QUEUE_FREE;
                        s5p_mfc_alloc_instance_buffer(ctx);
                        s5p_mfc_alloc_dec_temp_buffers(ctx);
-                       spin_lock_irqsave(&dev->condlock, flags);
-                       set_bit(ctx->num, &dev->ctx_work_bits);
-                       spin_unlock_irqrestore(&dev->condlock, flags);
+                       set_work_bit_irqsave(ctx);
                        s5p_mfc_clean_ctx_int_flags(ctx);
                        s5p_mfc_try_run(dev);
 
@@ -875,18 +868,14 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
        struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
 
        v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
        if (ctx->state == MFCINST_FINISHING ||
                ctx->state == MFCINST_FINISHED)
                ctx->state = MFCINST_RUNNING;
        /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_ctx_ready(ctx)) {
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
-       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
        s5p_mfc_try_run(dev);
        return 0;
 }
@@ -936,14 +925,14 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
 
        if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
-               mfc_buf->used = 0;
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
                spin_lock_irqsave(&dev->irqlock, flags);
                list_add_tail(&mfc_buf->list, &ctx->src_queue);
                ctx->src_queue_cnt++;
                spin_unlock_irqrestore(&dev->irqlock, flags);
        } else if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
-               mfc_buf->used = 0;
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
                /* Mark destination as available for use by MFC */
                spin_lock_irqsave(&dev->irqlock, flags);
                set_bit(vb->v4l2_buf.index, &ctx->dec_dst_flag);
@@ -953,11 +942,8 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        } else {
                mfc_err("Unsupported buffer type (%d)\n", vq->type);
        }
-       if (s5p_mfc_ctx_ready(ctx)) {
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
-       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
        s5p_mfc_try_run(dev);
 }
 
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc_dec.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
index fb8b215db0e7640d9228f9e9d59a9765e5e935c8..fdf1d99a9d15df53decc6bb427ede6dfd0903ece 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_dec.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_dec.h
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 95%
rename from drivers/media/video/s5p-mfc/s5p_mfc_enc.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
index aa1c244cf66eee087c6f89a372c18d6bd6be6b72..179e4db60b15614a4cac63e04be9bc98667232b4 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.c
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
@@ -21,6 +21,7 @@
 #include <linux/sched.h>
 #include <linux/version.h>
 #include <linux/videodev2.h>
+#include <media/v4l2-event.h>
 #include <linux/workqueue.h>
 #include <media/v4l2-ctrls.h>
 #include <media/videobuf2-core.h>
@@ -576,9 +577,9 @@ static int s5p_mfc_ctx_ready(struct s5p_mfc_ctx *ctx)
        if (ctx->state == MFCINST_RUNNING &&
                ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
                return 1;
-       /* context is ready to encode remain frames */
+       /* context is ready to encode remaining frames */
        if (ctx->state == MFCINST_FINISHING &&
-               ctx->src_queue_cnt >= 1 && ctx->dst_queue_cnt >= 1)
+               ctx->dst_queue_cnt >= 1)
                return 1;
        mfc_debug(2, "ctx is not ready\n");
        return 0;
@@ -642,11 +643,8 @@ static int enc_post_seq_start(struct s5p_mfc_ctx *ctx)
                spin_unlock_irqrestore(&dev->irqlock, flags);
        }
        ctx->state = MFCINST_RUNNING;
-       if (s5p_mfc_ctx_ready(ctx)) {
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
-       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
        s5p_mfc_try_run(dev);
        return 0;
 }
@@ -724,7 +722,7 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
        if ((ctx->src_queue_cnt > 0) && (ctx->state == MFCINST_RUNNING)) {
                mb_entry = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
                                                                        list);
-               if (mb_entry->used) {
+               if (mb_entry->flags & MFC_BUF_FLAG_USED) {
                        list_del(&mb_entry->list);
                        ctx->src_queue_cnt--;
                        list_add_tail(&mb_entry->list, &ctx->ref_queue);
@@ -754,11 +752,8 @@ static int enc_post_frame_start(struct s5p_mfc_ctx *ctx)
                vb2_buffer_done(mb_entry->b, VB2_BUF_STATE_DONE);
        }
        spin_unlock_irqrestore(&dev->irqlock, flags);
-       if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0)) {
-               spin_lock(&dev->condlock);
-               clear_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock(&dev->condlock);
-       }
+       if ((ctx->src_queue_cnt == 0) || (ctx->dst_queue_cnt == 0))
+               clear_work_bit(ctx);
        return 0;
 }
 
@@ -921,7 +916,6 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
        struct s5p_mfc_fmt *fmt;
        struct v4l2_pix_format_mplane *pix_fmt_mp = &f->fmt.pix_mp;
-       unsigned long flags;
        int ret = 0;
 
        ret = vidioc_try_fmt(file, priv, f);
@@ -946,9 +940,7 @@ static int vidioc_s_fmt(struct file *file, void *priv, struct v4l2_format *f)
                ctx->dst_bufs_cnt = 0;
                ctx->capture_state = QUEUE_FREE;
                s5p_mfc_alloc_instance_buffer(ctx);
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
+               set_work_bit_irqsave(ctx);
                s5p_mfc_clean_ctx_int_flags(ctx);
                s5p_mfc_try_run(dev);
                if (s5p_mfc_wait_for_done_ctx(ctx, \
@@ -1119,27 +1111,43 @@ static int vidioc_qbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
                mfc_err("Call on QBUF after unrecoverable error\n");
                return -EIO;
        }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               if (ctx->state == MFCINST_FINISHING) {
+                       mfc_err("Call on QBUF after EOS command\n");
+                       return -EIO;
+               }
                return vb2_qbuf(&ctx->vq_src, buf);
-       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                return vb2_qbuf(&ctx->vq_dst, buf);
+       }
        return -EINVAL;
 }
 
 /* Dequeue a buffer */
 static int vidioc_dqbuf(struct file *file, void *priv, struct v4l2_buffer *buf)
 {
+       const struct v4l2_event ev = {
+               .type = V4L2_EVENT_EOS
+       };
        struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       int ret;
 
        if (ctx->state == MFCINST_ERROR) {
                mfc_err("Call on DQBUF after unrecoverable error\n");
                return -EIO;
        }
-       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE)
-               return vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
-       else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE)
-               return vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
-       return -EINVAL;
+       if (buf->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
+               ret = vb2_dqbuf(&ctx->vq_src, buf, file->f_flags & O_NONBLOCK);
+       } else if (buf->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
+               ret = vb2_dqbuf(&ctx->vq_dst, buf, file->f_flags & O_NONBLOCK);
+               if (ret == 0 && ctx->state == MFCINST_FINISHED
+                                       && list_empty(&ctx->vq_dst.done_list))
+                       v4l2_event_queue_fh(&ctx->fh, &ev);
+       } else {
+               ret = -EINVAL;
+       }
+
+       return ret;
 }
 
 /* Stream on */
@@ -1471,6 +1479,57 @@ static int vidioc_g_parm(struct file *file, void *priv,
        return 0;
 }
 
+int vidioc_encoder_cmd(struct file *file, void *priv,
+                                               struct v4l2_encoder_cmd *cmd)
+{
+       struct s5p_mfc_ctx *ctx = fh_to_ctx(priv);
+       struct s5p_mfc_dev *dev = ctx->dev;
+       struct s5p_mfc_buf *buf;
+       unsigned long flags;
+
+       switch (cmd->cmd) {
+       case V4L2_ENC_CMD_STOP:
+               if (cmd->flags != 0)
+                       return -EINVAL;
+
+               if (!ctx->vq_src.streaming)
+                       return -EINVAL;
+
+               spin_lock_irqsave(&dev->irqlock, flags);
+               if (list_empty(&ctx->src_queue)) {
+                       mfc_debug(2, "EOS: empty src queue, entering finishing state");
+                       ctx->state = MFCINST_FINISHING;
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+                       s5p_mfc_try_run(dev);
+               } else {
+                       mfc_debug(2, "EOS: marking last buffer of stream");
+                       buf = list_entry(ctx->src_queue.prev,
+                                               struct s5p_mfc_buf, list);
+                       if (buf->flags & MFC_BUF_FLAG_USED)
+                               ctx->state = MFCINST_FINISHING;
+                       else
+                               buf->flags |= MFC_BUF_FLAG_EOS;
+                       spin_unlock_irqrestore(&dev->irqlock, flags);
+               }
+               break;
+       default:
+               return -EINVAL;
+
+       }
+       return 0;
+}
+
+static int vidioc_subscribe_event(struct v4l2_fh *fh,
+                                       struct v4l2_event_subscription *sub)
+{
+       switch (sub->type) {
+       case V4L2_EVENT_EOS:
+               return v4l2_event_subscribe(fh, sub, 2, NULL);
+       default:
+               return -EINVAL;
+       }
+}
+
 static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
        .vidioc_querycap = vidioc_querycap,
        .vidioc_enum_fmt_vid_cap = vidioc_enum_fmt_vid_cap,
@@ -1491,6 +1550,9 @@ static const struct v4l2_ioctl_ops s5p_mfc_enc_ioctl_ops = {
        .vidioc_streamoff = vidioc_streamoff,
        .vidioc_s_parm = vidioc_s_parm,
        .vidioc_g_parm = vidioc_g_parm,
+       .vidioc_encoder_cmd = vidioc_encoder_cmd,
+       .vidioc_subscribe_event = vidioc_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
 };
 
 static int check_vb_with_fmt(struct s5p_mfc_fmt *fmt, struct vb2_buffer *vb)
@@ -1648,15 +1710,11 @@ static int s5p_mfc_start_streaming(struct vb2_queue *q, unsigned int count)
 {
        struct s5p_mfc_ctx *ctx = fh_to_ctx(q->drv_priv);
        struct s5p_mfc_dev *dev = ctx->dev;
-       unsigned long flags;
 
        v4l2_ctrl_handler_setup(&ctx->ctrl_handler);
        /* If context is ready then dev = work->data;schedule it to run */
-       if (s5p_mfc_ctx_ready(ctx)) {
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
-       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
        s5p_mfc_try_run(dev);
        return 0;
 }
@@ -1706,7 +1764,7 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
        }
        if (vq->type == V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE) {
                mfc_buf = &ctx->dst_bufs[vb->v4l2_buf.index];
-               mfc_buf->used = 0;
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
                /* Mark destination as available for use by MFC */
                spin_lock_irqsave(&dev->irqlock, flags);
                list_add_tail(&mfc_buf->list, &ctx->dst_queue);
@@ -1714,26 +1772,16 @@ static void s5p_mfc_buf_queue(struct vb2_buffer *vb)
                spin_unlock_irqrestore(&dev->irqlock, flags);
        } else if (vq->type == V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE) {
                mfc_buf = &ctx->src_bufs[vb->v4l2_buf.index];
-               mfc_buf->used = 0;
+               mfc_buf->flags &= ~MFC_BUF_FLAG_USED;
                spin_lock_irqsave(&dev->irqlock, flags);
-               if (vb->v4l2_planes[0].bytesused == 0) {
-                       mfc_debug(1, "change state to FINISHING\n");
-                       ctx->state = MFCINST_FINISHING;
-                       vb2_buffer_done(vb, VB2_BUF_STATE_DONE);
-                       cleanup_ref_queue(ctx);
-               } else {
-                       list_add_tail(&mfc_buf->list, &ctx->src_queue);
-                       ctx->src_queue_cnt++;
-               }
+               list_add_tail(&mfc_buf->list, &ctx->src_queue);
+               ctx->src_queue_cnt++;
                spin_unlock_irqrestore(&dev->irqlock, flags);
        } else {
                mfc_err("unsupported buffer type (%d)\n", vq->type);
        }
-       if (s5p_mfc_ctx_ready(ctx)) {
-               spin_lock_irqsave(&dev->condlock, flags);
-               set_bit(ctx->num, &dev->ctx_work_bits);
-               spin_unlock_irqrestore(&dev->condlock, flags);
-       }
+       if (s5p_mfc_ctx_ready(ctx))
+               set_work_bit_irqsave(ctx);
        s5p_mfc_try_run(dev);
 }
 
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc_enc.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
index 405bdd3ee083200fbea8a2462a66031d13952d79..ca9fd66bd310a287ff015ee3e041e3b3ccae5518 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_enc.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_enc.h
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 97%
rename from drivers/media/video/s5p-mfc/s5p_mfc_intr.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_intr.c
index 8f2f8bf4da7f81f00be7eeb65370a7caad373c93..37860e299021dddfd16f28f967e7412fb88d6ba5 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/samsung/mfc5/s5p_mfc_intr.c
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.c
  *
  * C file for Samsung MFC (Multi Function Codec - FIMV) driver
  * This file contains functions used to wait for command completion.
similarity index 93%
rename from drivers/media/video/s5p-mfc/s5p_mfc_intr.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_intr.h
index 122d7732f74522e76be7f2d8506185fc5cd1d248..18341a88514ead9aa3e707340929272acc692442 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/samsung/mfc5/s5p_mfc_intr.h
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_intr.h
  *
  * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
  * It contains waiting functions declarations.
similarity index 97%
rename from drivers/media/video/s5p-mfc/s5p_mfc_opr.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_opr.c
index e6217cbfa4a3e82612cee5dbae7c0afab0f13bda..767a51271dc248f8f7663545ae4e101acee9ea39 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/samsung/mfc5/s5p_mfc_opr.c
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.c
  *
  * Samsung MFC (Multi Function Codec - FIMV) driver
  * This file contains hw related functions.
@@ -1075,14 +1075,21 @@ int s5p_mfc_init_encode(struct s5p_mfc_ctx *ctx)
 int s5p_mfc_encode_one_frame(struct s5p_mfc_ctx *ctx)
 {
        struct s5p_mfc_dev *dev = ctx->dev;
+       int cmd;
        /* memory structure cur. frame */
        if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12M)
                mfc_write(dev, 0, S5P_FIMV_ENC_MAP_FOR_CUR);
        else if (ctx->src_fmt->fourcc == V4L2_PIX_FMT_NV12MT)
                mfc_write(dev, 3, S5P_FIMV_ENC_MAP_FOR_CUR);
        s5p_mfc_set_shared_buffer(ctx);
-       mfc_write(dev, (S5P_FIMV_CH_FRAME_START << 16 & 0x70000) |
-               (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
+       if (ctx->state == MFCINST_FINISHING)
+               cmd = S5P_FIMV_CH_LAST_FRAME;
+       else
+               cmd = S5P_FIMV_CH_FRAME_START;
+       mfc_write(dev, ((cmd & S5P_FIMV_CH_MASK) << S5P_FIMV_CH_SHIFT)
+                               | (ctx->inst_no), S5P_FIMV_SI_CH0_INST_ID);
+
        return 0;
 }
 
@@ -1133,7 +1140,7 @@ static int s5p_mfc_run_dec_frame(struct s5p_mfc_ctx *ctx, int last_frame)
        }
        /* Get the next source buffer */
        temp_vb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       temp_vb->used = 1;
+       temp_vb->flags |= MFC_BUF_FLAG_USED;
        s5p_mfc_set_dec_stream_buffer(ctx,
                vb2_dma_contig_plane_dma_addr(temp_vb->b, 0), ctx->consumed_stream,
                                        temp_vb->b->v4l2_planes[0].bytesused);
@@ -1160,7 +1167,7 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
        unsigned int dst_size;
 
        spin_lock_irqsave(&dev->irqlock, flags);
-       if (list_empty(&ctx->src_queue)) {
+       if (list_empty(&ctx->src_queue) && ctx->state != MFCINST_FINISHING) {
                mfc_debug(2, "no src buffers\n");
                spin_unlock_irqrestore(&dev->irqlock, flags);
                return -EAGAIN;
@@ -1170,19 +1177,40 @@ static int s5p_mfc_run_enc_frame(struct s5p_mfc_ctx *ctx)
                spin_unlock_irqrestore(&dev->irqlock, flags);
                return -EAGAIN;
        }
-       src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf, list);
-       src_mb->used = 1;
-       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 0);
-       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b, 1);
-       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr, src_c_addr);
+       if (list_empty(&ctx->src_queue)) {
+               /* send null frame */
+               s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2, dev->bank2);
+               src_mb = NULL;
+       } else {
+               src_mb = list_entry(ctx->src_queue.next, struct s5p_mfc_buf,
+                                                                       list);
+               src_mb->flags |= MFC_BUF_FLAG_USED;
+               if (src_mb->b->v4l2_planes[0].bytesused == 0) {
+                       /* send null frame */
+                       s5p_mfc_set_enc_frame_buffer(ctx, dev->bank2,
+                                                               dev->bank2);
+                       ctx->state = MFCINST_FINISHING;
+               } else {
+                       src_y_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       0);
+                       src_c_addr = vb2_dma_contig_plane_dma_addr(src_mb->b,
+                                                                       1);
+                       s5p_mfc_set_enc_frame_buffer(ctx, src_y_addr,
+                                                               src_c_addr);
+                       if (src_mb->flags & MFC_BUF_FLAG_EOS)
+                               ctx->state = MFCINST_FINISHING;
+               }
+       }
        dst_mb = list_entry(ctx->dst_queue.next, struct s5p_mfc_buf, list);
-       dst_mb->used = 1;
+       dst_mb->flags |= MFC_BUF_FLAG_USED;
        dst_addr = vb2_dma_contig_plane_dma_addr(dst_mb->b, 0);
        dst_size = vb2_plane_size(dst_mb->b, 0);
        s5p_mfc_set_enc_stream_buffer(ctx, dst_addr, dst_size);
        spin_unlock_irqrestore(&dev->irqlock, flags);
        dev->curr_ctx = ctx->num;
        s5p_mfc_clean_ctx_int_flags(ctx);
+       mfc_debug(2, "encoding buffer with index=%d state=%d",
+                       src_mb ? src_mb->b->v4l2_buf.index : -1, ctx->state);
        s5p_mfc_encode_one_frame(ctx);
        return 0;
 }
similarity index 98%
rename from drivers/media/video/s5p-mfc/s5p_mfc_opr.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_opr.h
index 5932d1c782c5dba36e18b55a6a3dcf6cda9f77da..2ad3def052f8836d844e27ef6bad80ec0d77d8dc 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * drivers/media/video/samsung/mfc5/s5p_mfc_opr.h
+ * drivers/media/platform/samsung/mfc5/s5p_mfc_opr.h
  *
  * Header file for Samsung MFC (Multi Function Codec - FIMV) driver
  * Contains declarations of hw related functions.
similarity index 98%
rename from drivers/media/video/s5p-mfc/s5p_mfc_pm.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
index 738a607be43c9b05b7a7040195fb4bea625a5cab..0503d14ac94e141931ca250f744f82db4476822c 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 92%
rename from drivers/media/video/s5p-mfc/s5p_mfc_pm.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_pm.h
index 5107914f27e46e9f29b30c8cb0a758013d5ea5c2..875c5346bc85416684f26e0659b47d9261b9ee90 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_pm.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_pm.h
  *
  * Copyright (C) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 96%
rename from drivers/media/video/s5p-mfc/s5p_mfc_shm.c
rename to drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
index 91fdbac8c37a2bf7647226fe7a84a500289803f4..b5933d233a4bdbb029dbdfdc9eb8b2fd52051420 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.c
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.c
  *
  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 98%
rename from drivers/media/video/s5p-mfc/s5p_mfc_shm.h
rename to drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
index cf962a4662766db5b1888f01c7e910fe245447c6..416ebd7ba35ad3d333d15d2d4f004b31937be366 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * linux/drivers/media/video/s5p-mfc/s5p_mfc_shm.h
+ * linux/drivers/media/platform/s5p-mfc/s5p_mfc_shm.h
  *
  * Copyright (c) 2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 98%
rename from drivers/media/video/s5p-tv/Kconfig
rename to drivers/media/platform/s5p-tv/Kconfig
index f248b285672090990bdea9f9bf81d6ff95adcae8..ea11a513033f6e436e5af6469dbb6cc6dfa5ba7b 100644 (file)
@@ -1,4 +1,4 @@
-# drivers/media/video/s5p-tv/Kconfig
+# drivers/media/platform/s5p-tv/Kconfig
 #
 # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
 #      http://www.samsung.com/
similarity index 92%
rename from drivers/media/video/s5p-tv/Makefile
rename to drivers/media/platform/s5p-tv/Makefile
index f49e756a2fde117e1096c29a6db7a5ef25f6be95..7cd47902e2691d606680860080185d13cbecdb10 100644 (file)
@@ -1,4 +1,4 @@
-# drivers/media/video/samsung/tvout/Makefile
+# drivers/media/platform/samsung/tvout/Makefile
 #
 # Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
 #      http://www.samsung.com/
similarity index 99%
rename from drivers/media/video/s5p-tv/hdmi_drv.c
rename to drivers/media/platform/s5p-tv/hdmi_drv.c
index 20cb6eef2979968bc669cd9dddee74441b0a15d6..8a9cf43018f635f48724953756108ec3ce800cb5 100644 (file)
@@ -11,6 +11,8 @@
  * or (at your option) any later version
  */
 
+#define pr_fmt(fmt) "s5p-tv (hdmi_drv): " fmt
+
 #ifdef CONFIG_VIDEO_SAMSUNG_S5P_HDMI_DEBUG
 #define DEBUG
 #endif
@@ -161,12 +163,12 @@ static irqreturn_t hdmi_irq_handler(int irq, void *dev_data)
        intc_flag = hdmi_read(hdev, HDMI_INTC_FLAG);
        /* clearing flags for HPD plug/unplug */
        if (intc_flag & HDMI_INTC_FLAG_HPD_UNPLUG) {
-               printk(KERN_INFO "unplugged\n");
+               pr_info("unplugged\n");
                hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
                        HDMI_INTC_FLAG_HPD_UNPLUG);
        }
        if (intc_flag & HDMI_INTC_FLAG_HPD_PLUG) {
-               printk(KERN_INFO "plugged\n");
+               pr_info("plugged\n");
                hdmi_write_mask(hdev, HDMI_INTC_FLAG, ~0,
                        HDMI_INTC_FLAG_HPD_PLUG);
        }
similarity index 98%
rename from drivers/media/video/s5p-tv/mixer_drv.c
rename to drivers/media/platform/s5p-tv/mixer_drv.c
index edca06592883af71a1fee9b191f7acd3d723214c..ca0f2971744851e6ee9770fcc3227ad8c699be72 100644 (file)
@@ -384,7 +384,7 @@ static int __devinit mxr_probe(struct platform_device *pdev)
 
        mdev = kzalloc(sizeof *mdev, GFP_KERNEL);
        if (!mdev) {
-               mxr_err(mdev, "not enough memory.\n");
+               dev_err(dev, "not enough memory.\n");
                ret = -ENOMEM;
                goto fail;
        }
@@ -461,10 +461,10 @@ static struct platform_driver mxr_driver __refdata = {
 static int __init mxr_init(void)
 {
        int i, ret;
-       static const char banner[] __initconst = KERN_INFO
+       static const char banner[] __initconst =
                "Samsung TV Mixer driver, "
                "(c) 2010-2011 Samsung Electronics Co., Ltd.\n";
-       printk(banner);
+       pr_info("%s\n", banner);
 
        /* Loading auxiliary modules */
        for (i = 0; i < ARRAY_SIZE(mxr_output_conf); ++i)
@@ -472,7 +472,7 @@ static int __init mxr_init(void)
 
        ret = platform_driver_register(&mxr_driver);
        if (ret != 0) {
-               printk(KERN_ERR "registration of MIXER driver failed\n");
+               pr_err("s5p-tv: registration of MIXER driver failed\n");
                return -ENXIO;
        }
 
similarity index 97%
rename from drivers/media/video/s5p-tv/mixer_video.c
rename to drivers/media/platform/s5p-tv/mixer_video.c
index 6c74b05d1f95382e691feb48f863e96b175d1a4b..0c1cd895ff660453dfff91f5ac40feea5d67535d 100644 (file)
@@ -11,6 +11,8 @@
  * or (at your option) any later version
  */
 
+#define pr_fmt(fmt) "s5p-tv (mixer): " fmt
+
 #include "mixer.h"
 
 #include <media/v4l2-ioctl.h>
@@ -162,9 +164,8 @@ static int mxr_querycap(struct file *file, void *priv,
        strlcpy(cap->driver, MXR_DRIVER_NAME, sizeof cap->driver);
        strlcpy(cap->card, layer->vfd.name, sizeof cap->card);
        sprintf(cap->bus_info, "%d", layer->idx);
-       cap->version = KERNEL_VERSION(0, 1, 0);
-       cap->capabilities = V4L2_CAP_STREAMING |
-               V4L2_CAP_VIDEO_OUTPUT | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+       cap->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_VIDEO_OUTPUT_MPLANE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
 
        return 0;
 }
@@ -716,7 +717,7 @@ static int mxr_streamoff(struct file *file, void *priv, enum v4l2_buf_type i)
 static const struct v4l2_ioctl_ops mxr_ioctl_ops = {
        .vidioc_querycap = mxr_querycap,
        /* format handling */
-       .vidioc_enum_fmt_vid_out = mxr_enum_fmt,
+       .vidioc_enum_fmt_vid_out_mplane = mxr_enum_fmt,
        .vidioc_s_fmt_vid_out_mplane = mxr_s_fmt,
        .vidioc_g_fmt_vid_out_mplane = mxr_g_fmt,
        /* buffer control */
@@ -750,18 +751,20 @@ static int mxr_video_open(struct file *file)
        int ret = 0;
 
        mxr_dbg(mdev, "%s:%d\n", __func__, __LINE__);
+       if (mutex_lock_interruptible(&layer->mutex))
+               return -ERESTARTSYS;
        /* assure device probe is finished */
        wait_for_device_probe();
        /* creating context for file descriptor */
        ret = v4l2_fh_open(file);
        if (ret) {
                mxr_err(mdev, "v4l2_fh_open failed\n");
-               return ret;
+               goto unlock;
        }
 
        /* leaving if layer is already initialized */
        if (!v4l2_fh_is_singular_file(file))
-               return 0;
+               goto unlock;
 
        /* FIXME: should power be enabled on open? */
        ret = mxr_power_get(mdev);
@@ -779,6 +782,7 @@ static int mxr_video_open(struct file *file)
        layer->fmt = layer->fmt_array[0];
        /* setup default geometry */
        mxr_layer_default_geo(layer);
+       mutex_unlock(&layer->mutex);
 
        return 0;
 
@@ -788,6 +792,9 @@ fail_power:
 fail_fh_open:
        v4l2_fh_release(file);
 
+unlock:
+       mutex_unlock(&layer->mutex);
+
        return ret;
 }
 
@@ -795,19 +802,28 @@ static unsigned int
 mxr_video_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct mxr_layer *layer = video_drvdata(file);
+       unsigned int res;
 
        mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
 
-       return vb2_poll(&layer->vb_queue, file, wait);
+       mutex_lock(&layer->mutex);
+       res = vb2_poll(&layer->vb_queue, file, wait);
+       mutex_unlock(&layer->mutex);
+       return res;
 }
 
 static int mxr_video_mmap(struct file *file, struct vm_area_struct *vma)
 {
        struct mxr_layer *layer = video_drvdata(file);
+       int ret;
 
        mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
 
-       return vb2_mmap(&layer->vb_queue, vma);
+       if (mutex_lock_interruptible(&layer->mutex))
+               return -ERESTARTSYS;
+       ret = vb2_mmap(&layer->vb_queue, vma);
+       mutex_unlock(&layer->mutex);
+       return ret;
 }
 
 static int mxr_video_release(struct file *file)
@@ -815,11 +831,13 @@ static int mxr_video_release(struct file *file)
        struct mxr_layer *layer = video_drvdata(file);
 
        mxr_dbg(layer->mdev, "%s:%d\n", __func__, __LINE__);
+       mutex_lock(&layer->mutex);
        if (v4l2_fh_is_singular_file(file)) {
                vb2_queue_release(&layer->vb_queue);
                mxr_power_put(layer->mdev);
        }
        v4l2_fh_release(file);
+       mutex_unlock(&layer->mutex);
        return 0;
 }
 
@@ -1036,7 +1054,7 @@ void mxr_base_layer_release(struct mxr_layer *layer)
 
 static void mxr_vfd_release(struct video_device *vdev)
 {
-       printk(KERN_INFO "video device release\n");
+       pr_info("video device release\n");
 }
 
 struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
@@ -1062,6 +1080,7 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
                .minor = -1,
                .release = mxr_vfd_release,
                .fops = &mxr_fops,
+               .vfl_dir = VFL_DIR_TX,
                .ioctl_ops = &mxr_ioctl_ops,
        };
        strlcpy(layer->vfd.name, name, sizeof(layer->vfd.name));
@@ -1069,10 +1088,6 @@ struct mxr_layer *mxr_base_layer_create(struct mxr_device *mdev,
        set_bit(V4L2_FL_USE_FH_PRIO, &layer->vfd.flags);
 
        video_set_drvdata(&layer->vfd, layer);
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &layer->vfd.flags);
        layer->vfd.lock = &layer->mutex;
        layer->vfd.v4l2_dev = &mdev->v4l2_dev;
 
similarity index 97%
rename from drivers/media/video/s5p-tv/regs-sdo.h
rename to drivers/media/platform/s5p-tv/regs-sdo.h
index 7f7c2b8ac14099f9ee3dd1b6d6eda79cddd0c2f8..6f22fbfe2f6c471bb5467dd31e86a42ce143d3e2 100644 (file)
@@ -1,4 +1,4 @@
-/* drivers/media/video/s5p-tv/regs-sdo.h
+/* drivers/media/platform/s5p-tv/regs-sdo.h
  *
  * Copyright (c) 2010-2011 Samsung Electronics Co., Ltd.
  *             http://www.samsung.com/
similarity index 98%
rename from drivers/media/video/s5p-tv/sdo_drv.c
rename to drivers/media/platform/s5p-tv/sdo_drv.c
index f6bca2c20e8923d1cc6a3b5d1e44d452e8acdf2f..ad68bbed014e2c3a31119c0f4ea46c0317903b5f 100644 (file)
@@ -374,15 +374,15 @@ static int __devinit sdo_probe(struct platform_device *pdev)
        dev_info(dev, "fout_vpll.rate = %lu\n", clk_get_rate(sclk_vpll));
 
        /* acquire regulator */
-       sdev->vdac = regulator_get(dev, "vdd33a_dac");
+       sdev->vdac = devm_regulator_get(dev, "vdd33a_dac");
        if (IS_ERR_OR_NULL(sdev->vdac)) {
                dev_err(dev, "failed to get regulator 'vdac'\n");
                goto fail_fout_vpll;
        }
-       sdev->vdet = regulator_get(dev, "vdet");
+       sdev->vdet = devm_regulator_get(dev, "vdet");
        if (IS_ERR_OR_NULL(sdev->vdet)) {
                dev_err(dev, "failed to get regulator 'vdet'\n");
-               goto fail_vdac;
+               goto fail_fout_vpll;
        }
 
        /* enable gate for dac clock, because mixer uses it */
@@ -406,8 +406,6 @@ static int __devinit sdo_probe(struct platform_device *pdev)
        dev_info(dev, "probe succeeded\n");
        return 0;
 
-fail_vdac:
-       regulator_put(sdev->vdac);
 fail_fout_vpll:
        clk_put(sdev->fout_vpll);
 fail_dacphy:
@@ -428,8 +426,6 @@ static int __devexit sdo_remove(struct platform_device *pdev)
 
        pm_runtime_disable(&pdev->dev);
        clk_disable(sdev->dac);
-       regulator_put(sdev->vdet);
-       regulator_put(sdev->vdac);
        clk_put(sdev->fout_vpll);
        clk_put(sdev->dacphy);
        clk_put(sdev->dac);
similarity index 97%
rename from drivers/media/video/s5p-tv/sii9234_drv.c
rename to drivers/media/platform/s5p-tv/sii9234_drv.c
index 6d348f90237af244c6d4436d7f094ba2d973dab3..716d4846f8bdba7cadf04e992fc36ece0ffac226 100644 (file)
@@ -323,7 +323,7 @@ static int __devinit sii9234_probe(struct i2c_client *client,
        struct sii9234_context *ctx;
        int ret;
 
-       ctx = kzalloc(sizeof(*ctx), GFP_KERNEL);
+       ctx = devm_kzalloc(&client->dev, sizeof(*ctx), GFP_KERNEL);
        if (!ctx) {
                dev_err(dev, "out of memory\n");
                ret = -ENOMEM;
@@ -331,18 +331,17 @@ static int __devinit sii9234_probe(struct i2c_client *client,
        }
        ctx->client = client;
 
-       ctx->power = regulator_get(dev, "hdmi-en");
+       ctx->power = devm_regulator_get(dev, "hdmi-en");
        if (IS_ERR(ctx->power)) {
                dev_err(dev, "failed to acquire regulator hdmi-en\n");
-               ret = PTR_ERR(ctx->power);
-               goto fail_ctx;
+               return PTR_ERR(ctx->power);
        }
 
        ctx->gpio_n_reset = pdata->gpio_n_reset;
        ret = gpio_request(ctx->gpio_n_reset, "MHL_RST");
        if (ret) {
                dev_err(dev, "failed to acquire MHL_RST gpio\n");
-               goto fail_power;
+               return ret;
        }
 
        v4l2_i2c_subdev_init(&ctx->sd, client, &sii9234_ops);
@@ -373,12 +372,6 @@ fail_pm:
        pm_runtime_disable(dev);
        gpio_free(ctx->gpio_n_reset);
 
-fail_power:
-       regulator_put(ctx->power);
-
-fail_ctx:
-       kfree(ctx);
-
 fail:
        dev_err(dev, "probe failed\n");
 
@@ -393,8 +386,6 @@ static int __devexit sii9234_remove(struct i2c_client *client)
 
        pm_runtime_disable(dev);
        gpio_free(ctx->gpio_n_reset);
-       regulator_put(ctx->power);
-       kfree(ctx);
 
        dev_info(dev, "remove successful\n");
 
similarity index 97%
rename from drivers/media/video/sh_vou.c
rename to drivers/media/platform/sh_vou.c
index 8fd1874382c65f7479fddb819a6c171aa6305579..85fd312f0a829fee9f45b1e682694cc3fc475cf3 100644 (file)
@@ -933,7 +933,7 @@ static int sh_vou_g_crop(struct file *file, void *fh, struct v4l2_crop *a)
 }
 
 /* Assume a dull encoder, do all the work ourselves. */
-static int sh_vou_s_crop(struct file *file, void *fh, struct v4l2_crop *a)
+static int sh_vou_s_crop(struct file *file, void *fh, const struct v4l2_crop *a)
 {
        struct video_device *vdev = video_devdata(file);
        struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
@@ -1171,6 +1171,8 @@ static int sh_vou_open(struct file *file)
 
        file->private_data = vou_file;
 
+       if (mutex_lock_interruptible(&vou_dev->fop_lock))
+               return -ERESTARTSYS;
        if (atomic_inc_return(&vou_dev->use_count) == 1) {
                int ret;
                /* First open */
@@ -1181,6 +1183,7 @@ static int sh_vou_open(struct file *file)
                        atomic_dec(&vou_dev->use_count);
                        pm_runtime_put(vdev->v4l2_dev->dev);
                        vou_dev->status = SH_VOU_IDLE;
+                       mutex_unlock(&vou_dev->fop_lock);
                        return ret;
                }
        }
@@ -1191,6 +1194,7 @@ static int sh_vou_open(struct file *file)
                                       V4L2_FIELD_NONE,
                                       sizeof(struct videobuf_buffer), vdev,
                                       &vou_dev->fop_lock);
+       mutex_unlock(&vou_dev->fop_lock);
 
        return 0;
 }
@@ -1204,10 +1208,12 @@ static int sh_vou_release(struct file *file)
        dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
 
        if (!atomic_dec_return(&vou_dev->use_count)) {
+               mutex_lock(&vou_dev->fop_lock);
                /* Last close */
                vou_dev->status = SH_VOU_IDLE;
                sh_vou_reg_a_set(vou_dev, VOUER, 0, 0x101);
                pm_runtime_put(vdev->v4l2_dev->dev);
+               mutex_unlock(&vou_dev->fop_lock);
        }
 
        file->private_data = NULL;
@@ -1218,20 +1224,33 @@ static int sh_vou_release(struct file *file)
 
 static int sh_vou_mmap(struct file *file, struct vm_area_struct *vma)
 {
+       struct video_device *vdev = video_devdata(file);
+       struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
        struct sh_vou_file *vou_file = file->private_data;
+       int ret;
 
        dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
 
-       return videobuf_mmap_mapper(&vou_file->vbq, vma);
+       if (mutex_lock_interruptible(&vou_dev->fop_lock))
+               return -ERESTARTSYS;
+       ret = videobuf_mmap_mapper(&vou_file->vbq, vma);
+       mutex_unlock(&vou_dev->fop_lock);
+       return ret;
 }
 
 static unsigned int sh_vou_poll(struct file *file, poll_table *wait)
 {
+       struct video_device *vdev = video_devdata(file);
+       struct sh_vou_device *vou_dev = video_get_drvdata(vdev);
        struct sh_vou_file *vou_file = file->private_data;
+       unsigned int res;
 
        dev_dbg(vou_file->vbq.dev, "%s()\n", __func__);
 
-       return videobuf_poll_stream(file, &vou_file->vbq, wait);
+       mutex_lock(&vou_dev->fop_lock);
+       res = videobuf_poll_stream(file, &vou_file->vbq, wait);
+       mutex_unlock(&vou_dev->fop_lock);
+       return res;
 }
 
 static int sh_vou_g_chip_ident(struct file *file, void *fh,
@@ -1303,6 +1322,7 @@ static const struct video_device sh_vou_video_template = {
        .ioctl_ops      = &sh_vou_ioctl_ops,
        .tvnorms        = V4L2_STD_525_60, /* PAL only supported in 8-bit non-bt656 mode */
        .current_norm   = V4L2_STD_NTSC_M,
+       .vfl_dir        = VFL_DIR_TX,
 };
 
 static int __devinit sh_vou_probe(struct platform_device *pdev)
@@ -1390,10 +1410,6 @@ static int __devinit sh_vou_probe(struct platform_device *pdev)
        vdev->v4l2_dev = &vou_dev->v4l2_dev;
        vdev->release = video_device_release;
        vdev->lock = &vou_dev->fop_lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
 
        vou_dev->vdev = vdev;
        video_set_drvdata(vdev, vou_dev);
diff --git a/drivers/media/platform/soc_camera/Kconfig b/drivers/media/platform/soc_camera/Kconfig
new file mode 100644 (file)
index 0000000..9afe1e7
--- /dev/null
@@ -0,0 +1,87 @@
+config SOC_CAMERA
+       tristate "SoC camera support"
+       depends on VIDEO_V4L2 && HAS_DMA && I2C
+       select VIDEOBUF_GEN
+       select VIDEOBUF2_CORE
+       help
+         SoC Camera is a common API to several cameras, not connecting
+         over a bus like PCI or USB. For example some i2c camera connected
+         directly to the data bus of an SoC.
+
+config SOC_CAMERA_PLATFORM
+       tristate "platform camera support"
+       depends on SOC_CAMERA
+       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 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 MX3_VIDEO
+       bool
+
+config VIDEO_MX3
+       tristate "i.MX3x Camera Sensor Interface driver"
+       depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
+       select VIDEOBUF2_DMA_CONTIG
+       select MX3_VIDEO
+       ---help---
+         This is a v4l2 driver for the i.MX3x Camera Sensor Interface
+
+config VIDEO_PXA27x
+       tristate "PXA27x Quick Capture Interface driver"
+       depends on VIDEO_DEV && PXA27x && SOC_CAMERA
+       select VIDEOBUF_DMA_SG
+       ---help---
+         This is a v4l2 driver for the PXA27x Quick Capture Interface
+
+config VIDEO_SH_MOBILE_CSI2
+       tristate "SuperH Mobile MIPI CSI-2 Interface driver"
+       depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
+       ---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
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         This is a v4l2 driver for the SuperH Mobile CEU Interface
+
+config VIDEO_OMAP1
+       tristate "OMAP1 Camera Interface driver"
+       depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA
+       select VIDEOBUF_DMA_CONTIG
+       select VIDEOBUF_DMA_SG
+       ---help---
+         This is a v4l2 driver for the TI OMAP1 camera interface
+
+config VIDEO_MX2_HOSTSUPPORT
+       bool
+
+config VIDEO_MX2
+       tristate "i.MX27/i.MX25 Camera Sensor Interface driver"
+       depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || (ARCH_MX25 && BROKEN))
+       select VIDEOBUF2_DMA_CONTIG
+       select VIDEO_MX2_HOSTSUPPORT
+       ---help---
+         This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor
+         Interface
+
+config VIDEO_ATMEL_ISI
+       tristate "ATMEL Image Sensor Interface (ISI) support"
+       depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91
+       select VIDEOBUF2_DMA_CONTIG
+       ---help---
+         This module makes the ATMEL Image Sensor Interface available
+         as a v4l2 device.
+
diff --git a/drivers/media/platform/soc_camera/Makefile b/drivers/media/platform/soc_camera/Makefile
new file mode 100644 (file)
index 0000000..136b7f8
--- /dev/null
@@ -0,0 +1,14 @@
+obj-$(CONFIG_SOC_CAMERA)               += soc_camera.o soc_mediabus.o
+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
+obj-$(CONFIG_VIDEO_PXA27x)             += pxa_camera.o
+obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)      += sh_mobile_ceu_camera.o
+obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)     += sh_mobile_csi2.o
+
+ccflags-y += -I$(srctree)/drivers/media/i2c/soc_camera
similarity index 93%
rename from drivers/media/video/mx2_camera.c
rename to drivers/media/platform/soc_camera/mx2_camera.c
index 965427f279a5b827c348a06f2cc7715f924482fd..403d7f17bfab1277adba82ed59d0650f99dd16aa 100644 (file)
@@ -274,12 +274,9 @@ struct mx2_camera_dev {
        struct soc_camera_device *icd;
        struct clk              *clk_csi, *clk_emma_ahb, *clk_emma_ipg;
 
-       unsigned int            irq_csi, irq_emma;
        void __iomem            *base_csi, *base_emma;
-       unsigned long           base_dma;
 
        struct mx2_camera_platform_data *pdata;
-       struct resource         *res_csi, *res_emma;
        unsigned long           platform_flags;
 
        struct list_head        capture;
@@ -335,6 +332,34 @@ static struct mx2_fmt_cfg mx27_emma_prp_table[] = {
                        .csicr1         = 0,
                }
        },
+       {
+               .in_fmt         = V4L2_MBUS_FMT_UYVY8_2X8,
+               .out_fmt        = V4L2_PIX_FMT_YUYV,
+               .cfg            = {
+                       .channel        = 1,
+                       .in_fmt         = PRP_CNTL_DATA_IN_YUV422,
+                       .out_fmt        = PRP_CNTL_CH1_OUT_YUV422,
+                       .src_pixel      = 0x22000888, /* YUV422 (YUYV) */
+                       .ch1_pixel      = 0x62000888, /* YUV422 (YUYV) */
+                       .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
+                                               PRP_INTR_CH1FC | PRP_INTR_LBOVF,
+                       .csicr1         = CSICR1_SWAP16_EN,
+               }
+       },
+       {
+               .in_fmt         = V4L2_MBUS_FMT_YUYV8_2X8,
+               .out_fmt        = V4L2_PIX_FMT_YUYV,
+               .cfg            = {
+                       .channel        = 1,
+                       .in_fmt         = PRP_CNTL_DATA_IN_YUV422,
+                       .out_fmt        = PRP_CNTL_CH1_OUT_YUV422,
+                       .src_pixel      = 0x22000888, /* YUV422 (YUYV) */
+                       .ch1_pixel      = 0x62000888, /* YUV422 (YUYV) */
+                       .irq_flags      = PRP_INTR_RDERR | PRP_INTR_CH1WERR |
+                                               PRP_INTR_CH1FC | PRP_INTR_LBOVF,
+                       .csicr1         = CSICR1_PACK_DIR,
+               }
+       },
        {
                .in_fmt         = V4L2_MBUS_FMT_YUYV8_2X8,
                .out_fmt        = V4L2_PIX_FMT_YUV420,
@@ -441,11 +466,9 @@ static int mx2_camera_add_device(struct soc_camera_device *icd)
 
        csicr1 = CSICR1_MCLKEN;
 
-       if (cpu_is_mx27()) {
+       if (cpu_is_mx27())
                csicr1 |= CSICR1_PRP_IF_EN | CSICR1_FCC |
                        CSICR1_RXFF_LEVEL(0);
-       } else if (cpu_is_mx27())
-               csicr1 |= CSICR1_SOF_INTEN | CSICR1_RXFF_LEVEL(2);
 
        pcdev->csicr1 = csicr1;
        writel(pcdev->csicr1, pcdev->base_csi + CSICR1);
@@ -1142,6 +1165,18 @@ static int mx2_camera_get_formats(struct soc_camera_device *icd,
                }
        }
 
+       if (code == V4L2_MBUS_FMT_UYVY8_2X8) {
+               formats++;
+               if (xlate) {
+                       xlate->host_fmt =
+                               soc_mbus_get_fmtdesc(V4L2_MBUS_FMT_YUYV8_2X8);
+                       xlate->code     = code;
+                       dev_dbg(dev, "Providing host format %s for sensor code %d\n",
+                               xlate->host_fmt->name, code);
+                       xlate++;
+               }
+       }
+
        /* Generic pass-trough */
        formats++;
        if (xlate) {
@@ -1609,64 +1644,59 @@ static irqreturn_t mx27_camera_emma_irq(int irq_emma, void *data)
        return IRQ_HANDLED;
 }
 
-static int __devinit mx27_camera_emma_init(struct mx2_camera_dev *pcdev)
+static int __devinit mx27_camera_emma_init(struct platform_device *pdev)
 {
-       struct resource *res_emma = pcdev->res_emma;
+       struct mx2_camera_dev *pcdev = platform_get_drvdata(pdev);
+       struct resource *res_emma;
+       int irq_emma;
        int err = 0;
 
-       if (!request_mem_region(res_emma->start, resource_size(res_emma),
-                               MX2_CAM_DRV_NAME)) {
-               err = -EBUSY;
+       res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1);
+       irq_emma = platform_get_irq(pdev, 1);
+       if (!res_emma || !irq_emma) {
+               dev_err(pcdev->dev, "no EMMA resources\n");
                goto out;
        }
 
-       pcdev->base_emma = ioremap(res_emma->start, resource_size(res_emma));
+       pcdev->base_emma = devm_request_and_ioremap(pcdev->dev, res_emma);
        if (!pcdev->base_emma) {
-               err = -ENOMEM;
-               goto exit_release;
+               err = -EADDRNOTAVAIL;
+               goto out;
        }
 
-       err = request_irq(pcdev->irq_emma, mx27_camera_emma_irq, 0,
-                       MX2_CAM_DRV_NAME, pcdev);
+       err = devm_request_irq(pcdev->dev, irq_emma, mx27_camera_emma_irq, 0,
+                              MX2_CAM_DRV_NAME, pcdev);
        if (err) {
                dev_err(pcdev->dev, "Camera EMMA interrupt register failed \n");
-               goto exit_iounmap;
+               goto out;
        }
 
-       pcdev->clk_emma_ipg = clk_get(pcdev->dev, "emma-ipg");
+       pcdev->clk_emma_ipg = devm_clk_get(pcdev->dev, "emma-ipg");
        if (IS_ERR(pcdev->clk_emma_ipg)) {
                err = PTR_ERR(pcdev->clk_emma_ipg);
-               goto exit_free_irq;
+               goto out;
        }
 
        clk_prepare_enable(pcdev->clk_emma_ipg);
 
-       pcdev->clk_emma_ahb = clk_get(pcdev->dev, "emma-ahb");
+       pcdev->clk_emma_ahb = devm_clk_get(pcdev->dev, "emma-ahb");
        if (IS_ERR(pcdev->clk_emma_ahb)) {
                err = PTR_ERR(pcdev->clk_emma_ahb);
-               goto exit_clk_emma_ipg_put;
+               goto exit_clk_emma_ipg;
        }
 
        clk_prepare_enable(pcdev->clk_emma_ahb);
 
        err = mx27_camera_emma_prp_reset(pcdev);
        if (err)
-               goto exit_clk_emma_ahb_put;
+               goto exit_clk_emma_ahb;
 
        return err;
 
-exit_clk_emma_ahb_put:
+exit_clk_emma_ahb:
        clk_disable_unprepare(pcdev->clk_emma_ahb);
-       clk_put(pcdev->clk_emma_ahb);
-exit_clk_emma_ipg_put:
+exit_clk_emma_ipg:
        clk_disable_unprepare(pcdev->clk_emma_ipg);
-       clk_put(pcdev->clk_emma_ipg);
-exit_free_irq:
-       free_irq(pcdev->irq_emma, pcdev);
-exit_iounmap:
-       iounmap(pcdev->base_emma);
-exit_release:
-       release_mem_region(res_emma->start, resource_size(res_emma));
 out:
        return err;
 }
@@ -1674,9 +1704,8 @@ out:
 static int __devinit mx2_camera_probe(struct platform_device *pdev)
 {
        struct mx2_camera_dev *pcdev;
-       struct resource *res_csi, *res_emma;
-       void __iomem *base_csi;
-       int irq_csi, irq_emma;
+       struct resource *res_csi;
+       int irq_csi;
        int err = 0;
 
        dev_dbg(&pdev->dev, "initialising\n");
@@ -1689,21 +1718,20 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
                goto exit;
        }
 
-       pcdev = kzalloc(sizeof(*pcdev), GFP_KERNEL);
+       pcdev = devm_kzalloc(&pdev->dev, sizeof(*pcdev), GFP_KERNEL);
        if (!pcdev) {
                dev_err(&pdev->dev, "Could not allocate pcdev\n");
                err = -ENOMEM;
                goto exit;
        }
 
-       pcdev->clk_csi = clk_get(&pdev->dev, "ahb");
+       pcdev->clk_csi = devm_clk_get(&pdev->dev, "ahb");
        if (IS_ERR(pcdev->clk_csi)) {
                dev_err(&pdev->dev, "Could not get csi clock\n");
                err = PTR_ERR(pcdev->clk_csi);
-               goto exit_kfree;
+               goto exit;
        }
 
-       pcdev->res_csi = res_csi;
        pcdev->pdata = pdev->dev.platform_data;
        if (pcdev->pdata) {
                long rate;
@@ -1713,11 +1741,11 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
                rate = clk_round_rate(pcdev->clk_csi, pcdev->pdata->clk * 2);
                if (rate <= 0) {
                        err = -ENODEV;
-                       goto exit_dma_free;
+                       goto exit;
                }
                err = clk_set_rate(pcdev->clk_csi, rate);
                if (err < 0)
-                       goto exit_dma_free;
+                       goto exit;
        }
 
        INIT_LIST_HEAD(&pcdev->capture);
@@ -1725,50 +1753,36 @@ static int __devinit mx2_camera_probe(struct platform_device *pdev)
        INIT_LIST_HEAD(&pcdev->discard);
        spin_lock_init(&pcdev->lock);
 
-       /*
-        * Request the regions.
-        */
-       if (!request_mem_region(res_csi->start, resource_size(res_csi),
-                               MX2_CAM_DRV_NAME)) {
-               err = -EBUSY;
-               goto exit_dma_free;
+       pcdev->base_csi = devm_request_and_ioremap(&pdev->dev, res_csi);
+       if (!pcdev->base_csi) {
+               err = -EADDRNOTAVAIL;
+               goto exit;
        }
 
-       base_csi = ioremap(res_csi->start, resource_size(res_csi));
-       if (!base_csi) {
-               err = -ENOMEM;
-               goto exit_release;
-       }
-       pcdev->irq_csi = irq_csi;
-       pcdev->base_csi = base_csi;
-       pcdev->base_dma = res_csi->start;
        pcdev->dev = &pdev->dev;
+       platform_set_drvdata(pdev, pcdev);
 
        if (cpu_is_mx25()) {
-               err = request_irq(pcdev->irq_csi, mx25_camera_irq, 0,
-                               MX2_CAM_DRV_NAME, pcdev);
+               err = devm_request_irq(&pdev->dev, irq_csi, mx25_camera_irq, 0,
+                                      MX2_CAM_DRV_NAME, pcdev);
                if (err) {
                        dev_err(pcdev->dev, "Camera interrupt register failed \n");
-                       goto exit_iounmap;
+                       goto exit;
                }
        }
 
        if (cpu_is_mx27()) {
-               /* EMMA support */
-               res_emma = platform_get_resource(pdev, IORESOURCE_MEM, 1);
-               irq_emma = platform_get_irq(pdev, 1);
-
-               if (!res_emma || !irq_emma) {
-                       dev_err(&pdev->dev, "no EMMA resources\n");
-                       goto exit_free_irq;
-               }
-
-               pcdev->res_emma = res_emma;
-               pcdev->irq_emma = irq_emma;
-               if (mx27_camera_emma_init(pcdev))
-                       goto exit_free_irq;
+               err = mx27_camera_emma_init(pdev);
+               if (err)
+                       goto exit;
        }
 
+       /*
+        * We're done with drvdata here.  Clear the pointer so that
+        * v4l2 core can start using drvdata on its purpose.
+        */
+       platform_set_drvdata(pdev, NULL);
+
        pcdev->soc_host.drv_name        = MX2_CAM_DRV_NAME,
        pcdev->soc_host.ops             = &mx2_soc_camera_host_ops,
        pcdev->soc_host.priv            = pcdev;
@@ -1795,25 +1809,9 @@ exit_free_emma:
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 eallocctx:
        if (cpu_is_mx27()) {
-               free_irq(pcdev->irq_emma, pcdev);
                clk_disable_unprepare(pcdev->clk_emma_ipg);
-               clk_put(pcdev->clk_emma_ipg);
                clk_disable_unprepare(pcdev->clk_emma_ahb);
-               clk_put(pcdev->clk_emma_ahb);
-               iounmap(pcdev->base_emma);
-               release_mem_region(pcdev->res_emma->start, resource_size(pcdev->res_emma));
        }
-exit_free_irq:
-       if (cpu_is_mx25())
-               free_irq(pcdev->irq_csi, pcdev);
-exit_iounmap:
-       iounmap(base_csi);
-exit_release:
-       release_mem_region(res_csi->start, resource_size(res_csi));
-exit_dma_free:
-       clk_put(pcdev->clk_csi);
-exit_kfree:
-       kfree(pcdev);
 exit:
        return err;
 }
@@ -1823,35 +1821,16 @@ static int __devexit mx2_camera_remove(struct platform_device *pdev)
        struct soc_camera_host *soc_host = to_soc_camera_host(&pdev->dev);
        struct mx2_camera_dev *pcdev = container_of(soc_host,
                        struct mx2_camera_dev, soc_host);
-       struct resource *res;
-
-       clk_put(pcdev->clk_csi);
-       if (cpu_is_mx25())
-               free_irq(pcdev->irq_csi, pcdev);
-       if (cpu_is_mx27())
-               free_irq(pcdev->irq_emma, pcdev);
 
        soc_camera_host_unregister(&pcdev->soc_host);
 
        vb2_dma_contig_cleanup_ctx(pcdev->alloc_ctx);
 
-       iounmap(pcdev->base_csi);
-
        if (cpu_is_mx27()) {
                clk_disable_unprepare(pcdev->clk_emma_ipg);
-               clk_put(pcdev->clk_emma_ipg);
                clk_disable_unprepare(pcdev->clk_emma_ahb);
-               clk_put(pcdev->clk_emma_ahb);
-               iounmap(pcdev->base_emma);
-               res = pcdev->res_emma;
-               release_mem_region(res->start, resource_size(res));
        }
 
-       res = pcdev->res_csi;
-       release_mem_region(res->start, resource_size(res));
-
-       kfree(pcdev);
-
        dev_info(&pdev->dev, "MX2 Camera driver unloaded\n");
 
        return 0;
similarity index 99%
rename from drivers/media/video/mx3_camera.c
rename to drivers/media/platform/soc_camera/mx3_camera.c
index 1481b0d419da8da4c8874c01cc26cd7d5703bac2..3557ac97e4303f4743330850a5144f43cb06cbd0 100644 (file)
@@ -1171,9 +1171,7 @@ static int __devinit mx3_camera_probe(struct platform_device *pdev)
 
        mx3_cam->pdata = pdev->dev.platform_data;
        mx3_cam->platform_flags = mx3_cam->pdata->flags;
-       if (!(mx3_cam->platform_flags & (MX3_CAMERA_DATAWIDTH_4 |
-                       MX3_CAMERA_DATAWIDTH_8 | MX3_CAMERA_DATAWIDTH_10 |
-                       MX3_CAMERA_DATAWIDTH_15))) {
+       if (!(mx3_cam->platform_flags & MX3_CAMERA_DATAWIDTH_MASK)) {
                /*
                 * Platform hasn't set available data widths. This is bad.
                 * Warn and use a default.
similarity index 99%
rename from drivers/media/video/omap1_camera.c
rename to drivers/media/platform/soc_camera/omap1_camera.c
index c7e41145041fc0cc77ed0ce421070b9a0ca22432..fa08c7695ccb05aa61d680d8bcf4f002516d2894 100644 (file)
@@ -12,7 +12,7 @@
  * Copyright (C) 2008, Guennadi Liakhovetski <kernel@pengutronix.de>
  *
  * Hardware specific bits initialy based on former work by Matt Callow
- * drivers/media/video/omap/omap1510cam.c
+ * drivers/media/platform/omap/omap1510cam.c
  * Copyright (C) 2006 Matt Callow
  *
  * This program is free software; you can redistribute it and/or modify
similarity index 99%
rename from drivers/media/video/sh_mobile_ceu_camera.c
rename to drivers/media/platform/soc_camera/sh_mobile_ceu_camera.c
index 0baaf94db7e03081d71770a0076fb4c1516e718e..0a24253dcda2a9afd42d4a2bfb017a5c016171ac 100644 (file)
@@ -1263,7 +1263,7 @@ static void update_subrect(struct sh_mobile_ceu_cam *cam)
  * 3. if (2) failed, try to request the maximum image
  */
 static int client_s_crop(struct soc_camera_device *icd, struct v4l2_crop *crop,
-                        struct v4l2_crop *cam_crop)
+                        const struct v4l2_crop *cam_crop)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        struct v4l2_rect *rect = &crop->c, *cam_rect = &cam_crop->c;
@@ -1517,7 +1517,7 @@ static int client_scale(struct soc_camera_device *icd,
  * scaling and cropping algorithms and for the meaning of referenced here steps.
  */
 static int sh_mobile_ceu_set_crop(struct soc_camera_device *icd,
-                                 struct v4l2_crop *a)
+                                 const struct v4l2_crop *a)
 {
        struct v4l2_rect *rect = &a->c;
        struct device *dev = icd->parent;
similarity index 91%
rename from drivers/media/video/soc_camera.c
rename to drivers/media/platform/soc_camera/soc_camera.c
index 1bde255e45dfcd4554594e6fd5f844d130fa5d16..3be92944f8e7efd7e44d8ff0f7acf37c8f8af084 100644 (file)
@@ -50,66 +50,77 @@ static LIST_HEAD(hosts);
 static LIST_HEAD(devices);
 static DEFINE_MUTEX(list_lock);                /* Protects the list of hosts */
 
-static int soc_camera_power_on(struct soc_camera_device *icd,
-                              struct soc_camera_link *icl)
+int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl)
 {
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        int ret = regulator_bulk_enable(icl->num_regulators,
                                        icl->regulators);
        if (ret < 0) {
-               dev_err(icd->pdev, "Cannot enable regulators\n");
+               dev_err(dev, "Cannot enable regulators\n");
                return ret;
        }
 
        if (icl->power) {
-               ret = icl->power(icd->control, 1);
+               ret = icl->power(dev, 1);
                if (ret < 0) {
-                       dev_err(icd->pdev,
+                       dev_err(dev,
                                "Platform failed to power-on the camera.\n");
-                       goto elinkpwr;
+                       regulator_bulk_disable(icl->num_regulators,
+                                              icl->regulators);
                }
        }
 
-       ret = v4l2_subdev_call(sd, core, s_power, 1);
-       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
-               goto esdpwr;
-
-       return 0;
-
-esdpwr:
-       if (icl->power)
-               icl->power(icd->control, 0);
-elinkpwr:
-       regulator_bulk_disable(icl->num_regulators,
-                              icl->regulators);
        return ret;
 }
+EXPORT_SYMBOL(soc_camera_power_on);
 
-static int soc_camera_power_off(struct soc_camera_device *icd,
-                               struct soc_camera_link *icl)
+int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl)
 {
-       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
-       int ret = v4l2_subdev_call(sd, core, s_power, 0);
-
-       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
-               return ret;
+       int ret = 0;
+       int err;
 
        if (icl->power) {
-               ret = icl->power(icd->control, 0);
-               if (ret < 0) {
-                       dev_err(icd->pdev,
+               err = icl->power(dev, 0);
+               if (err < 0) {
+                       dev_err(dev,
                                "Platform failed to power-off the camera.\n");
-                       return ret;
+                       ret = err;
                }
        }
 
-       ret = regulator_bulk_disable(icl->num_regulators,
+       err = regulator_bulk_disable(icl->num_regulators,
                                     icl->regulators);
-       if (ret < 0)
-               dev_err(icd->pdev, "Cannot disable regulators\n");
+       if (err < 0) {
+               dev_err(dev, "Cannot disable regulators\n");
+               ret = ret ? : err;
+       }
 
        return ret;
 }
+EXPORT_SYMBOL(soc_camera_power_off);
+
+static int __soc_camera_power_on(struct soc_camera_device *icd)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       int ret;
+
+       ret = v4l2_subdev_call(sd, core, s_power, 1);
+       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               return ret;
+
+       return 0;
+}
+
+static int __soc_camera_power_off(struct soc_camera_device *icd)
+{
+       struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
+       int ret;
+
+       ret = v4l2_subdev_call(sd, core, s_power, 0);
+       if (ret < 0 && ret != -ENOIOCTLCMD && ret != -ENODEV)
+               return ret;
+
+       return 0;
+}
 
 const struct soc_camera_format_xlate *soc_camera_xlate_by_fourcc(
        struct soc_camera_device *icd, unsigned int fourcc)
@@ -508,9 +519,12 @@ static int soc_camera_open(struct file *file)
 
        ici = to_soc_camera_host(icd->parent);
 
+       if (mutex_lock_interruptible(&icd->video_lock))
+               return -ERESTARTSYS;
        if (!try_module_get(ici->ops->owner)) {
                dev_err(icd->pdev, "Couldn't lock capture bus driver.\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto emodule;
        }
 
        icd->use_count++;
@@ -543,7 +557,7 @@ static int soc_camera_open(struct file *file)
                        goto eiciadd;
                }
 
-               ret = soc_camera_power_on(icd, icl);
+               ret = __soc_camera_power_on(icd);
                if (ret < 0)
                        goto epower;
 
@@ -571,6 +585,7 @@ static int soc_camera_open(struct file *file)
                }
                v4l2_ctrl_handler_setup(&icd->ctrl_handler);
        }
+       mutex_unlock(&icd->video_lock);
 
        file->private_data = icd;
        dev_dbg(icd->pdev, "camera device open\n");
@@ -585,12 +600,14 @@ einitvb:
 esfmt:
        pm_runtime_disable(&icd->vdev->dev);
 eresume:
-       soc_camera_power_off(icd, icl);
+       __soc_camera_power_off(icd);
 epower:
        ici->ops->remove(icd);
 eiciadd:
        icd->use_count--;
        module_put(ici->ops->owner);
+emodule:
+       mutex_unlock(&icd->video_lock);
 
        return ret;
 }
@@ -600,10 +617,9 @@ static int soc_camera_close(struct file *file)
        struct soc_camera_device *icd = file->private_data;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
 
+       mutex_lock(&icd->video_lock);
        icd->use_count--;
        if (!icd->use_count) {
-               struct soc_camera_link *icl = to_soc_camera_link(icd);
-
                pm_runtime_suspend(&icd->vdev->dev);
                pm_runtime_disable(&icd->vdev->dev);
 
@@ -611,11 +627,12 @@ static int soc_camera_close(struct file *file)
                        vb2_queue_release(&icd->vb2_vidq);
                ici->ops->remove(icd);
 
-               soc_camera_power_off(icd, icl);
+               __soc_camera_power_off(icd);
        }
 
        if (icd->streamer == file)
                icd->streamer = NULL;
+       mutex_unlock(&icd->video_lock);
 
        module_put(ici->ops->owner);
 
@@ -646,10 +663,13 @@ static int soc_camera_mmap(struct file *file, struct vm_area_struct *vma)
        if (icd->streamer != file)
                return -EBUSY;
 
+       if (mutex_lock_interruptible(&icd->video_lock))
+               return -ERESTARTSYS;
        if (ici->ops->init_videobuf)
                err = videobuf_mmap_mapper(&icd->vb_vidq, vma);
        else
                err = vb2_mmap(&icd->vb2_vidq, vma);
+       mutex_unlock(&icd->video_lock);
 
        dev_dbg(icd->pdev, "vma start=0x%08lx, size=%ld, ret=%d\n",
                (unsigned long)vma->vm_start,
@@ -663,16 +683,18 @@ static unsigned int soc_camera_poll(struct file *file, poll_table *pt)
 {
        struct soc_camera_device *icd = file->private_data;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       unsigned res = POLLERR;
 
        if (icd->streamer != file)
-               return -EBUSY;
-
-       if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream)) {
-               dev_err(icd->pdev, "Trying to poll with no queued buffers!\n");
                return POLLERR;
-       }
 
-       return ici->ops->poll(file, pt);
+       mutex_lock(&icd->video_lock);
+       if (ici->ops->init_videobuf && list_empty(&icd->vb_vidq.stream))
+               dev_err(icd->pdev, "Trying to poll with no queued buffers!\n");
+       else
+               res = ici->ops->poll(file, pt);
+       mutex_unlock(&icd->video_lock);
+       return res;
 }
 
 void soc_camera_lock(struct vb2_queue *vq)
@@ -866,11 +888,11 @@ static int soc_camera_g_crop(struct file *file, void *fh,
  * retrieve it.
  */
 static int soc_camera_s_crop(struct file *file, void *fh,
-                            struct v4l2_crop *a)
+                            const struct v4l2_crop *a)
 {
        struct soc_camera_device *icd = file->private_data;
        struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
-       struct v4l2_rect *rect = &a->c;
+       const struct v4l2_rect *rect = &a->c;
        struct v4l2_crop current_crop;
        int ret;
 
@@ -903,6 +925,65 @@ static int soc_camera_s_crop(struct file *file, void *fh,
        return ret;
 }
 
+static int soc_camera_g_selection(struct file *file, void *fh,
+                                 struct v4l2_selection *s)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+
+       /* With a wrong type no need to try to fall back to cropping */
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
+               return -EINVAL;
+
+       if (!ici->ops->get_selection)
+               return -ENOTTY;
+
+       return ici->ops->get_selection(icd, s);
+}
+
+static int soc_camera_s_selection(struct file *file, void *fh,
+                                 struct v4l2_selection *s)
+{
+       struct soc_camera_device *icd = file->private_data;
+       struct soc_camera_host *ici = to_soc_camera_host(icd->parent);
+       int ret;
+
+       /* In all these cases cropping emulation will not help */
+       if (s->type != V4L2_BUF_TYPE_VIDEO_CAPTURE ||
+           (s->target != V4L2_SEL_TGT_COMPOSE_ACTIVE &&
+            s->target != V4L2_SEL_TGT_CROP_ACTIVE))
+               return -EINVAL;
+
+       if (s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+               /* No output size change during a running capture! */
+               if (is_streaming(ici, icd) &&
+                   (icd->user_width != s->r.width ||
+                    icd->user_height != s->r.height))
+                       return -EBUSY;
+
+               /*
+                * Only one user is allowed to change the output format, touch
+                * buffers, start / stop streaming, poll for data
+                */
+               if (icd->streamer && icd->streamer != file)
+                       return -EBUSY;
+       }
+
+       if (!ici->ops->set_selection)
+               return -ENOTTY;
+
+       ret = ici->ops->set_selection(icd, s);
+       if (!ret &&
+           s->target == V4L2_SEL_TGT_COMPOSE_ACTIVE) {
+               icd->user_width = s->r.width;
+               icd->user_height = s->r.height;
+               if (!icd->streamer)
+                       icd->streamer = file;
+       }
+
+       return ret;
+}
+
 static int soc_camera_g_parm(struct file *file, void *fh,
                             struct v4l2_streamparm *a)
 {
@@ -1065,16 +1146,6 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        if (ret < 0)
                goto eadd;
 
-       /*
-        * This will not yet call v4l2_subdev_core_ops::s_power(1), because the
-        * subdevice has not been initialised yet. We'll have to call it once
-        * again after initialisation, even though it shouldn't be needed, we
-        * don't do any IO here.
-        */
-       ret = soc_camera_power_on(icd, icl);
-       if (ret < 0)
-               goto epower;
-
        /* Must have icd->vdev before registering the device */
        ret = video_dev_create(icd);
        if (ret < 0)
@@ -1113,7 +1184,7 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        sd->grp_id = soc_camera_grp_id(icd);
        v4l2_set_subdev_hostdata(sd, icd);
 
-       if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler))
+       if (v4l2_ctrl_add_handler(&icd->ctrl_handler, sd->ctrl_handler, NULL))
                goto ectrl;
 
        /* At this point client .probe() should have run already */
@@ -1134,10 +1205,6 @@ static int soc_camera_probe(struct soc_camera_device *icd)
        if (ret < 0)
                goto evidstart;
 
-       ret = v4l2_subdev_call(sd, core, s_power, 1);
-       if (ret < 0 && ret != -ENOIOCTLCMD)
-               goto esdpwr;
-
        /* Try to improve our guess of a reasonable window format */
        if (!v4l2_subdev_call(sd, video, g_mbus_fmt, &mf)) {
                icd->user_width         = mf.width;
@@ -1148,14 +1215,10 @@ static int soc_camera_probe(struct soc_camera_device *icd)
 
        ici->ops->remove(icd);
 
-       soc_camera_power_off(icd, icl);
-
        mutex_unlock(&icd->video_lock);
 
        return 0;
 
-esdpwr:
-       video_unregister_device(icd->vdev);
 evidstart:
        mutex_unlock(&icd->video_lock);
        soc_camera_free_user_formats(icd);
@@ -1172,8 +1235,6 @@ eadddev:
        video_device_release(icd->vdev);
        icd->vdev = NULL;
 evdc:
-       soc_camera_power_off(icd, icl);
-epower:
        ici->ops->remove(icd);
 eadd:
        regulator_bulk_free(icl->num_regulators, icl->regulators);
@@ -1228,7 +1289,7 @@ static int default_g_crop(struct soc_camera_device *icd, struct v4l2_crop *a)
        return v4l2_subdev_call(sd, video, g_crop, a);
 }
 
-static int default_s_crop(struct soc_camera_device *icd, struct v4l2_crop *a)
+static int default_s_crop(struct soc_camera_device *icd, const struct v4l2_crop *a)
 {
        struct v4l2_subdev *sd = soc_camera_to_subdev(icd);
        return v4l2_subdev_call(sd, video, s_crop, a);
@@ -1406,6 +1467,8 @@ static const struct v4l2_ioctl_ops soc_camera_ioctl_ops = {
        .vidioc_cropcap          = soc_camera_cropcap,
        .vidioc_g_crop           = soc_camera_g_crop,
        .vidioc_s_crop           = soc_camera_s_crop,
+       .vidioc_g_selection      = soc_camera_g_selection,
+       .vidioc_s_selection      = soc_camera_s_selection,
        .vidioc_g_parm           = soc_camera_g_parm,
        .vidioc_s_parm           = soc_camera_s_parm,
        .vidioc_g_chip_ident     = soc_camera_g_chip_ident,
@@ -1433,10 +1496,6 @@ static int video_dev_create(struct soc_camera_device *icd)
        vdev->tvnorms           = V4L2_STD_UNKNOWN;
        vdev->ctrl_handler      = &icd->ctrl_handler;
        vdev->lock              = &icd->video_lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
 
        icd->vdev = vdev;
 
similarity index 94%
rename from drivers/media/video/soc_camera_platform.c
rename to drivers/media/platform/soc_camera/soc_camera_platform.c
index f59ccade07c8b5cb9a0c3ebb4c4bdb539e2cbea8..7cf7fd16481fbd65f8820a3374ca4009de68eee7 100644 (file)
@@ -50,7 +50,16 @@ static int soc_camera_platform_fill_fmt(struct v4l2_subdev *sd,
        return 0;
 }
 
-static struct v4l2_subdev_core_ops platform_subdev_core_ops;
+static int soc_camera_platform_s_power(struct v4l2_subdev *sd, int on)
+{
+       struct soc_camera_platform_info *p = v4l2_get_subdevdata(sd);
+
+       return soc_camera_set_power(p->icd->control, p->icd->link, on);
+}
+
+static struct v4l2_subdev_core_ops platform_subdev_core_ops = {
+       .s_power = soc_camera_platform_s_power,
+};
 
 static int soc_camera_platform_enum_fmt(struct v4l2_subdev *sd, unsigned int index,
                                        enum v4l2_mbus_pixelcode *code)
similarity index 99%
rename from drivers/media/video/vino.c
rename to drivers/media/platform/vino.c
index aae1720b2f2d14a0ceb1ca1080fafdb125d28fc4..790d96cffeea7d7ca0bbb808a23173e3b77373df 100644 (file)
@@ -3284,7 +3284,7 @@ static int vino_g_crop(struct file *file, void *__fh,
 }
 
 static int vino_s_crop(struct file *file, void *__fh,
-                           struct v4l2_crop *c)
+                           const struct v4l2_crop *c)
 {
        struct vino_channel_settings *vcs = video_drvdata(file);
        unsigned long flags;
similarity index 97%
rename from drivers/media/video/vivi.c
rename to drivers/media/platform/vivi.c
index a05494b71b20a7247a8bfb27c05304dcf8ae3272..b366b050a3dd487473345d1ddaee013b2740513f 100644 (file)
@@ -80,7 +80,8 @@ static const u8 *font8x16;
 struct vivi_fmt {
        char  *name;
        u32   fourcc;          /* v4l2 format id */
-       int   depth;
+       u8    depth;
+       bool  is_yuv;
 };
 
 static struct vivi_fmt formats[] = {
@@ -88,21 +89,25 @@ static struct vivi_fmt formats[] = {
                .name     = "4:2:2, packed, YUYV",
                .fourcc   = V4L2_PIX_FMT_YUYV,
                .depth    = 16,
+               .is_yuv   = true,
        },
        {
                .name     = "4:2:2, packed, UYVY",
                .fourcc   = V4L2_PIX_FMT_UYVY,
                .depth    = 16,
+               .is_yuv   = true,
        },
        {
                .name     = "4:2:2, packed, YVYU",
                .fourcc   = V4L2_PIX_FMT_YVYU,
                .depth    = 16,
+               .is_yuv   = true,
        },
        {
                .name     = "4:2:2, packed, VYUY",
                .fourcc   = V4L2_PIX_FMT_VYUY,
                .depth    = 16,
+               .is_yuv   = true,
        },
        {
                .name     = "RGB565 (LE)",
@@ -309,15 +314,9 @@ static void precalculate_bars(struct vivi_dev *dev)
                r = bars[dev->input].bar[k][0];
                g = bars[dev->input].bar[k][1];
                b = bars[dev->input].bar[k][2];
-               is_yuv = 0;
+               is_yuv = dev->fmt->is_yuv;
 
                switch (dev->fmt->fourcc) {
-               case V4L2_PIX_FMT_YUYV:
-               case V4L2_PIX_FMT_UYVY:
-               case V4L2_PIX_FMT_YVYU:
-               case V4L2_PIX_FMT_VYUY:
-                       is_yuv = 1;
-                       break;
                case V4L2_PIX_FMT_RGB565:
                case V4L2_PIX_FMT_RGB565X:
                        r >>= 3;
@@ -330,6 +329,10 @@ static void precalculate_bars(struct vivi_dev *dev)
                        g >>= 3;
                        b >>= 3;
                        break;
+               case V4L2_PIX_FMT_YUYV:
+               case V4L2_PIX_FMT_UYVY:
+               case V4L2_PIX_FMT_YVYU:
+               case V4L2_PIX_FMT_VYUY:
                case V4L2_PIX_FMT_RGB24:
                case V4L2_PIX_FMT_BGR24:
                case V4L2_PIX_FMT_RGB32:
@@ -895,7 +898,8 @@ static int vidioc_querycap(struct file *file, void  *priv,
 
        strcpy(cap->driver, "vivi");
        strcpy(cap->card, "vivi");
-       strlcpy(cap->bus_info, dev->v4l2_dev.name, sizeof(cap->bus_info));
+       snprintf(cap->bus_info, sizeof(cap->bus_info),
+                       "platform:%s", dev->v4l2_dev.name);
        cap->device_caps = V4L2_CAP_VIDEO_CAPTURE | V4L2_CAP_STREAMING |
                            V4L2_CAP_READWRITE;
        cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
@@ -930,8 +934,7 @@ static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
                (f->fmt.pix.width * dev->fmt->depth) >> 3;
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
-       if (dev->fmt->fourcc == V4L2_PIX_FMT_YUYV ||
-           dev->fmt->fourcc == V4L2_PIX_FMT_UYVY)
+       if (dev->fmt->is_yuv)
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        else
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
@@ -959,11 +962,11 @@ static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
                (f->fmt.pix.width * fmt->depth) >> 3;
        f->fmt.pix.sizeimage =
                f->fmt.pix.height * f->fmt.pix.bytesperline;
-       if (fmt->fourcc == V4L2_PIX_FMT_YUYV ||
-           fmt->fourcc == V4L2_PIX_FMT_UYVY)
+       if (fmt->is_yuv)
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
        else
                f->fmt.pix.colorspace = V4L2_COLORSPACE_SRGB;
+       f->fmt.pix.priv = 0;
        return 0;
 }
 
@@ -990,6 +993,27 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
+static int vidioc_enum_framesizes(struct file *file, void *fh,
+                                        struct v4l2_frmsizeenum *fsize)
+{
+       static const struct v4l2_frmsize_stepwise sizes = {
+               48, MAX_WIDTH, 4,
+               32, MAX_HEIGHT, 1
+       };
+       int i;
+
+       if (fsize->index)
+               return -EINVAL;
+       for (i = 0; i < ARRAY_SIZE(formats); i++)
+               if (formats[i].fourcc == fsize->pixel_format)
+                       break;
+       if (i == ARRAY_SIZE(formats))
+               return -EINVAL;
+       fsize->type = V4L2_FRMSIZE_TYPE_STEPWISE;
+       fsize->stepwise = sizes;
+       return 0;
+}
+
 /* only one input in this sample driver */
 static int vidioc_enum_input(struct file *file, void *priv,
                                struct v4l2_input *inp)
@@ -1174,6 +1198,7 @@ static const struct v4l2_ioctl_ops vivi_ioctl_ops = {
        .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
        .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
        .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_enum_framesizes   = vidioc_enum_framesizes,
        .vidioc_reqbufs       = vb2_ioctl_reqbufs,
        .vidioc_create_bufs   = vb2_ioctl_create_bufs,
        .vidioc_prepare_buf   = vb2_ioctl_prepare_buf,
@@ -1282,7 +1307,6 @@ static int __init vivi_create_instance(int inst)
 
        /* initialize queue */
        q = &dev->vb_vidq;
-       memset(q, 0, sizeof(dev->vb_vidq));
        q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        q->io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
        q->drv_priv = dev;
@@ -1290,7 +1314,9 @@ static int __init vivi_create_instance(int inst)
        q->ops = &vivi_video_qops;
        q->mem_ops = &vb2_vmalloc_memops;
 
-       vb2_queue_init(q);
+       ret = vb2_queue_init(q);
+       if (ret)
+               goto unreg_dev;
 
        mutex_init(&dev->mutex);
 
index 79adf3e654e5f57d678199539be2c153daf40265..e10e525f33e51f0a14b5c3f5b7ef0006ae3524cb 100644 (file)
@@ -203,7 +203,7 @@ static int vidioc_g_modulator(struct file *file, void *priv,
 }
 
 static int vidioc_s_modulator(struct file *file, void *priv,
-                               struct v4l2_modulator *v)
+                               const struct v4l2_modulator *v)
 {
        struct keene_device *radio = video_drvdata(file);
 
index 87c1ee13b058541b0ec9cfa3f0f33c75f173334b..11f76ed4c6fb7082e6f9de5f3ba717cab9f40faa 100644 (file)
@@ -197,7 +197,7 @@ static int vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
-                               struct v4l2_audio *a)
+                               const struct v4l2_audio *a)
 {
        return a->index ? -EINVAL : 0;
 }
index 3182b26d6efa8f99cb50fdc7d81d5b9681782ab9..9c5a267b60b46f80f35a0326771cffa3666a12c9 100644 (file)
@@ -348,7 +348,7 @@ static int vidioc_g_frequency(struct file *file, void *priv,
 }
 
 static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
-               struct v4l2_hw_freq_seek *seek)
+               const struct v4l2_hw_freq_seek *seek)
 {
        static u8 buf[8] = {
                0x3d, 0x32, 0x0f, 0x08, 0x3d, 0x32, 0x0f, 0x08
@@ -360,6 +360,9 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *priv,
        if (seek->tuner != 0 || !seek->wrap_around)
                return -EINVAL;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
        retval = amradio_send_cmd(radio,
                        AMRADIO_SET_SEARCH_LVL, 0, buf, 8, false);
        if (retval)
index 8185d5fbfa89af74cf0153a822659a69e4846f8b..227dcdb54df358235111f42518686b404317b76a 100644 (file)
@@ -239,7 +239,7 @@ static int vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
+                                       const struct v4l2_audio *a)
 {
        return a->index ? -EINVAL : 0;
 }
index 72ded29728bbb2cbf459184095be31cf45a81270..8c309c7134d7f0e0abb60be8a83e03578e2cfc9e 100644 (file)
@@ -59,7 +59,8 @@ MODULE_LICENSE("GPL");
 
 #define v4l2_dev_to_shark(d) container_of(d, struct shark_device, v4l2_dev)
 
-enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS };
+/* Note BLUE_IS_PULSE comes after NO_LEDS as it is a status bit, not a LED */
+enum { BLUE_LED, BLUE_PULSE_LED, RED_LED, NO_LEDS, BLUE_IS_PULSE };
 
 struct shark_device {
        struct usb_device *usbdev;
@@ -190,6 +191,7 @@ static void shark_led_set_blue(struct led_classdev *led_cdev,
 
        atomic_set(&shark->brightness[BLUE_LED], value);
        set_bit(BLUE_LED, &shark->brightness_new);
+       clear_bit(BLUE_IS_PULSE, &shark->brightness_new);
        schedule_work(&shark->led_work);
 }
 
@@ -201,6 +203,7 @@ static void shark_led_set_blue_pulse(struct led_classdev *led_cdev,
 
        atomic_set(&shark->brightness[BLUE_PULSE_LED], 256 - value);
        set_bit(BLUE_PULSE_LED, &shark->brightness_new);
+       set_bit(BLUE_IS_PULSE, &shark->brightness_new);
        schedule_work(&shark->led_work);
 }
 
@@ -240,6 +243,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
        int i, retval;
 
+       atomic_set(&shark->brightness[BLUE_LED], 127);
        INIT_WORK(&shark->led_work, shark_led_work);
        for (i = 0; i < NO_LEDS; i++) {
                shark->leds[i] = shark_led_templates[i];
@@ -266,6 +270,16 @@ static void shark_unregister_leds(struct shark_device *shark)
 
        cancel_work_sync(&shark->led_work);
 }
+
+static void shark_resume_leds(struct shark_device *shark)
+{
+       if (test_bit(BLUE_IS_PULSE, &shark->brightness_new))
+               set_bit(BLUE_PULSE_LED, &shark->brightness_new);
+       else
+               set_bit(BLUE_LED, &shark->brightness_new);
+       set_bit(RED_LED, &shark->brightness_new);
+       schedule_work(&shark->led_work);
+}
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
@@ -274,6 +288,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev)
        return 0;
 }
 static inline void shark_unregister_leds(struct shark_device *shark) { }
+static inline void shark_resume_leds(struct shark_device *shark) { }
 #endif
 
 static void usb_shark_disconnect(struct usb_interface *intf)
@@ -333,6 +348,7 @@ static int usb_shark_probe(struct usb_interface *intf,
        shark->tea.radio_nr = -1;
        shark->tea.ops = &shark_tea_ops;
        shark->tea.cannot_mute = true;
+       shark->tea.has_am = true;
        strlcpy(shark->tea.card, "Griffin radioSHARK",
                sizeof(shark->tea.card));
        usb_make_path(shark->usbdev, shark->tea.bus_info,
@@ -358,6 +374,27 @@ err_alloc_buffer:
        return retval;
 }
 
+#ifdef CONFIG_PM
+static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       return 0;
+}
+
+static int usb_shark_resume(struct usb_interface *intf)
+{
+       struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
+       struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
+
+       mutex_lock(&shark->tea.mutex);
+       snd_tea575x_set_freq(&shark->tea);
+       mutex_unlock(&shark->tea.mutex);
+
+       shark_resume_leds(shark);
+
+       return 0;
+}
+#endif
+
 /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */
 static struct usb_device_id usb_shark_device_table[] = {
        { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
@@ -377,5 +414,10 @@ static struct usb_driver usb_shark_driver = {
        .probe                  = usb_shark_probe,
        .disconnect             = usb_shark_disconnect,
        .id_table               = usb_shark_device_table,
+#ifdef CONFIG_PM
+       .suspend                = usb_shark_suspend,
+       .resume                 = usb_shark_resume,
+       .reset_resume           = usb_shark_resume,
+#endif
 };
 module_usb_driver(usb_shark_driver);
index 7b4efdfaae283748edea0dc359ae647667add6b6..ef65ebbd536451a276244e0119da4b2674fe97b1 100644 (file)
@@ -86,12 +86,8 @@ static int shark_write_reg(struct radio_tea5777 *tea, u64 reg)
        for (i = 0; i < 6; i++)
                shark->transfer_buffer[i + 1] = (reg >> (40 - i * 8)) & 0xff;
 
-       v4l2_dbg(1, debug, tea->v4l2_dev,
-                "shark2-write: %02x %02x %02x %02x %02x %02x %02x\n",
-                shark->transfer_buffer[0], shark->transfer_buffer[1],
-                shark->transfer_buffer[2], shark->transfer_buffer[3],
-                shark->transfer_buffer[4], shark->transfer_buffer[5],
-                shark->transfer_buffer[6]);
+       v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-write: %*ph\n",
+                7, shark->transfer_buffer);
 
        res = usb_interrupt_msg(shark->usbdev,
                                usb_sndintpipe(shark->usbdev, SHARK_OUT_EP),
@@ -134,9 +130,8 @@ static int shark_read_reg(struct radio_tea5777 *tea, u32 *reg_ret)
        for (i = 0; i < 3; i++)
                reg |= shark->transfer_buffer[i] << (16 - i * 8);
 
-       v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %02x %02x %02x\n",
-                shark->transfer_buffer[0], shark->transfer_buffer[1],
-                shark->transfer_buffer[2]);
+       v4l2_dbg(1, debug, tea->v4l2_dev, "shark2-read: %*ph\n",
+                3, shark->transfer_buffer);
 
        *reg_ret = reg;
        return 0;
@@ -214,6 +209,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
        int i, retval;
 
+       atomic_set(&shark->brightness[BLUE_LED], 127);
        INIT_WORK(&shark->led_work, shark_led_work);
        for (i = 0; i < NO_LEDS; i++) {
                shark->leds[i] = shark_led_templates[i];
@@ -240,6 +236,16 @@ static void shark_unregister_leds(struct shark_device *shark)
 
        cancel_work_sync(&shark->led_work);
 }
+
+static void shark_resume_leds(struct shark_device *shark)
+{
+       int i;
+
+       for (i = 0; i < NO_LEDS; i++)
+               set_bit(i, &shark->brightness_new);
+
+       schedule_work(&shark->led_work);
+}
 #else
 static int shark_register_leds(struct shark_device *shark, struct device *dev)
 {
@@ -248,6 +254,7 @@ static int shark_register_leds(struct shark_device *shark, struct device *dev)
        return 0;
 }
 static inline void shark_unregister_leds(struct shark_device *shark) { }
+static inline void shark_resume_leds(struct shark_device *shark) { }
 #endif
 
 static void usb_shark_disconnect(struct usb_interface *intf)
@@ -332,6 +339,28 @@ err_alloc_buffer:
        return retval;
 }
 
+#ifdef CONFIG_PM
+static int usb_shark_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       return 0;
+}
+
+static int usb_shark_resume(struct usb_interface *intf)
+{
+       struct v4l2_device *v4l2_dev = usb_get_intfdata(intf);
+       struct shark_device *shark = v4l2_dev_to_shark(v4l2_dev);
+       int ret;
+
+       mutex_lock(&shark->tea.mutex);
+       ret = radio_tea5777_set_freq(&shark->tea);
+       mutex_unlock(&shark->tea.mutex);
+
+       shark_resume_leds(shark);
+
+       return ret;
+}
+#endif
+
 /* Specify the bcdDevice value, as the radioSHARK and radioSHARK2 share ids */
 static struct usb_device_id usb_shark_device_table[] = {
        { .match_flags = USB_DEVICE_ID_MATCH_DEVICE_AND_VERSION |
@@ -351,5 +380,10 @@ static struct usb_driver usb_shark_driver = {
        .probe                  = usb_shark_probe,
        .disconnect             = usb_shark_disconnect,
        .id_table               = usb_shark_device_table,
+#ifdef CONFIG_PM
+       .suspend                = usb_shark_suspend,
+       .resume                 = usb_shark_resume,
+       .reset_resume           = usb_shark_resume,
+#endif
 };
 module_usb_driver(usb_shark_driver);
index c54210c7fef90783200ccec467230fa6a7f3dc69..a082e400ed0f6ed8022fd3562231e5cc969c10d2 100644 (file)
@@ -83,7 +83,7 @@ static int radio_si4713_g_audout(struct file *file, void *priv,
 }
 
 static int radio_si4713_s_audout(struct file *file, void *priv,
-                                       struct v4l2_audioout *vao)
+                                       const struct v4l2_audioout *vao)
 {
        return vao->index ? -EINVAL : 0;
 }
@@ -200,7 +200,7 @@ static int radio_si4713_g_modulator(struct file *file, void *p,
 }
 
 static int radio_si4713_s_modulator(struct file *file, void *p,
-                                               struct v4l2_modulator *vm)
+                                               const struct v4l2_modulator *vm)
 {
        return v4l2_device_call_until_err(get_v4l2_dev(file), 0, tuner,
                                                        s_modulator, vm);
@@ -268,7 +268,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
                goto exit;
        }
 
-       rsdev = kzalloc(sizeof *rsdev, GFP_KERNEL);
+       rsdev = devm_kzalloc(&pdev->dev, sizeof(*rsdev), GFP_KERNEL);
        if (!rsdev) {
                dev_err(&pdev->dev, "Failed to alloc video device.\n");
                rval = -ENOMEM;
@@ -278,7 +278,7 @@ static int radio_si4713_pdriver_probe(struct platform_device *pdev)
        rval = v4l2_device_register(&pdev->dev, &rsdev->v4l2_dev);
        if (rval) {
                dev_err(&pdev->dev, "Failed to register v4l2 device.\n");
-               goto free_rsdev;
+               goto exit;
        }
 
        adapter = i2c_get_adapter(pdata->i2c_bus);
@@ -322,8 +322,6 @@ put_adapter:
        i2c_put_adapter(adapter);
 unregister_v4l2_dev:
        v4l2_device_unregister(&rsdev->v4l2_dev);
-free_rsdev:
-       kfree(rsdev);
 exit:
        return rval;
 }
@@ -342,7 +340,6 @@ static int __exit radio_si4713_pdriver_remove(struct platform_device *pdev)
        video_unregister_device(rsdev->radio_dev);
        i2c_put_adapter(client->adapter);
        v4l2_device_unregister(&rsdev->v4l2_dev);
-       kfree(rsdev);
 
        return 0;
 }
index 6b1fae32b483525d8933a7d00408f80cb3c63264..d0c905310071e9cb0eba764bef1cc5787720fbd8 100644 (file)
@@ -151,8 +151,11 @@ int tea5764_i2c_read(struct tea5764_device *radio)
        u16 *p = (u16 *) &radio->regs;
 
        struct i2c_msg msgs[1] = {
-               { radio->i2c_client->addr, I2C_M_RD, sizeof(radio->regs),
-                       (void *)&radio->regs },
+               {       .addr = radio->i2c_client->addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(radio->regs),
+                       .buf = (void *)&radio->regs
+               },
        };
        if (i2c_transfer(radio->i2c_client->adapter, msgs, 1) != 1)
                return -EIO;
@@ -167,7 +170,11 @@ int tea5764_i2c_write(struct tea5764_device *radio)
        struct tea5764_write_regs wr;
        struct tea5764_regs *r = &radio->regs;
        struct i2c_msg msgs[1] = {
-               { radio->i2c_client->addr, 0, sizeof(wr), (void *) &wr },
+               {
+                       .addr = radio->i2c_client->addr,
+                       .len = sizeof(wr),
+                       .buf = (void *)&wr
+               },
        };
        wr.intreg  = r->intreg & 0xff;
        wr.frqset  = __cpu_to_be16(r->frqset);
@@ -448,7 +455,7 @@ static int vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int vidioc_s_audio(struct file *file, void *priv,
-                          struct v4l2_audio *a)
+                          const struct v4l2_audio *a)
 {
        if (a->index != 0)
                return -EINVAL;
index 5bc9fa62720b6e23355a2ae54447a95de04d9222..4b5190d4fea5d701b06853bedb5b89408742fb3c 100644 (file)
 #include <media/v4l2-fh.h>
 #include <media/v4l2-ioctl.h>
 #include <media/v4l2-event.h>
-#include <asm/div64.h>
 #include "radio-tea5777.h"
 
 MODULE_AUTHOR("Hans de Goede <perex@perex.cz>");
 MODULE_DESCRIPTION("Routines for control of TEA5777 Philips AM/FM radio tuner chips");
 MODULE_LICENSE("GPL");
 
-/* Fixed FM only band for now, will implement multi-band support when the
-   VIDIOC_ENUM_FREQ_BANDS API is upstream */
-#define TEA5777_FM_RANGELOW            (76000 * 16)
-#define TEA5777_FM_RANGEHIGH           (108000 * 16)
-
 #define TEA5777_FM_IF                  150 /* kHz */
-#define TEA5777_FM_FREQ_STEP           50 /* kHz */
+#define TEA5777_FM_FREQ_STEP           50  /* kHz */
+
+#define TEA5777_AM_IF                  21  /* kHz */
+#define TEA5777_AM_FREQ_STEP           1   /* kHz */
 
 /* Write reg, common bits */
 #define TEA5777_W_MUTE_MASK            (1LL << 47)
@@ -95,7 +92,7 @@ MODULE_LICENSE("GPL");
 #define TEA5777_W_FM_PLL_SHIFT         32
 #define TEA5777_W_FM_FREF_MASK         (0x03LL << 30)
 #define TEA5777_W_FM_FREF_SHIFT                30
-#define TEA5777_W_FM_FREF_VALUE                0 /* 50 kHz tune steps, 150 kHz IF */
+#define TEA5777_W_FM_FREF_VALUE                0LL /* 50k steps, 150k IF */
 
 #define TEA5777_W_FM_FORCEMONO_MASK    (1LL << 15)
 #define TEA5777_W_FM_FORCEMONO_SHIFT   15
@@ -116,6 +113,8 @@ MODULE_LICENSE("GPL");
 #define TEA5777_W_AM_AGCIF_SHIFT       32
 #define TEA5777_W_AM_MWLW_MASK         (1LL << 31)
 #define TEA5777_W_AM_MWLW_SHIFT                31
+#define TEA5777_W_AM_LW                        0LL
+#define TEA5777_W_AM_MW                        1LL
 #define TEA5777_W_AM_LNA_MASK          (1LL << 30)
 #define TEA5777_W_AM_LNA_SHIFT         30
 
@@ -148,26 +147,82 @@ MODULE_LICENSE("GPL");
 #define TEA5777_R_FM_PLL_MASK          0x1fff
 #define TEA5777_R_FM_PLL_SHIFT         0
 
+enum { BAND_FM, BAND_AM };
+
+static const struct v4l2_frequency_band bands[] = {
+       {
+               .type = V4L2_TUNER_RADIO,
+               .index = 0,
+               .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+                             V4L2_TUNER_CAP_FREQ_BANDS |
+                             V4L2_TUNER_CAP_HWSEEK_BOUNDED |
+                             V4L2_TUNER_CAP_HWSEEK_PROG_LIM,
+               .rangelow   =  76000 * 16,
+               .rangehigh  = 108000 * 16,
+               .modulation = V4L2_BAND_MODULATION_FM,
+       },
+       {
+               .type = V4L2_TUNER_RADIO,
+               .index = 1,
+               .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS |
+                             V4L2_TUNER_CAP_HWSEEK_BOUNDED |
+                             V4L2_TUNER_CAP_HWSEEK_PROG_LIM,
+               .rangelow   =  530 * 16,
+               .rangehigh  = 1710 * 16,
+               .modulation = V4L2_BAND_MODULATION_AM,
+       },
+};
+
 static u32 tea5777_freq_to_v4l2_freq(struct radio_tea5777 *tea, u32 freq)
 {
-       return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16;
+       switch (tea->band) {
+       case BAND_FM:
+               return (freq * TEA5777_FM_FREQ_STEP + TEA5777_FM_IF) * 16;
+       case BAND_AM:
+               return (freq * TEA5777_AM_FREQ_STEP + TEA5777_AM_IF) * 16;
+       }
+       return 0; /* Never reached */
 }
 
-static int radio_tea5777_set_freq(struct radio_tea5777 *tea)
+int radio_tea5777_set_freq(struct radio_tea5777 *tea)
 {
-       u64 freq;
+       u32 freq;
        int res;
 
-       freq = clamp_t(u32, tea->freq,
-                      TEA5777_FM_RANGELOW, TEA5777_FM_RANGEHIGH) + 8;
-       do_div(freq, 16); /* to kHz */
-
-       freq -= TEA5777_FM_IF;
-       do_div(freq, TEA5777_FM_FREQ_STEP);
-
-       tea->write_reg &= ~(TEA5777_W_FM_PLL_MASK | TEA5777_W_FM_FREF_MASK);
-       tea->write_reg |= freq << TEA5777_W_FM_PLL_SHIFT;
-       tea->write_reg |= TEA5777_W_FM_FREF_VALUE << TEA5777_W_FM_FREF_SHIFT;
+       freq = clamp(tea->freq, bands[tea->band].rangelow,
+                               bands[tea->band].rangehigh);
+       freq = (freq + 8) / 16; /* to kHz */
+
+       switch (tea->band) {
+       case BAND_FM:
+               tea->write_reg &= ~TEA5777_W_AM_FM_MASK;
+               freq = (freq - TEA5777_FM_IF) / TEA5777_FM_FREQ_STEP;
+               tea->write_reg &= ~TEA5777_W_FM_PLL_MASK;
+               tea->write_reg |= (u64)freq << TEA5777_W_FM_PLL_SHIFT;
+               tea->write_reg &= ~TEA5777_W_FM_FREF_MASK;
+               tea->write_reg |= TEA5777_W_FM_FREF_VALUE <<
+                                 TEA5777_W_FM_FREF_SHIFT;
+               tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK;
+               if (tea->audmode == V4L2_TUNER_MODE_MONO)
+                       tea->write_reg |= 1LL << TEA5777_W_FM_FORCEMONO_SHIFT;
+               break;
+       case BAND_AM:
+               tea->write_reg &= ~TEA5777_W_AM_FM_MASK;
+               tea->write_reg |= (1LL << TEA5777_W_AM_FM_SHIFT);
+               freq = (freq - TEA5777_AM_IF) / TEA5777_AM_FREQ_STEP;
+               tea->write_reg &= ~TEA5777_W_AM_PLL_MASK;
+               tea->write_reg |= (u64)freq << TEA5777_W_AM_PLL_SHIFT;
+               tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK;
+               tea->write_reg &= ~TEA5777_W_AM_AGCRF_MASK;
+               tea->write_reg &= ~TEA5777_W_AM_MWLW_MASK;
+               tea->write_reg |= TEA5777_W_AM_MW << TEA5777_W_AM_MWLW_SHIFT;
+               tea->write_reg &= ~TEA5777_W_AM_LNA_MASK;
+               tea->write_reg |= 1LL << TEA5777_W_AM_LNA_SHIFT;
+               tea->write_reg &= ~TEA5777_W_AM_PEAK_MASK;
+               tea->write_reg |= 1LL << TEA5777_W_AM_PEAK_SHIFT;
+               tea->write_reg &= ~TEA5777_W_AM_CALLIGN_MASK;
+               break;
+       }
 
        res = tea->ops->write_reg(tea, tea->write_reg);
        if (res)
@@ -225,6 +280,19 @@ static int vidioc_querycap(struct file *file, void  *priv,
        return 0;
 }
 
+static int vidioc_enum_freq_bands(struct file *file, void *priv,
+                                        struct v4l2_frequency_band *band)
+{
+       struct radio_tea5777 *tea = video_drvdata(file);
+
+       if (band->tuner != 0 || band->index >= ARRAY_SIZE(bands) ||
+           (!tea->has_am && band->index == BAND_AM))
+               return -EINVAL;
+
+       *band = bands[band->index];
+       return 0;
+}
+
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
@@ -245,13 +313,18 @@ static int vidioc_g_tuner(struct file *file, void *priv,
                strlcpy(v->name, "FM", sizeof(v->name));
        v->type = V4L2_TUNER_RADIO;
        v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
-                       V4L2_TUNER_CAP_HWSEEK_BOUNDED;
-       v->rangelow   = TEA5777_FM_RANGELOW;
-       v->rangehigh  = TEA5777_FM_RANGEHIGH;
-       v->rxsubchans = (tea->read_reg & TEA5777_R_FM_STEREO_MASK) ?
-                       V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
-       v->audmode = (tea->write_reg & TEA5777_W_FM_FORCEMONO_MASK) ?
-               V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO;
+                       V4L2_TUNER_CAP_FREQ_BANDS |
+                       V4L2_TUNER_CAP_HWSEEK_BOUNDED |
+                       V4L2_TUNER_CAP_HWSEEK_PROG_LIM;
+       v->rangelow   = tea->has_am ? bands[BAND_AM].rangelow :
+                                     bands[BAND_FM].rangelow;
+       v->rangehigh  = bands[BAND_FM].rangehigh;
+       if (tea->band == BAND_FM &&
+                       (tea->read_reg & TEA5777_R_FM_STEREO_MASK))
+               v->rxsubchans = V4L2_TUNER_SUB_STEREO;
+       else
+               v->rxsubchans = V4L2_TUNER_SUB_MONO;
+       v->audmode = tea->audmode;
        /* shift - 12 to convert 4-bits (0-15) scale to 16-bits (0-65535) */
        v->signal = (tea->read_reg & TEA5777_R_LEVEL_MASK) >>
                    (TEA5777_R_LEVEL_SHIFT - 12);
@@ -266,16 +339,20 @@ static int vidioc_s_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
        struct radio_tea5777 *tea = video_drvdata(file);
+       u32 orig_audmode = tea->audmode;
 
        if (v->index)
                return -EINVAL;
 
-       if (v->audmode == V4L2_TUNER_MODE_MONO)
-               tea->write_reg |= TEA5777_W_FM_FORCEMONO_MASK;
-       else
-               tea->write_reg &= ~TEA5777_W_FM_FORCEMONO_MASK;
+       if (v->audmode > V4L2_TUNER_MODE_STEREO)
+               v->audmode = V4L2_TUNER_MODE_STEREO;
 
-       return radio_tea5777_set_freq(tea);
+       tea->audmode = v->audmode;
+
+       if (tea->audmode != orig_audmode && tea->band == BAND_FM)
+               return radio_tea5777_set_freq(tea);
+
+       return 0;
 }
 
 static int vidioc_g_frequency(struct file *file, void *priv,
@@ -298,40 +375,74 @@ static int vidioc_s_frequency(struct file *file, void *priv,
        if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
                return -EINVAL;
 
+       if (tea->has_am && f->frequency < (20000 * 16))
+               tea->band = BAND_AM;
+       else
+               tea->band = BAND_FM;
+
        tea->freq = f->frequency;
        return radio_tea5777_set_freq(tea);
 }
 
 static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
-                                       struct v4l2_hw_freq_seek *a)
+                                       const struct v4l2_hw_freq_seek *a)
 {
        struct radio_tea5777 *tea = video_drvdata(file);
-       u32 orig_freq = tea->freq;
        unsigned long timeout;
-       int res, spacing = 200 * 16; /* 200 kHz */
-       /* These are fixed *for now* */
-       const u32 seek_rangelow  = TEA5777_FM_RANGELOW;
-       const u32 seek_rangehigh = TEA5777_FM_RANGEHIGH;
+       u32 rangelow = a->rangelow;
+       u32 rangehigh = a->rangehigh;
+       int i, res, spacing;
+       u32 orig_freq;
 
        if (a->tuner || a->wrap_around)
                return -EINVAL;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
+       if (rangelow || rangehigh) {
+               for (i = 0; i < ARRAY_SIZE(bands); i++) {
+                       if (i == BAND_AM && !tea->has_am)
+                               continue;
+                       if (bands[i].rangelow  >= rangelow &&
+                           bands[i].rangehigh <= rangehigh)
+                               break;
+               }
+               if (i == ARRAY_SIZE(bands))
+                       return -EINVAL; /* No matching band found */
+
+               tea->band = i;
+               if (tea->freq < rangelow || tea->freq > rangehigh) {
+                       tea->freq = clamp(tea->freq, rangelow,
+                                                    rangehigh);
+                       res = radio_tea5777_set_freq(tea);
+                       if (res)
+                               return res;
+               }
+       } else {
+               rangelow  = bands[tea->band].rangelow;
+               rangehigh = bands[tea->band].rangehigh;
+       }
+
+       spacing   = (tea->band == BAND_AM) ? (5 * 16) : (200 * 16); /* kHz */
+       orig_freq = tea->freq;
+
        tea->write_reg |= TEA5777_W_PROGBLIM_MASK;
-       if (seek_rangelow != tea->seek_rangelow) {
+       if (tea->seek_rangelow != rangelow) {
                tea->write_reg &= ~TEA5777_W_UPDWN_MASK;
-               tea->freq = seek_rangelow;
+               tea->freq = rangelow;
                res = radio_tea5777_set_freq(tea);
                if (res)
                        goto leave;
-               tea->seek_rangelow = tea->freq;
+               tea->seek_rangelow = rangelow;
        }
-       if (seek_rangehigh != tea->seek_rangehigh) {
+       if (tea->seek_rangehigh != rangehigh) {
                tea->write_reg |= TEA5777_W_UPDWN_MASK;
-               tea->freq = seek_rangehigh;
+               tea->freq = rangehigh;
                res = radio_tea5777_set_freq(tea);
                if (res)
                        goto leave;
-               tea->seek_rangehigh = tea->freq;
+               tea->seek_rangehigh = rangehigh;
        }
        tea->write_reg &= ~TEA5777_W_PROGBLIM_MASK;
 
@@ -419,6 +530,7 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
        .vidioc_g_frequency = vidioc_g_frequency,
        .vidioc_s_frequency = vidioc_s_frequency,
        .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
+       .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
        .vidioc_log_status  = v4l2_ctrl_log_status,
        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
@@ -441,8 +553,9 @@ int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner)
                         (1LL << TEA5777_W_IFW_SHIFT) |
                         (1LL << TEA5777_W_INTEXT_SHIFT) |
                         (1LL << TEA5777_W_CHP0_SHIFT) |
-                        (2LL << TEA5777_W_SLEV_SHIFT);
+                        (1LL << TEA5777_W_SLEV_SHIFT);
        tea->freq = 90500 * 16; /* 90.5Mhz default */
+       tea->audmode = V4L2_TUNER_MODE_STEREO;
        res = radio_tea5777_set_freq(tea);
        if (res) {
                v4l2_err(tea->v4l2_dev, "can't set initial freq (%d)\n", res);
index 55cbd78df5eda8d144687c3d356a0218c9262d30..4ea43a90a151ed10604c57b01de530f5848cbbce 100644 (file)
@@ -68,7 +68,9 @@ struct radio_tea5777 {
        bool has_am;                    /* Device can tune to AM freqs */
        bool write_before_read;         /* must write before read quirk */
        bool needs_write;               /* for write before read quirk */
+       u32 band;                       /* current band */
        u32 freq;                       /* current frequency */
+       u32 audmode;                    /* last set audmode */
        u32 seek_rangelow;              /* current hwseek limits */
        u32 seek_rangehigh;
        u32 read_reg;
@@ -83,5 +85,6 @@ struct radio_tea5777 {
 
 int radio_tea5777_init(struct radio_tea5777 *tea, struct module *owner);
 void radio_tea5777_exit(struct radio_tea5777 *tea);
+int radio_tea5777_set_freq(struct radio_tea5777 *tea);
 
 #endif /* __RADIO_TEA5777_H */
index 7052adc0c0b0547a09f68534059912d769938482..5cf07779f4bb2b1ccddad9756f772184e036bed3 100644 (file)
@@ -85,7 +85,7 @@ static int timbradio_vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int timbradio_vidioc_s_audio(struct file *file, void *priv,
-       struct v4l2_audio *a)
+       const struct v4l2_audio *a)
 {
        return a->index ? -EINVAL : 0;
 }
@@ -157,7 +157,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
                goto err;
        }
 
-       tr = kzalloc(sizeof(*tr), GFP_KERNEL);
+       tr = devm_kzalloc(&pdev->dev, sizeof(*tr), GFP_KERNEL);
        if (!tr) {
                err = -ENOMEM;
                goto err;
@@ -177,7 +177,7 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
        strlcpy(tr->v4l2_dev.name, DRIVER_NAME, sizeof(tr->v4l2_dev.name));
        err = v4l2_device_register(NULL, &tr->v4l2_dev);
        if (err)
-               goto err_v4l2_dev;
+               goto err;
 
        tr->video_dev.v4l2_dev = &tr->v4l2_dev;
 
@@ -195,8 +195,6 @@ static int __devinit timbradio_probe(struct platform_device *pdev)
 err_video_req:
        video_device_release_empty(&tr->video_dev);
        v4l2_device_unregister(&tr->v4l2_dev);
-err_v4l2_dev:
-       kfree(tr);
 err:
        dev_err(&pdev->dev, "Failed to register: %d\n", err);
 
@@ -212,8 +210,6 @@ static int __devexit timbradio_remove(struct platform_device *pdev)
 
        v4l2_device_unregister(&tr->v4l2_dev);
 
-       kfree(tr);
-
        return 0;
 }
 
index e8428f573ccdf0a5649a9b04e187187117f33448..9b0c9fa0beb80307ac0a4b95785a2aaaa50fb0f3 100644 (file)
@@ -1479,7 +1479,7 @@ static int wl1273_fm_vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int wl1273_fm_vidioc_s_audio(struct file *file, void *priv,
-                                   struct v4l2_audio *audio)
+                                   const struct v4l2_audio *audio)
 {
        struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
 
@@ -1682,7 +1682,7 @@ static int wl1273_fm_vidioc_s_frequency(struct file *file, void *priv,
 #define WL1273_DEFAULT_SEEK_LEVEL      7
 
 static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv,
-                                          struct v4l2_hw_freq_seek *seek)
+                                          const struct v4l2_hw_freq_seek *seek)
 {
        struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
        struct wl1273_core *core = radio->core;
@@ -1693,6 +1693,9 @@ static int wl1273_fm_vidioc_s_hw_freq_seek(struct file *file, void *priv,
        if (seek->tuner != 0 || seek->type != V4L2_TUNER_RADIO)
                return -EINVAL;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
        if (mutex_lock_interruptible(&core->lock))
                return -EINTR;
 
@@ -1715,7 +1718,7 @@ out:
 }
 
 static int wl1273_fm_vidioc_s_modulator(struct file *file, void *priv,
-                                       struct v4l2_modulator *modulator)
+                                       const struct v4l2_modulator *modulator)
 {
        struct wl1273_device *radio = video_get_drvdata(video_devdata(file));
        struct wl1273_core *core = radio->core;
@@ -1983,9 +1986,6 @@ static int wl1273_fm_radio_remove(struct platform_device *pdev)
        v4l2_ctrl_handler_free(&radio->ctrl_handler);
        video_unregister_device(&radio->videodev);
        v4l2_device_unregister(&radio->v4l2dev);
-       kfree(radio->buffer);
-       kfree(radio->write_buf);
-       kfree(radio);
 
        return 0;
 }
@@ -2005,7 +2005,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
                goto pdata_err;
        }
 
-       radio = kzalloc(sizeof(*radio), GFP_KERNEL);
+       radio = devm_kzalloc(&pdev->dev, sizeof(*radio), GFP_KERNEL);
        if (!radio) {
                r = -ENOMEM;
                goto pdata_err;
@@ -2013,11 +2013,11 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
 
        /* RDS buffer allocation */
        radio->buf_size = rds_buf * RDS_BLOCK_SIZE;
-       radio->buffer = kmalloc(radio->buf_size, GFP_KERNEL);
+       radio->buffer = devm_kzalloc(&pdev->dev, radio->buf_size, GFP_KERNEL);
        if (!radio->buffer) {
                pr_err("Cannot allocate memory for RDS buffer.\n");
                r = -ENOMEM;
-               goto err_kmalloc;
+               goto pdata_err;
        }
 
        radio->core = *core;
@@ -2043,7 +2043,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
                if (r) {
                        dev_err(radio->dev, WL1273_FM_DRIVER_NAME
                                ": Cannot get platform data\n");
-                       goto err_resources;
+                       goto pdata_err;
                }
 
                dev_dbg(radio->dev, "irq: %d\n", radio->core->client->irq);
@@ -2061,13 +2061,13 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
                dev_err(radio->dev, WL1273_FM_DRIVER_NAME ": Core WL1273 IRQ"
                        " not configured");
                r = -EINVAL;
-               goto err_resources;
+               goto pdata_err;
        }
 
        init_completion(&radio->busy);
        init_waitqueue_head(&radio->read_queue);
 
-       radio->write_buf = kmalloc(256, GFP_KERNEL);
+       radio->write_buf = devm_kzalloc(&pdev->dev, 256, GFP_KERNEL);
        if (!radio->write_buf) {
                r = -ENOMEM;
                goto write_buf_err;
@@ -2080,7 +2080,7 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
        r = v4l2_device_register(&pdev->dev, &radio->v4l2dev);
        if (r) {
                dev_err(&pdev->dev, "Cannot register v4l2_device.\n");
-               goto device_register_err;
+               goto write_buf_err;
        }
 
        /* V4L2 configuration */
@@ -2135,16 +2135,10 @@ static int __devinit wl1273_fm_radio_probe(struct platform_device *pdev)
 handler_init_err:
        v4l2_ctrl_handler_free(&radio->ctrl_handler);
        v4l2_device_unregister(&radio->v4l2dev);
-device_register_err:
-       kfree(radio->write_buf);
 write_buf_err:
        free_irq(radio->core->client->irq, radio);
 err_request_irq:
        radio->core->pdata->free_resources();
-err_resources:
-       kfree(radio->buffer);
-err_kmalloc:
-       kfree(radio);
 pdata_err:
        return r;
 }
index bb953ef75f615dd831ecca6204f9aad36bc18a12..54db36ccb9ee2bb23d3e9615fe7c5b8a7e0967ef 100644 (file)
@@ -199,8 +199,19 @@ static int saa7706h_get_reg16(struct v4l2_subdev *sd, u16 reg)
        u8 buf[2];
        int err;
        u8 regaddr[] = {reg >> 8, reg};
-       struct i2c_msg msg[] = { {client->addr, 0, sizeof(regaddr), regaddr},
-                               {client->addr, I2C_M_RD, sizeof(buf), buf} };
+       struct i2c_msg msg[] = {
+                                       {
+                                               .addr = client->addr,
+                                               .len = sizeof(regaddr),
+                                               .buf = regaddr
+                                       },
+                                       {
+                                               .addr = client->addr,
+                                               .flags = I2C_M_RD,
+                                               .len = sizeof(buf),
+                                               .buf = buf
+                                       }
+                               };
 
        err = saa7706h_i2c_transfer(client, msg, ARRAY_SIZE(msg));
        if (err)
index 9bb65e170d99bd87455107083379931c6bda40a6..18989388ddc14d32f3134f650615c33e43bb55bb 100644 (file)
@@ -296,7 +296,7 @@ int si470x_set_freq(struct si470x_device *radio, unsigned int freq)
  * si470x_set_seek - set seek
  */
 static int si470x_set_seek(struct si470x_device *radio,
-                          struct v4l2_hw_freq_seek *seek)
+                          const struct v4l2_hw_freq_seek *seek)
 {
        int band, retval;
        unsigned int freq;
@@ -701,13 +701,16 @@ static int si470x_vidioc_s_frequency(struct file *file, void *priv,
  * si470x_vidioc_s_hw_freq_seek - set hardware frequency seek
  */
 static int si470x_vidioc_s_hw_freq_seek(struct file *file, void *priv,
-               struct v4l2_hw_freq_seek *seek)
+               const struct v4l2_hw_freq_seek *seek)
 {
        struct si470x_device *radio = video_drvdata(file);
 
        if (seek->tuner != 0)
                return -EINVAL;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
        return si470x_set_seek(radio, seek);
 }
 
index f867f04cccc99626bb7fc5dee97d34f2adaed9fa..e5024cfd27a713ffa77403471275b62e6ba264e3 100644 (file)
@@ -98,8 +98,12 @@ int si470x_get_register(struct si470x_device *radio, int regnr)
 {
        u16 buf[READ_REG_NUM];
        struct i2c_msg msgs[1] = {
-               { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
-                       (void *)buf },
+               {
+                       .addr = radio->client->addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(u16) * READ_REG_NUM,
+                       .buf = (void *)buf
+               },
        };
 
        if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
@@ -119,8 +123,11 @@ int si470x_set_register(struct si470x_device *radio, int regnr)
        int i;
        u16 buf[WRITE_REG_NUM];
        struct i2c_msg msgs[1] = {
-               { radio->client->addr, 0, sizeof(u16) * WRITE_REG_NUM,
-                       (void *)buf },
+               {
+                       .addr = radio->client->addr,
+                       .len = sizeof(u16) * WRITE_REG_NUM,
+                       .buf = (void *)buf
+               },
        };
 
        for (i = 0; i < WRITE_REG_NUM; i++)
@@ -146,8 +153,12 @@ static int si470x_get_all_registers(struct si470x_device *radio)
        int i;
        u16 buf[READ_REG_NUM];
        struct i2c_msg msgs[1] = {
-               { radio->client->addr, I2C_M_RD, sizeof(u16) * READ_REG_NUM,
-                       (void *)buf },
+               {
+                       .addr = radio->client->addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(u16) * READ_REG_NUM,
+                       .buf = (void *)buf
+               },
        };
 
        if (i2c_transfer(radio->client->adapter, msgs, 1) != 1)
index b898c8925ab778603ddb4f7f5177379d20fc109b..a9e6d17015ef545cc11aa3fc4562acd403a41683 100644 (file)
@@ -1213,7 +1213,7 @@ exit:
 }
 
 static int si4713_s_frequency(struct v4l2_subdev *sd, struct v4l2_frequency *f);
-static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *);
+static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *);
 /*
  * si4713_setup - Sets the device up with current configuration.
  * @sdev: si4713_device structure for the device we are communicating
@@ -1873,7 +1873,7 @@ exit:
 }
 
 /* si4713_s_modulator - set modulator attributes */
-static int si4713_s_modulator(struct v4l2_subdev *sd, struct v4l2_modulator *vm)
+static int si4713_s_modulator(struct v4l2_subdev *sd, const struct v4l2_modulator *vm)
 {
        struct si4713_device *sdev = to_si4713_device(sd);
        int rval = 0;
index 49a11ec1f44967fe99bce27b3a602ed320e41170..048de45360360251095639d1422f9931853d3fba 100644 (file)
@@ -56,23 +56,29 @@ static ssize_t fm_v4l2_fops_read(struct file *file, char __user * buf,
                return -EIO;
        }
 
-       /* Turn on RDS mode , if it is disabled */
+       if (mutex_lock_interruptible(&fmdev->mutex))
+               return -ERESTARTSYS;
+
+       /* Turn on RDS mode if it is disabled */
        ret = fm_rx_get_rds_mode(fmdev, &rds_mode);
        if (ret < 0) {
                fmerr("Unable to read current rds mode\n");
-               return ret;
+               goto read_unlock;
        }
 
        if (rds_mode == FM_RDS_DISABLE) {
                ret = fmc_set_rds_mode(fmdev, FM_RDS_ENABLE);
                if (ret < 0) {
                        fmerr("Failed to enable rds mode\n");
-                       return ret;
+                       goto read_unlock;
                }
        }
 
        /* Copy RDS data from internal buffer to user buffer */
-       return fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
+       ret = fmc_transfer_rds_from_internal_buff(fmdev, file, buf, count);
+read_unlock:
+       mutex_unlock(&fmdev->mutex);
+       return ret;
 }
 
 /* Write TX RDS data */
@@ -91,8 +97,11 @@ static ssize_t fm_v4l2_fops_write(struct file *file, const char __user * buf,
                return -EFAULT;
 
        fmdev = video_drvdata(file);
+       if (mutex_lock_interruptible(&fmdev->mutex))
+               return -ERESTARTSYS;
        fm_tx_set_radio_text(fmdev, rds.text, rds.text_type);
        fm_tx_set_af(fmdev, rds.af_freq);
+       mutex_unlock(&fmdev->mutex);
 
        return sizeof(rds);
 }
@@ -103,7 +112,9 @@ static u32 fm_v4l2_fops_poll(struct file *file, struct poll_table_struct *pts)
        struct fmdev *fmdev;
 
        fmdev = video_drvdata(file);
+       mutex_lock(&fmdev->mutex);
        ret = fmc_is_rds_data_available(fmdev, file, pts);
+       mutex_unlock(&fmdev->mutex);
        if (ret < 0)
                return POLLIN | POLLRDNORM;
 
@@ -127,10 +138,12 @@ static int fm_v4l2_fops_open(struct file *file)
 
        fmdev = video_drvdata(file);
 
+       if (mutex_lock_interruptible(&fmdev->mutex))
+               return -ERESTARTSYS;
        ret = fmc_prepare(fmdev);
        if (ret < 0) {
                fmerr("Unable to prepare FM CORE\n");
-               return ret;
+               goto open_unlock;
        }
 
        fmdbg("Load FM RX firmware..\n");
@@ -138,10 +151,12 @@ static int fm_v4l2_fops_open(struct file *file)
        ret = fmc_set_mode(fmdev, FM_MODE_RX);
        if (ret < 0) {
                fmerr("Unable to load FM RX firmware\n");
-               return ret;
+               goto open_unlock;
        }
        radio_disconnected = 1;
 
+open_unlock:
+       mutex_unlock(&fmdev->mutex);
        return ret;
 }
 
@@ -156,19 +171,22 @@ static int fm_v4l2_fops_release(struct file *file)
                return 0;
        }
 
+       mutex_lock(&fmdev->mutex);
        ret = fmc_set_mode(fmdev, FM_MODE_OFF);
        if (ret < 0) {
                fmerr("Unable to turn off the chip\n");
-               return ret;
+               goto release_unlock;
        }
 
        ret = fmc_release(fmdev);
        if (ret < 0) {
                fmerr("FM CORE release failed\n");
-               return ret;
+               goto release_unlock;
        }
        radio_disconnected = 0;
 
+release_unlock:
+       mutex_unlock(&fmdev->mutex);
        return ret;
 }
 
@@ -240,7 +258,7 @@ static int fm_v4l2_vidioc_g_audio(struct file *file, void *priv,
 }
 
 static int fm_v4l2_vidioc_s_audio(struct file *file, void *priv,
-               struct v4l2_audio *audio)
+               const struct v4l2_audio *audio)
 {
        if (audio->index != 0)
                return -EINVAL;
@@ -385,11 +403,14 @@ static int fm_v4l2_vidioc_s_freq(struct file *file, void *priv,
 
 /* Set hardware frequency seek. If current mode is NOT RX, set it RX. */
 static int fm_v4l2_vidioc_s_hw_freq_seek(struct file *file, void *priv,
-               struct v4l2_hw_freq_seek *seek)
+               const struct v4l2_hw_freq_seek *seek)
 {
        struct fmdev *fmdev = video_drvdata(file);
        int ret;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
        if (fmdev->curr_fmmode != FM_MODE_RX) {
                ret = fmc_set_mode(fmdev, FM_MODE_RX);
                if (ret != 0) {
@@ -430,7 +451,7 @@ static int fm_v4l2_vidioc_g_modulator(struct file *file, void *priv,
 
 /* Set modulator attributes. If mode is not TX, set to TX. */
 static int fm_v4l2_vidioc_s_modulator(struct file *file, void *priv,
-               struct v4l2_modulator *mod)
+               const struct v4l2_modulator *mod)
 {
        struct fmdev *fmdev = video_drvdata(file);
        u8 rds_mode;
@@ -520,10 +541,6 @@ int fm_v4l2_init_video_device(struct fmdev *fmdev, int radio_nr)
        video_set_drvdata(gradio_dev, fmdev);
 
        gradio_dev->lock = &fmdev->mutex;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &gradio_dev->flags);
 
        /* Register with V4L2 subsystem as RADIO device */
        if (video_register_device(gradio_dev, VFL_TYPE_RADIO, radio_nr)) {
index 8be57634ba60f23e09fc5840a6bb6837920549e2..79ba242fe263a71e4c1590acad673f7c5f00d74f 100644 (file)
@@ -265,12 +265,40 @@ config IR_IGUANA
        depends on RC_CORE
        select USB
        ---help---
-          Say Y here if you want to use the IgaunaWorks USB IR Transceiver.
-          Both infrared receive and send are supported.
+          Say Y here if you want to use the IguanaWorks USB IR Transceiver.
+          Both infrared receive and send are supported. If you want to
+          change the ID or the pin config, use the user space driver from
+          IguanaWorks.
+
+          Only firmware 0x0205 and later is supported.
 
           To compile this driver as a module, choose M here: the module will
           be called iguanair.
 
+config IR_TTUSBIR
+       tristate "TechnoTrend USB IR Receiver"
+       depends on USB_ARCH_HAS_HCD
+       depends on RC_CORE
+       select USB
+       select NEW_LEDS
+       select LEDS_CLASS
+       ---help---
+          Say Y here if you want to use the TechnoTrend USB IR Receiver. The
+          driver can control the led.
+
+          To compile this driver as a module, choose M here: the module will
+          be called ttusbir.
+
+config IR_RX51
+       tristate "Nokia N900 IR transmitter diode"
+       depends on OMAP_DM_TIMER && LIRC
+       ---help---
+          Say Y or M here if you want to enable support for the IR
+          transmitter diode built in the Nokia N900 (RX51) device.
+
+          The driver uses omap DM timers for generating the carrier
+          wave and pulses.
+
 config RC_LOOPBACK
        tristate "Remote Control Loopback Driver"
        depends on RC_CORE
index f871d1986c21901011477f61f60374d032c28c14..56bacf07b3618f37db4cbe5ea39735ec9d6065b6 100644 (file)
@@ -23,8 +23,10 @@ obj-$(CONFIG_IR_FINTEK) += fintek-cir.o
 obj-$(CONFIG_IR_NUVOTON) += nuvoton-cir.o
 obj-$(CONFIG_IR_ENE) += ene_ir.o
 obj-$(CONFIG_IR_REDRAT3) += redrat3.o
+obj-$(CONFIG_IR_RX51) += ir-rx51.o
 obj-$(CONFIG_IR_STREAMZAP) += streamzap.o
 obj-$(CONFIG_IR_WINBOND_CIR) += winbond-cir.o
 obj-$(CONFIG_RC_LOOPBACK) += rc-loopback.o
 obj-$(CONFIG_IR_GPIO_CIR) += gpio-ir-recv.o
 obj-$(CONFIG_IR_IGUANA) += iguanair.o
+obj-$(CONFIG_IR_TTUSBIR) += ttusbir.o
index 8fa72e2dacb1cf709abded7d041fd35d0e2f456e..49bb356ed14cabb56a2af7c5b9df9dfcb3cd1674 100644 (file)
@@ -331,13 +331,9 @@ static void ati_remote_dump(struct device *dev, unsigned char *data,
                if (data[0] != (unsigned char)0xff && data[0] != 0x00)
                        dev_warn(dev, "Weird byte 0x%02x\n", data[0]);
        } else if (len == 4)
-               dev_warn(dev, "Weird key %02x %02x %02x %02x\n",
-                    data[0], data[1], data[2], data[3]);
+               dev_warn(dev, "Weird key %*ph\n", 4, data);
        else
-               dev_warn(dev,
-                       "Weird data, len=%d %02x %02x %02x %02x %02x %02x ...\n",
-                       len, data[0], data[1], data[2], data[3], data[4],
-                       data[5]);
+               dev_warn(dev, "Weird data, len=%d %*ph ...\n", len, 6, data);
 }
 
 /*
@@ -519,8 +515,7 @@ static void ati_remote_input_report(struct urb *urb)
 
        if (data[1] != ((data[2] + data[3] + 0xd5) & 0xff)) {
                dbginfo(&ati_remote->interface->dev,
-                       "wrong checksum in input: %02x %02x %02x %02x\n",
-                       data[0], data[1], data[2], data[3]);
+                       "wrong checksum in input: %*ph\n", 4, data);
                return;
        }
 
@@ -942,8 +937,10 @@ static int ati_remote_probe(struct usb_interface *interface,
        /* Set up and register mouse input device */
        if (mouse) {
                input_dev = input_allocate_device();
-               if (!input_dev)
+               if (!input_dev) {
+                       err = -ENOMEM;
                        goto fail4;
+               }
 
                ati_remote->idev = input_dev;
                ati_remote_input_init(ati_remote);
index ab30c64f812491d186e3a088bea23cc6849651a2..52fd7696b1ba8c7e5bccc9321fd8bd7f4a8fd105 100644 (file)
@@ -295,6 +295,7 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
 {
        DEFINE_IR_RAW_EVENT(rawir);
        u8 sample;
+       bool event = false;
        int i;
 
        for (i = 0; i < fintek->pkts; i++) {
@@ -332,7 +333,9 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
                        fit_dbg("Storing %s with duration %d",
                                rawir.pulse ? "pulse" : "space",
                                rawir.duration);
-                       ir_raw_event_store_with_filter(fintek->rdev, &rawir);
+                       if (ir_raw_event_store_with_filter(fintek->rdev,
+                                                                       &rawir))
+                               event = true;
                        break;
                }
 
@@ -342,8 +345,10 @@ static void fintek_process_rx_ir_data(struct fintek_dev *fintek)
 
        fintek->pkts = 0;
 
-       fit_dbg("Calling ir_raw_event_handle");
-       ir_raw_event_handle(fintek->rdev);
+       if (event) {
+               fit_dbg("Calling ir_raw_event_handle");
+               ir_raw_event_handle(fintek->rdev);
+       }
 }
 
 /* copy data from hardware rx register into driver buffer */
index 5e2eaf8ba73ecb0c85556bc022669f8641a25a62..1e4c68a5cecfedfa24c2053dd1b67db88f83e5a3 100644 (file)
@@ -35,9 +35,9 @@ struct iguanair {
        struct device *dev;
        struct usb_device *udev;
 
-       int pipe_in, pipe_out;
+       int pipe_out;
+       uint16_t version;
        uint8_t bufsize;
-       uint8_t version[2];
 
        struct mutex lock;
 
@@ -75,6 +75,7 @@ struct iguanair {
 
 #define MAX_PACKET_SIZE                8u
 #define TIMEOUT                        1000
+#define RX_RESOLUTION          21333
 
 struct packet {
        uint16_t start;
@@ -82,11 +83,6 @@ struct packet {
        uint8_t cmd;
 };
 
-struct response_packet {
-       struct packet header;
-       uint8_t data[4];
-};
-
 struct send_packet {
        struct packet header;
        uint8_t length;
@@ -100,6 +96,25 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
 {
        if (len >= 4 && ir->buf_in[0] == 0 && ir->buf_in[1] == 0) {
                switch (ir->buf_in[3]) {
+               case CMD_GET_VERSION:
+                       if (len == 6) {
+                               ir->version = (ir->buf_in[5] << 8) |
+                                                       ir->buf_in[4];
+                               complete(&ir->completion);
+                       }
+                       break;
+               case CMD_GET_BUFSIZE:
+                       if (len >= 5) {
+                               ir->bufsize = ir->buf_in[4];
+                               complete(&ir->completion);
+                       }
+                       break;
+               case CMD_GET_FEATURES:
+                       if (len > 5) {
+                               ir->cycle_overhead = ir->buf_in[5];
+                               complete(&ir->completion);
+                       }
+                       break;
                case CMD_TX_OVERFLOW:
                        ir->tx_overflow = true;
                case CMD_RECEIVER_OFF:
@@ -109,6 +124,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
                        break;
                case CMD_RX_OVERFLOW:
                        dev_warn(ir->dev, "receive overflow\n");
+                       ir_raw_event_reset(ir->rc);
                        break;
                default:
                        dev_warn(ir->dev, "control code %02x received\n",
@@ -118,6 +134,7 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
        } else if (len >= 7) {
                DEFINE_IR_RAW_EVENT(rawir);
                unsigned i;
+               bool event = false;
 
                init_ir_raw_event(&rawir);
 
@@ -128,19 +145,22 @@ static void process_ir_data(struct iguanair *ir, unsigned len)
                        } else {
                                rawir.pulse = (ir->buf_in[i] & 0x80) == 0;
                                rawir.duration = ((ir->buf_in[i] & 0x7f) + 1) *
-                                                                        21330;
+                                                                RX_RESOLUTION;
                        }
 
-                       ir_raw_event_store_with_filter(ir->rc, &rawir);
+                       if (ir_raw_event_store_with_filter(ir->rc, &rawir))
+                               event = true;
                }
 
-               ir_raw_event_handle(ir->rc);
+               if (event)
+                       ir_raw_event_handle(ir->rc);
        }
 }
 
 static void iguanair_rx(struct urb *urb)
 {
        struct iguanair *ir;
+       int rc;
 
        if (!urb)
                return;
@@ -166,34 +186,27 @@ static void iguanair_rx(struct urb *urb)
                break;
        }
 
-       usb_submit_urb(urb, GFP_ATOMIC);
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
+       if (rc && rc != -ENODEV)
+               dev_warn(ir->dev, "failed to resubmit urb: %d\n", rc);
 }
 
-static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
-                       struct response_packet *response, unsigned *res_len)
+static int iguanair_send(struct iguanair *ir, void *data, unsigned size)
 {
-       unsigned offset, len;
        int rc, transferred;
 
-       for (offset = 0; offset < size; offset += MAX_PACKET_SIZE) {
-               len = min(size - offset, MAX_PACKET_SIZE);
-
-               if (ir->tx_overflow)
-                       return -EOVERFLOW;
+       INIT_COMPLETION(ir->completion);
 
-               rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data + offset,
-                                               len, &transferred, TIMEOUT);
-               if (rc)
-                       return rc;
+       rc = usb_interrupt_msg(ir->udev, ir->pipe_out, data, size,
+                                                       &transferred, TIMEOUT);
+       if (rc)
+               return rc;
 
-               if (transferred != len)
-                       return -EIO;
-       }
+       if (transferred != size)
+               return -EIO;
 
-       if (response) {
-               rc = usb_interrupt_msg(ir->udev, ir->pipe_in, response,
-                                       sizeof(*response), res_len, TIMEOUT);
-       }
+       if (wait_for_completion_timeout(&ir->completion, TIMEOUT) == 0)
+               return -ETIMEDOUT;
 
        return rc;
 }
@@ -201,66 +214,43 @@ static int iguanair_send(struct iguanair *ir, void *data, unsigned size,
 static int iguanair_get_features(struct iguanair *ir)
 {
        struct packet packet;
-       struct response_packet response;
-       int rc, len;
+       int rc;
 
        packet.start = 0;
        packet.direction = DIR_OUT;
        packet.cmd = CMD_GET_VERSION;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
+       rc = iguanair_send(ir, &packet, sizeof(packet));
        if (rc) {
                dev_info(ir->dev, "failed to get version\n");
                goto out;
        }
 
-       if (len != 6) {
-               dev_info(ir->dev, "failed to get version\n");
-               rc = -EIO;
+       if (ir->version < 0x205) {
+               dev_err(ir->dev, "firmware 0x%04x is too old\n", ir->version);
+               rc = -ENODEV;
                goto out;
        }
 
-       ir->version[0] = response.data[0];
-       ir->version[1] = response.data[1];
        ir->bufsize = 150;
        ir->cycle_overhead = 65;
 
        packet.cmd = CMD_GET_BUFSIZE;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
+       rc = iguanair_send(ir, &packet, sizeof(packet));
        if (rc) {
                dev_info(ir->dev, "failed to get buffer size\n");
                goto out;
        }
 
-       if (len != 5) {
-               dev_info(ir->dev, "failed to get buffer size\n");
-               rc = -EIO;
-               goto out;
-       }
-
-       ir->bufsize = response.data[0];
-
-       if (ir->version[0] == 0 || ir->version[1] == 0)
-               goto out;
-
        packet.cmd = CMD_GET_FEATURES;
 
-       rc = iguanair_send(ir, &packet, sizeof(packet), &response, &len);
+       rc = iguanair_send(ir, &packet, sizeof(packet));
        if (rc) {
                dev_info(ir->dev, "failed to get features\n");
                goto out;
        }
 
-       if (len < 5) {
-               dev_info(ir->dev, "failed to get features\n");
-               rc = -EIO;
-               goto out;
-       }
-
-       if (len > 5 && ir->version[0] >= 4)
-               ir->cycle_overhead = response.data[1];
-
 out:
        return rc;
 }
@@ -269,17 +259,11 @@ static int iguanair_receiver(struct iguanair *ir, bool enable)
 {
        struct packet packet = { 0, DIR_OUT, enable ?
                                CMD_RECEIVER_ON : CMD_RECEIVER_OFF };
-       int rc;
-
-       INIT_COMPLETION(ir->completion);
 
-       rc = iguanair_send(ir, &packet, sizeof(packet), NULL, NULL);
-       if (rc)
-               return rc;
-
-       wait_for_completion_timeout(&ir->completion, TIMEOUT);
+       if (enable)
+               ir_raw_event_reset(ir->rc);
 
-       return 0;
+       return iguanair_send(ir, &packet, sizeof(packet));
 }
 
 /*
@@ -350,26 +334,38 @@ static int iguanair_set_tx_mask(struct rc_dev *dev, uint32_t mask)
 static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 {
        struct iguanair *ir = dev->priv;
-       uint8_t space, *payload;
-       unsigned i, size, rc;
+       uint8_t space;
+       unsigned i, size, periods, bytes;
+       int rc;
        struct send_packet *packet;
 
        mutex_lock(&ir->lock);
 
-       /* convert from us to carrier periods */
-       for (i = size = 0; i < count; i++) {
-               txbuf[i] = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
-               size += (txbuf[i] + 126) / 127;
-       }
-
-       packet = kmalloc(sizeof(*packet) + size, GFP_KERNEL);
+       packet = kmalloc(sizeof(*packet) + ir->bufsize, GFP_KERNEL);
        if (!packet) {
                rc = -ENOMEM;
                goto out;
        }
 
-       if (size > ir->bufsize) {
-               rc = -E2BIG;
+       /* convert from us to carrier periods */
+       for (i = space = size = 0; i < count; i++) {
+               periods = DIV_ROUND_CLOSEST(txbuf[i] * ir->carrier, 1000000);
+               bytes = DIV_ROUND_UP(periods, 127);
+               if (size + bytes > ir->bufsize) {
+                       count = i;
+                       break;
+               }
+               while (periods > 127) {
+                       packet->payload[size++] = 127 | space;
+                       periods -= 127;
+               }
+
+               packet->payload[size++] = periods | space;
+               space ^= 0x80;
+       }
+
+       if (count == 0) {
+               rc = -EINVAL;
                goto out;
        }
 
@@ -381,21 +377,6 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        packet->busy7 = ir->busy7;
        packet->busy4 = ir->busy4;
 
-       space = 0;
-       payload = packet->payload;
-
-       for (i = 0; i < count; i++) {
-               unsigned periods = txbuf[i];
-
-               while (periods > 127) {
-                       *payload++ = 127 | space;
-                       periods -= 127;
-               }
-
-               *payload++ = periods | space;
-               space ^= 0x80;
-       }
-
        if (ir->receiver_on) {
                rc = iguanair_receiver(ir, false);
                if (rc) {
@@ -406,17 +387,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 
        ir->tx_overflow = false;
 
-       INIT_COMPLETION(ir->completion);
+       rc = iguanair_send(ir, packet, size + 8);
 
-       rc = iguanair_send(ir, packet, size + 8, NULL, NULL);
-
-       if (rc == 0) {
-               wait_for_completion_timeout(&ir->completion, TIMEOUT);
-               if (ir->tx_overflow)
-                       rc = -EOVERFLOW;
-       }
-
-       ir->tx_overflow = false;
+       if (rc == 0 && ir->tx_overflow)
+               rc = -EOVERFLOW;
 
        if (ir->receiver_on) {
                if (iguanair_receiver(ir, true))
@@ -424,10 +398,10 @@ static int iguanair_tx(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        }
 
 out:
-       mutex_unlock(&ir->lock);
        kfree(packet);
+       mutex_unlock(&ir->lock);
 
-       return rc;
+       return rc ? rc : count;
 }
 
 static int iguanair_open(struct rc_dev *rdev)
@@ -437,8 +411,6 @@ static int iguanair_open(struct rc_dev *rdev)
 
        mutex_lock(&ir->lock);
 
-       usb_submit_urb(ir->urb_in, GFP_KERNEL);
-
        BUG_ON(ir->receiver_on);
 
        rc = iguanair_receiver(ir, true);
@@ -459,11 +431,9 @@ static void iguanair_close(struct rc_dev *rdev)
 
        rc = iguanair_receiver(ir, false);
        ir->receiver_on = false;
-       if (rc)
+       if (rc && rc != -ENODEV)
                dev_warn(ir->dev, "failed to disable receiver: %d\n", rc);
 
-       usb_kill_urb(ir->urb_in);
-
        mutex_unlock(&ir->lock);
 }
 
@@ -473,22 +443,22 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        struct usb_device *udev = interface_to_usbdev(intf);
        struct iguanair *ir;
        struct rc_dev *rc;
-       int ret;
+       int ret, pipein;
        struct usb_host_interface *idesc;
 
        ir = kzalloc(sizeof(*ir), GFP_KERNEL);
        rc = rc_allocate_device();
        if (!ir || !rc) {
-               ret = ENOMEM;
+               ret = -ENOMEM;
                goto out;
        }
 
-       ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_ATOMIC,
+       ir->buf_in = usb_alloc_coherent(udev, MAX_PACKET_SIZE, GFP_KERNEL,
                                                                &ir->dma_in);
        ir->urb_in = usb_alloc_urb(0, GFP_KERNEL);
 
        if (!ir->buf_in || !ir->urb_in) {
-               ret = ENOMEM;
+               ret = -ENOMEM;
                goto out;
        }
 
@@ -502,28 +472,29 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        ir->rc = rc;
        ir->dev = &intf->dev;
        ir->udev = udev;
-       ir->pipe_in = usb_rcvintpipe(udev,
-                               idesc->endpoint[0].desc.bEndpointAddress);
        ir->pipe_out = usb_sndintpipe(udev,
                                idesc->endpoint[1].desc.bEndpointAddress);
        mutex_init(&ir->lock);
        init_completion(&ir->completion);
 
-       ret = iguanair_get_features(ir);
+       pipein = usb_rcvintpipe(udev, idesc->endpoint[0].desc.bEndpointAddress);
+       usb_fill_int_urb(ir->urb_in, udev, pipein, ir->buf_in, MAX_PACKET_SIZE,
+                                                        iguanair_rx, ir, 1);
+       ir->urb_in->transfer_dma = ir->dma_in;
+       ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+
+       ret = usb_submit_urb(ir->urb_in, GFP_KERNEL);
        if (ret) {
-               dev_warn(&intf->dev, "failed to get device features");
+               dev_warn(&intf->dev, "failed to submit urb: %d\n", ret);
                goto out;
        }
 
-       usb_fill_int_urb(ir->urb_in, ir->udev, ir->pipe_in, ir->buf_in,
-               MAX_PACKET_SIZE, iguanair_rx, ir,
-               idesc->endpoint[0].desc.bInterval);
-       ir->urb_in->transfer_dma = ir->dma_in;
-       ir->urb_in->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+       ret = iguanair_get_features(ir);
+       if (ret)
+               goto out2;
 
        snprintf(ir->name, sizeof(ir->name),
-               "IguanaWorks USB IR Transceiver version %d.%d",
-               ir->version[0], ir->version[1]);
+               "IguanaWorks USB IR Transceiver version 0x%04x", ir->version);
 
        usb_make_path(ir->udev, ir->phys, sizeof(ir->phys));
 
@@ -540,21 +511,23 @@ static int __devinit iguanair_probe(struct usb_interface *intf,
        rc->s_tx_carrier = iguanair_set_tx_carrier;
        rc->tx_ir = iguanair_tx;
        rc->driver_name = DRIVER_NAME;
-       rc->map_name = RC_MAP_EMPTY;
+       rc->map_name = RC_MAP_RC6_MCE;
+       rc->timeout = MS_TO_NS(100);
+       rc->rx_resolution = RX_RESOLUTION;
 
        iguanair_set_tx_carrier(rc, 38000);
 
        ret = rc_register_device(rc);
        if (ret < 0) {
                dev_err(&intf->dev, "failed to register rc device %d", ret);
-               goto out;
+               goto out2;
        }
 
        usb_set_intfdata(intf, ir);
 
-       dev_info(&intf->dev, "Registered %s", ir->name);
-
        return 0;
+out2:
+       usb_kill_urb(ir->urb_in);
 out:
        if (ir) {
                usb_free_urb(ir->urb_in);
@@ -570,12 +543,11 @@ static void __devexit iguanair_disconnect(struct usb_interface *intf)
 {
        struct iguanair *ir = usb_get_intfdata(intf);
 
+       rc_unregister_device(ir->rc);
        usb_set_intfdata(intf, NULL);
-
        usb_kill_urb(ir->urb_in);
        usb_free_urb(ir->urb_in);
        usb_free_coherent(ir->udev, MAX_PACKET_SIZE, ir->buf_in, ir->dma_in);
-       rc_unregister_device(ir->rc);
        kfree(ir);
 }
 
@@ -592,6 +564,8 @@ static int iguanair_suspend(struct usb_interface *intf, pm_message_t message)
                        dev_warn(ir->dev, "failed to disable receiver for suspend\n");
        }
 
+       usb_kill_urb(ir->urb_in);
+
        mutex_unlock(&ir->lock);
 
        return rc;
@@ -604,6 +578,10 @@ static int iguanair_resume(struct usb_interface *intf)
 
        mutex_lock(&ir->lock);
 
+       rc = usb_submit_urb(ir->urb_in, GFP_KERNEL);
+       if (rc)
+               dev_warn(&intf->dev, "failed to submit urb: %d\n", rc);
+
        if (ir->receiver_on) {
                rc = iguanair_receiver(ir, true);
                if (rc)
@@ -627,7 +605,8 @@ static struct usb_driver iguanair_driver = {
        .suspend = iguanair_suspend,
        .resume = iguanair_resume,
        .reset_resume = iguanair_resume,
-       .id_table = iguanair_table
+       .id_table = iguanair_table,
+       .soft_unbind = 1        /* we want to disable receiver on unbind */
 };
 
 module_usb_driver(iguanair_driver);
index 5faba2a2fdd3b87621388c5c8f4254129d4db0ff..569124b03de3f8ecfa67321a536e144b628b81cd 100644 (file)
@@ -105,8 +105,14 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
        struct lirc_codec *lirc;
        struct rc_dev *dev;
        unsigned int *txbuf; /* buffer with values to transmit */
-       ssize_t ret = 0;
+       ssize_t ret = -EINVAL;
        size_t count;
+       ktime_t start;
+       s64 towait;
+       unsigned int duration = 0; /* signal duration in us */
+       int i;
+
+       start = ktime_get();
 
        lirc = lirc_get_pdata(file);
        if (!lirc)
@@ -129,11 +135,30 @@ static ssize_t ir_lirc_transmit_ir(struct file *file, const char __user *buf,
                goto out;
        }
 
-       if (dev->tx_ir)
-               ret = dev->tx_ir(dev, txbuf, count);
+       if (!dev->tx_ir) {
+               ret = -ENOSYS;
+               goto out;
+       }
+
+       ret = dev->tx_ir(dev, txbuf, count);
+       if (ret < 0)
+               goto out;
+
+       for (i = 0; i < ret; i++)
+               duration += txbuf[i];
 
-       if (ret > 0)
-               ret *= sizeof(unsigned);
+       ret *= sizeof(unsigned int);
+
+       /*
+        * The lircd gap calculation expects the write function to
+        * wait for the actual IR signal to be transmitted before
+        * returning.
+        */
+       towait = ktime_us_delta(ktime_add_us(start, duration), ktime_get());
+       if (towait > 0) {
+               set_current_state(TASK_INTERRUPTIBLE);
+               schedule_timeout(usecs_to_jiffies(towait));
+       }
 
 out:
        kfree(txbuf);
index 3c9431a9f62d282d37238ab6089cd63ca73ad77b..2ca509e6e16b6c73cc09b0bc84616b8b1b1beafe 100644 (file)
@@ -70,7 +70,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
                if (!ev.pulse)
                        break;
 
-               if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT / 2)) {
+               if (eq_margin(ev.duration, NEC_HEADER_PULSE, NEC_UNIT * 2)) {
                        data->is_nec_x = false;
                        data->necx_repeat = false;
                } else if (eq_margin(ev.duration, NECX_HEADER_PULSE, NEC_UNIT / 2))
@@ -86,7 +86,7 @@ static int ir_nec_decode(struct rc_dev *dev, struct ir_raw_event ev)
                if (ev.pulse)
                        break;
 
-               if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT / 2)) {
+               if (eq_margin(ev.duration, NEC_HEADER_SPACE, NEC_UNIT)) {
                        data->state = STATE_BIT_PULSE;
                        return 0;
                } else if (eq_margin(ev.duration, NEC_REPEAT_SPACE, NEC_UNIT / 2)) {
index a82025121345bdad0dc1d84f425d640fa7010a30..97dc8d13b06b386ab2b93293f227a7de37769a29 100644 (file)
@@ -157,7 +157,9 @@ EXPORT_SYMBOL_GPL(ir_raw_event_store_edge);
  * This routine (which may be called from an interrupt context) works
  * in similar manner to ir_raw_event_store_edge.
  * This routine is intended for devices with limited internal buffer
- * It automerges samples of same type, and handles timeouts
+ * It automerges samples of same type, and handles timeouts. Returns non-zero
+ * if the event was added, and zero if the event was ignored due to idle
+ * processing.
  */
 int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
 {
@@ -184,7 +186,7 @@ int ir_raw_event_store_with_filter(struct rc_dev *dev, struct ir_raw_event *ev)
            dev->raw->this_ev.duration >= dev->timeout)
                ir_raw_event_set_idle(dev, true);
 
-       return 0;
+       return 1;
 }
 EXPORT_SYMBOL_GPL(ir_raw_event_store_with_filter);
 
diff --git a/drivers/media/rc/ir-rx51.c b/drivers/media/rc/ir-rx51.c
new file mode 100644 (file)
index 0000000..546199e
--- /dev/null
@@ -0,0 +1,498 @@
+/*
+ *  Copyright (C) 2008 Nokia Corporation
+ *
+ *  Based on lirc_serial.c
+ *
+ *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/interrupt.h>
+#include <linux/uaccess.h>
+#include <linux/platform_device.h>
+#include <linux/sched.h>
+#include <linux/wait.h>
+
+#include <plat/dmtimer.h>
+#include <plat/clock.h>
+#include <plat/omap-pm.h>
+
+#include <media/lirc.h>
+#include <media/lirc_dev.h>
+#include <media/ir-rx51.h>
+
+#define LIRC_RX51_DRIVER_FEATURES (LIRC_CAN_SET_SEND_DUTY_CYCLE |      \
+                                  LIRC_CAN_SET_SEND_CARRIER |          \
+                                  LIRC_CAN_SEND_PULSE)
+
+#define DRIVER_NAME "lirc_rx51"
+
+#define WBUF_LEN 256
+
+#define TIMER_MAX_VALUE 0xffffffff
+
+struct lirc_rx51 {
+       struct omap_dm_timer *pwm_timer;
+       struct omap_dm_timer *pulse_timer;
+       struct device        *dev;
+       struct lirc_rx51_platform_data *pdata;
+       wait_queue_head_t     wqueue;
+
+       unsigned long   fclk_khz;
+       unsigned int    freq;           /* carrier frequency */
+       unsigned int    duty_cycle;     /* carrier duty cycle */
+       unsigned int    irq_num;
+       unsigned int    match;
+       int             wbuf[WBUF_LEN];
+       int             wbuf_index;
+       unsigned long   device_is_open;
+       int             pwm_timer_num;
+};
+
+static void lirc_rx51_on(struct lirc_rx51 *lirc_rx51)
+{
+       omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
+                             OMAP_TIMER_TRIGGER_OVERFLOW_AND_COMPARE);
+}
+
+static void lirc_rx51_off(struct lirc_rx51 *lirc_rx51)
+{
+       omap_dm_timer_set_pwm(lirc_rx51->pwm_timer, 0, 1,
+                             OMAP_TIMER_TRIGGER_NONE);
+}
+
+static int init_timing_params(struct lirc_rx51 *lirc_rx51)
+{
+       u32 load, match;
+
+       load = -(lirc_rx51->fclk_khz * 1000 / lirc_rx51->freq);
+       match = -(lirc_rx51->duty_cycle * -load / 100);
+       omap_dm_timer_set_load(lirc_rx51->pwm_timer, 1, load);
+       omap_dm_timer_set_match(lirc_rx51->pwm_timer, 1, match);
+       omap_dm_timer_write_counter(lirc_rx51->pwm_timer, TIMER_MAX_VALUE - 2);
+       omap_dm_timer_start(lirc_rx51->pwm_timer);
+       omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+       omap_dm_timer_start(lirc_rx51->pulse_timer);
+
+       lirc_rx51->match = 0;
+
+       return 0;
+}
+
+#define tics_after(a, b) ((long)(b) - (long)(a) < 0)
+
+static int pulse_timer_set_timeout(struct lirc_rx51 *lirc_rx51, int usec)
+{
+       int counter;
+
+       BUG_ON(usec < 0);
+
+       if (lirc_rx51->match == 0)
+               counter = omap_dm_timer_read_counter(lirc_rx51->pulse_timer);
+       else
+               counter = lirc_rx51->match;
+
+       counter += (u32)(lirc_rx51->fclk_khz * usec / (1000));
+       omap_dm_timer_set_match(lirc_rx51->pulse_timer, 1, counter);
+       omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer,
+                                    OMAP_TIMER_INT_MATCH);
+       if (tics_after(omap_dm_timer_read_counter(lirc_rx51->pulse_timer),
+                      counter)) {
+               return 1;
+       }
+       return 0;
+}
+
+static irqreturn_t lirc_rx51_interrupt_handler(int irq, void *ptr)
+{
+       unsigned int retval;
+       struct lirc_rx51 *lirc_rx51 = ptr;
+
+       retval = omap_dm_timer_read_status(lirc_rx51->pulse_timer);
+       if (!retval)
+               return IRQ_NONE;
+
+       if (retval & ~OMAP_TIMER_INT_MATCH)
+               dev_err_ratelimited(lirc_rx51->dev,
+                               ": Unexpected interrupt source: %x\n", retval);
+
+       omap_dm_timer_write_status(lirc_rx51->pulse_timer,
+                               OMAP_TIMER_INT_MATCH    |
+                               OMAP_TIMER_INT_OVERFLOW |
+                               OMAP_TIMER_INT_CAPTURE);
+       if (lirc_rx51->wbuf_index < 0) {
+               dev_err_ratelimited(lirc_rx51->dev,
+                               ": BUG wbuf_index has value of %i\n",
+                               lirc_rx51->wbuf_index);
+               goto end;
+       }
+
+       /*
+        * If we happen to hit an odd latency spike, loop through the
+        * pulses until we catch up.
+        */
+       do {
+               if (lirc_rx51->wbuf_index >= WBUF_LEN)
+                       goto end;
+               if (lirc_rx51->wbuf[lirc_rx51->wbuf_index] == -1)
+                       goto end;
+
+               if (lirc_rx51->wbuf_index % 2)
+                       lirc_rx51_off(lirc_rx51);
+               else
+                       lirc_rx51_on(lirc_rx51);
+
+               retval = pulse_timer_set_timeout(lirc_rx51,
+                                       lirc_rx51->wbuf[lirc_rx51->wbuf_index]);
+               lirc_rx51->wbuf_index++;
+
+       } while (retval);
+
+       return IRQ_HANDLED;
+end:
+       /* Stop TX here */
+       lirc_rx51_off(lirc_rx51);
+       lirc_rx51->wbuf_index = -1;
+       omap_dm_timer_stop(lirc_rx51->pwm_timer);
+       omap_dm_timer_stop(lirc_rx51->pulse_timer);
+       omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+       wake_up_interruptible(&lirc_rx51->wqueue);
+
+       return IRQ_HANDLED;
+}
+
+static int lirc_rx51_init_port(struct lirc_rx51 *lirc_rx51)
+{
+       struct clk *clk_fclk;
+       int retval, pwm_timer = lirc_rx51->pwm_timer_num;
+
+       lirc_rx51->pwm_timer = omap_dm_timer_request_specific(pwm_timer);
+       if (lirc_rx51->pwm_timer == NULL) {
+               dev_err(lirc_rx51->dev, ": Error requesting GPT%d timer\n",
+                       pwm_timer);
+               return -EBUSY;
+       }
+
+       lirc_rx51->pulse_timer = omap_dm_timer_request();
+       if (lirc_rx51->pulse_timer == NULL) {
+               dev_err(lirc_rx51->dev, ": Error requesting pulse timer\n");
+               retval = -EBUSY;
+               goto err1;
+       }
+
+       omap_dm_timer_set_source(lirc_rx51->pwm_timer, OMAP_TIMER_SRC_SYS_CLK);
+       omap_dm_timer_set_source(lirc_rx51->pulse_timer,
+                               OMAP_TIMER_SRC_SYS_CLK);
+
+       omap_dm_timer_enable(lirc_rx51->pwm_timer);
+       omap_dm_timer_enable(lirc_rx51->pulse_timer);
+
+       lirc_rx51->irq_num = omap_dm_timer_get_irq(lirc_rx51->pulse_timer);
+       retval = request_irq(lirc_rx51->irq_num, lirc_rx51_interrupt_handler,
+                            IRQF_DISABLED | IRQF_SHARED,
+                            "lirc_pulse_timer", lirc_rx51);
+       if (retval) {
+               dev_err(lirc_rx51->dev, ": Failed to request interrupt line\n");
+               goto err2;
+       }
+
+       clk_fclk = omap_dm_timer_get_fclk(lirc_rx51->pwm_timer);
+       lirc_rx51->fclk_khz = clk_fclk->rate / 1000;
+
+       return 0;
+
+err2:
+       omap_dm_timer_free(lirc_rx51->pulse_timer);
+err1:
+       omap_dm_timer_free(lirc_rx51->pwm_timer);
+
+       return retval;
+}
+
+static int lirc_rx51_free_port(struct lirc_rx51 *lirc_rx51)
+{
+       omap_dm_timer_set_int_enable(lirc_rx51->pulse_timer, 0);
+       free_irq(lirc_rx51->irq_num, lirc_rx51);
+       lirc_rx51_off(lirc_rx51);
+       omap_dm_timer_disable(lirc_rx51->pwm_timer);
+       omap_dm_timer_disable(lirc_rx51->pulse_timer);
+       omap_dm_timer_free(lirc_rx51->pwm_timer);
+       omap_dm_timer_free(lirc_rx51->pulse_timer);
+       lirc_rx51->wbuf_index = -1;
+
+       return 0;
+}
+
+static ssize_t lirc_rx51_write(struct file *file, const char *buf,
+                         size_t n, loff_t *ppos)
+{
+       int count, i;
+       struct lirc_rx51 *lirc_rx51 = file->private_data;
+
+       if (n % sizeof(int))
+               return -EINVAL;
+
+       count = n / sizeof(int);
+       if ((count > WBUF_LEN) || (count % 2 == 0))
+               return -EINVAL;
+
+       /* Wait any pending transfers to finish */
+       wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
+
+       if (copy_from_user(lirc_rx51->wbuf, buf, n))
+               return -EFAULT;
+
+       /* Sanity check the input pulses */
+       for (i = 0; i < count; i++)
+               if (lirc_rx51->wbuf[i] < 0)
+                       return -EINVAL;
+
+       init_timing_params(lirc_rx51);
+       if (count < WBUF_LEN)
+               lirc_rx51->wbuf[count] = -1; /* Insert termination mark */
+
+       /*
+        * Adjust latency requirements so the device doesn't go in too
+        * deep sleep states
+        */
+       lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, 50);
+
+       lirc_rx51_on(lirc_rx51);
+       lirc_rx51->wbuf_index = 1;
+       pulse_timer_set_timeout(lirc_rx51, lirc_rx51->wbuf[0]);
+
+       /*
+        * Don't return back to the userspace until the transfer has
+        * finished
+        */
+       wait_event_interruptible(lirc_rx51->wqueue, lirc_rx51->wbuf_index < 0);
+
+       /* We can sleep again */
+       lirc_rx51->pdata->set_max_mpu_wakeup_lat(lirc_rx51->dev, -1);
+
+       return n;
+}
+
+static long lirc_rx51_ioctl(struct file *filep,
+                       unsigned int cmd, unsigned long arg)
+{
+       int result;
+       unsigned long value;
+       unsigned int ivalue;
+       struct lirc_rx51 *lirc_rx51 = filep->private_data;
+
+       switch (cmd) {
+       case LIRC_GET_SEND_MODE:
+               result = put_user(LIRC_MODE_PULSE, (unsigned long *)arg);
+               if (result)
+                       return result;
+               break;
+
+       case LIRC_SET_SEND_MODE:
+               result = get_user(value, (unsigned long *)arg);
+               if (result)
+                       return result;
+
+               /* only LIRC_MODE_PULSE supported */
+               if (value != LIRC_MODE_PULSE)
+                       return -ENOSYS;
+               break;
+
+       case LIRC_GET_REC_MODE:
+               result = put_user(0, (unsigned long *) arg);
+               if (result)
+                       return result;
+               break;
+
+       case LIRC_GET_LENGTH:
+               return -ENOSYS;
+               break;
+
+       case LIRC_SET_SEND_DUTY_CYCLE:
+               result = get_user(ivalue, (unsigned int *) arg);
+               if (result)
+                       return result;
+
+               if (ivalue <= 0 || ivalue > 100) {
+                       dev_err(lirc_rx51->dev, ": invalid duty cycle %d\n",
+                               ivalue);
+                       return -EINVAL;
+               }
+
+               lirc_rx51->duty_cycle = ivalue;
+               break;
+
+       case LIRC_SET_SEND_CARRIER:
+               result = get_user(ivalue, (unsigned int *) arg);
+               if (result)
+                       return result;
+
+               if (ivalue > 500000 || ivalue < 20000) {
+                       dev_err(lirc_rx51->dev, ": invalid carrier freq %d\n",
+                               ivalue);
+                       return -EINVAL;
+               }
+
+               lirc_rx51->freq = ivalue;
+               break;
+
+       case LIRC_GET_FEATURES:
+               result = put_user(LIRC_RX51_DRIVER_FEATURES,
+                                 (unsigned long *) arg);
+               if (result)
+                       return result;
+               break;
+
+       default:
+               return -ENOIOCTLCMD;
+       }
+
+       return 0;
+}
+
+static int lirc_rx51_open(struct inode *inode, struct file *file)
+{
+       struct lirc_rx51 *lirc_rx51 = lirc_get_pdata(file);
+       BUG_ON(!lirc_rx51);
+
+       file->private_data = lirc_rx51;
+
+       if (test_and_set_bit(1, &lirc_rx51->device_is_open))
+               return -EBUSY;
+
+       return lirc_rx51_init_port(lirc_rx51);
+}
+
+static int lirc_rx51_release(struct inode *inode, struct file *file)
+{
+       struct lirc_rx51 *lirc_rx51 = file->private_data;
+
+       lirc_rx51_free_port(lirc_rx51);
+
+       clear_bit(1, &lirc_rx51->device_is_open);
+
+       return 0;
+}
+
+static struct lirc_rx51 lirc_rx51 = {
+       .freq           = 38000,
+       .duty_cycle     = 50,
+       .wbuf_index     = -1,
+};
+
+static const struct file_operations lirc_fops = {
+       .owner          = THIS_MODULE,
+       .write          = lirc_rx51_write,
+       .unlocked_ioctl = lirc_rx51_ioctl,
+       .read           = lirc_dev_fop_read,
+       .poll           = lirc_dev_fop_poll,
+       .open           = lirc_rx51_open,
+       .release        = lirc_rx51_release,
+};
+
+static struct lirc_driver lirc_rx51_driver = {
+       .name           = DRIVER_NAME,
+       .minor          = -1,
+       .code_length    = 1,
+       .data           = &lirc_rx51,
+       .fops           = &lirc_fops,
+       .owner          = THIS_MODULE,
+};
+
+#ifdef CONFIG_PM
+
+static int lirc_rx51_suspend(struct platform_device *dev, pm_message_t state)
+{
+       /*
+        * In case the device is still open, do not suspend. Normally
+        * this should not be a problem as lircd only keeps the device
+        * open only for short periods of time. We also don't want to
+        * get involved with race conditions that might happen if we
+        * were in a middle of a transmit. Thus, we defer any suspend
+        * actions until transmit has completed.
+        */
+       if (test_and_set_bit(1, &lirc_rx51.device_is_open))
+               return -EAGAIN;
+
+       clear_bit(1, &lirc_rx51.device_is_open);
+
+       return 0;
+}
+
+static int lirc_rx51_resume(struct platform_device *dev)
+{
+       return 0;
+}
+
+#else
+
+#define lirc_rx51_suspend      NULL
+#define lirc_rx51_resume       NULL
+
+#endif /* CONFIG_PM */
+
+static int __devinit lirc_rx51_probe(struct platform_device *dev)
+{
+       lirc_rx51_driver.features = LIRC_RX51_DRIVER_FEATURES;
+       lirc_rx51.pdata = dev->dev.platform_data;
+       lirc_rx51.pwm_timer_num = lirc_rx51.pdata->pwm_timer;
+       lirc_rx51.dev = &dev->dev;
+       lirc_rx51_driver.dev = &dev->dev;
+       lirc_rx51_driver.minor = lirc_register_driver(&lirc_rx51_driver);
+       init_waitqueue_head(&lirc_rx51.wqueue);
+
+       if (lirc_rx51_driver.minor < 0) {
+               dev_err(lirc_rx51.dev, ": lirc_register_driver failed: %d\n",
+                      lirc_rx51_driver.minor);
+               return lirc_rx51_driver.minor;
+       }
+       dev_info(lirc_rx51.dev, "registration ok, minor: %d, pwm: %d\n",
+                lirc_rx51_driver.minor, lirc_rx51.pwm_timer_num);
+
+       return 0;
+}
+
+static int __exit lirc_rx51_remove(struct platform_device *dev)
+{
+       return lirc_unregister_driver(lirc_rx51_driver.minor);
+}
+
+struct platform_driver lirc_rx51_platform_driver = {
+       .probe          = lirc_rx51_probe,
+       .remove         = __exit_p(lirc_rx51_remove),
+       .suspend        = lirc_rx51_suspend,
+       .resume         = lirc_rx51_resume,
+       .driver         = {
+               .name   = DRIVER_NAME,
+               .owner  = THIS_MODULE,
+       },
+};
+
+static int __init lirc_rx51_init(void)
+{
+       return platform_driver_register(&lirc_rx51_platform_driver);
+}
+module_init(lirc_rx51_init);
+
+static void __exit lirc_rx51_exit(void)
+{
+       platform_driver_unregister(&lirc_rx51_platform_driver);
+}
+module_exit(lirc_rx51_exit);
+
+MODULE_DESCRIPTION("LIRC TX driver for Nokia RX51");
+MODULE_AUTHOR("Nokia Corporation");
+MODULE_LICENSE("GPL");
index 36fe5a349b95d34e0d9a2b427b891647bf7bf6fa..24c77a42fc3645c2297688878396ae992ab9dc6b 100644 (file)
@@ -1473,6 +1473,7 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        rdev = rc_allocate_device();
        if (!rdev)
                goto failure;
+       itdev->rdev = rdev;
 
        ret = -ENODEV;
 
@@ -1604,7 +1605,6 @@ static int ite_probe(struct pnp_dev *pdev, const struct pnp_device_id
        if (ret)
                goto failure3;
 
-       itdev->rdev = rdev;
        ite_pr(KERN_NOTICE, "driver has been successfully loaded\n");
 
        return 0;
index caeff85603e3c71fb4182ae8822aff4734df801f..80217ffc91db39738e2936136444f353e447979e 100644 (file)
@@ -61,7 +61,7 @@ static struct rc_map_list tt_1500_map = {
        .map = {
                .scan    = tt_1500,
                .size    = ARRAY_SIZE(tt_1500),
-               .rc_type = RC_TYPE_UNKNOWN,     /* Legacy IR type */
+               .rc_type = RC_TYPE_RC5,
                .name    = RC_MAP_TT_1500,
        }
 };
index f38d9a8c6880168a4c6256bdb227218c70123ed9..850547fe711c25131ca84b748b35de2c35b8b5ae 100644 (file)
@@ -627,7 +627,7 @@ static void mceusb_dev_printdata(struct mceusb_dev *ir, char *buf,
                        break;
                case MCE_RSP_EQIRCFS:
                        period = DIV_ROUND_CLOSEST(
-                                       (1 << data1 * 2) * (data2 + 1), 10);
+                                       (1U << data1 * 2) * (data2 + 1), 10);
                        if (!period)
                                break;
                        carrier = (1000 * 1000) / period;
@@ -791,10 +791,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        int i, ret = 0;
        int cmdcount = 0;
        unsigned char *cmdbuf; /* MCE command buffer */
-       long signal_duration = 0; /* Singnal length in us */
-       struct timeval start_time, end_time;
-
-       do_gettimeofday(&start_time);
 
        cmdbuf = kzalloc(sizeof(unsigned) * MCE_CMDBUF_SIZE, GFP_KERNEL);
        if (!cmdbuf)
@@ -807,7 +803,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 
        /* Generate mce packet data */
        for (i = 0; (i < count) && (cmdcount < MCE_CMDBUF_SIZE); i++) {
-               signal_duration += txbuf[i];
                txbuf[i] = txbuf[i] / MCE_TIME_UNIT;
 
                do { /* loop to support long pulses/spaces > 127*50us=6.35ms */
@@ -850,19 +845,6 @@ static int mceusb_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        /* Transmit the command to the mce device */
        mce_async_out(ir, cmdbuf, cmdcount);
 
-       /*
-        * The lircd gap calculation expects the write function to
-        * wait the time it takes for the ircommand to be sent before
-        * it returns.
-        */
-       do_gettimeofday(&end_time);
-       signal_duration -= (end_time.tv_usec - start_time.tv_usec) +
-                          (end_time.tv_sec - start_time.tv_sec) * 1000000;
-
-       /* delay with the closest number of ticks */
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(usecs_to_jiffies(signal_duration));
-
 out:
        kfree(cmdbuf);
        return ret ? ret : count;
@@ -974,6 +956,7 @@ static void mceusb_handle_command(struct mceusb_dev *ir, int index)
 static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
 {
        DEFINE_IR_RAW_EVENT(rawir);
+       bool event = false;
        int i = 0;
 
        /* skip meaningless 0xb1 0x60 header bytes on orig receiver */
@@ -1004,7 +987,8 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
                                rawir.pulse ? "pulse" : "space",
                                rawir.duration);
 
-                       ir_raw_event_store_with_filter(ir->rc, &rawir);
+                       if (ir_raw_event_store_with_filter(ir->rc, &rawir))
+                               event = true;
                        break;
                case CMD_DATA:
                        ir->rem--;
@@ -1032,8 +1016,10 @@ static void mceusb_process_ir_data(struct mceusb_dev *ir, int buf_len)
                if (ir->parser_state != CMD_HEADER && !ir->rem)
                        ir->parser_state = CMD_HEADER;
        }
-       mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
-       ir_raw_event_handle(ir->rc);
+       if (event) {
+               mce_dbg(ir->dev, "processed IR data, calling ir_raw_event_handle\n");
+               ir_raw_event_handle(ir->rc);
+       }
 }
 
 static void mceusb_dev_recv(struct urb *urb)
index fae1615e0ff24d6b3d87b660f7c45e55f75a8689..f9be68132c67069e9f30eca7acade491d2770d41 100644 (file)
@@ -105,18 +105,9 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
 {
        struct loopback_dev *lodev = dev->priv;
        u32 rxmask;
-       unsigned total_duration = 0;
        unsigned i;
        DEFINE_IR_RAW_EVENT(rawir);
 
-       for (i = 0; i < count; i++)
-               total_duration += abs(txbuf[i]);
-
-       if (total_duration == 0) {
-               dprintk("invalid tx data, total duration zero\n");
-               return -EINVAL;
-       }
-
        if (lodev->txcarrier < lodev->rxcarriermin ||
            lodev->txcarrier > lodev->rxcarriermax) {
                dprintk("ignoring tx, carrier out of range\n");
@@ -148,9 +139,6 @@ static int loop_tx_ir(struct rc_dev *dev, unsigned *txbuf, unsigned count)
        ir_raw_event_handle(dev);
 
 out:
-       /* Lirc expects this function to take as long as the total duration */
-       set_current_state(TASK_INTERRUPTIBLE);
-       schedule_timeout(usecs_to_jiffies(total_duration));
        return count;
 }
 
index 2878b0ed9741b27e497a171dab39e664f271cb27..49731b1a9c57f09a5e9aa43a199e7f5f4e5d766a 100644 (file)
@@ -1217,9 +1217,10 @@ static int __devinit redrat3_dev_probe(struct usb_interface *intf,
        rr3->carrier = 38000;
 
        rr3->rc = redrat3_init_rc_dev(rr3);
-       if (!rr3->rc)
+       if (!rr3->rc) {
+               retval = -ENOMEM;
                goto error;
-
+       }
        setup_timer(&rr3->rx_timeout, redrat3_rx_timeout, (unsigned long)rr3);
 
        /* we can register the device now, as it is ready */
diff --git a/drivers/media/rc/ttusbir.c b/drivers/media/rc/ttusbir.c
new file mode 100644 (file)
index 0000000..fef0523
--- /dev/null
@@ -0,0 +1,447 @@
+/*
+ * TechnoTrend USB IR Receiver
+ *
+ * Copyright (C) 2012 Sean Young <sean@mess.org>
+ *
+ * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#include <linux/module.h>
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <linux/slab.h>
+#include <linux/leds.h>
+#include <media/rc-core.h>
+
+#define DRIVER_NAME    "ttusbir"
+#define DRIVER_DESC    "TechnoTrend USB IR Receiver"
+/*
+ * The Windows driver uses 8 URBS, the original lirc drivers has a
+ * configurable amount (2 default, 4 max). This device generates about 125
+ * messages per second (!), whether IR is idle or not.
+ */
+#define NUM_URBS       4
+#define NS_PER_BYTE    62500
+#define NS_PER_BIT     (NS_PER_BYTE/8)
+
+struct ttusbir {
+       struct rc_dev *rc;
+       struct device *dev;
+       struct usb_device *udev;
+
+       struct urb *urb[NUM_URBS];
+
+       struct led_classdev led;
+       struct urb *bulk_urb;
+       uint8_t bulk_buffer[5];
+       int bulk_out_endp, iso_in_endp;
+       bool led_on, is_led_on;
+       atomic_t led_complete;
+
+       char phys[64];
+};
+
+static enum led_brightness ttusbir_brightness_get(struct led_classdev *led_dev)
+{
+       struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
+
+       return tt->led_on ? LED_FULL : LED_OFF;
+}
+
+static void ttusbir_set_led(struct ttusbir *tt)
+{
+       int ret;
+
+       smp_mb();
+
+       if (tt->led_on != tt->is_led_on && tt->udev &&
+                               atomic_add_unless(&tt->led_complete, 1, 1)) {
+               tt->bulk_buffer[4] = tt->is_led_on = tt->led_on;
+               ret = usb_submit_urb(tt->bulk_urb, GFP_ATOMIC);
+               if (ret) {
+                       dev_warn(tt->dev, "failed to submit bulk urb: %d\n",
+                                                                       ret);
+                       atomic_dec(&tt->led_complete);
+               }
+       }
+}
+
+static void ttusbir_brightness_set(struct led_classdev *led_dev, enum
+                                               led_brightness brightness)
+{
+       struct ttusbir *tt = container_of(led_dev, struct ttusbir, led);
+
+       tt->led_on = brightness != LED_OFF;
+
+       ttusbir_set_led(tt);
+}
+
+/*
+ * The urb cannot be reused until the urb completes
+ */
+static void ttusbir_bulk_complete(struct urb *urb)
+{
+       struct ttusbir *tt = urb->context;
+
+       atomic_dec(&tt->led_complete);
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               usb_unlink_urb(urb);
+               return;
+       case -EPIPE:
+       default:
+               dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
+               break;
+       }
+
+       ttusbir_set_led(tt);
+}
+
+/*
+ * The data is one bit per sample, a set bit signifying silence and samples
+ * being MSB first. Bit 0 can contain garbage so take it to be whatever
+ * bit 1 is, so we don't have unexpected edges.
+ */
+static void ttusbir_process_ir_data(struct ttusbir *tt, uint8_t *buf)
+{
+       struct ir_raw_event rawir;
+       unsigned i, v, b;
+       bool event = false;
+
+       init_ir_raw_event(&rawir);
+
+       for (i = 0; i < 128; i++) {
+               v = buf[i] & 0xfe;
+               switch (v) {
+               case 0xfe:
+                       rawir.pulse = false;
+                       rawir.duration = NS_PER_BYTE;
+                       if (ir_raw_event_store_with_filter(tt->rc, &rawir))
+                               event = true;
+                       break;
+               case 0:
+                       rawir.pulse = true;
+                       rawir.duration = NS_PER_BYTE;
+                       if (ir_raw_event_store_with_filter(tt->rc, &rawir))
+                               event = true;
+                       break;
+               default:
+                       /* one edge per byte */
+                       if (v & 2) {
+                               b = ffz(v | 1);
+                               rawir.pulse = true;
+                       } else {
+                               b = ffs(v) - 1;
+                               rawir.pulse = false;
+                       }
+
+                       rawir.duration = NS_PER_BIT * (8 - b);
+                       if (ir_raw_event_store_with_filter(tt->rc, &rawir))
+                               event = true;
+
+                       rawir.pulse = !rawir.pulse;
+                       rawir.duration = NS_PER_BIT * b;
+                       if (ir_raw_event_store_with_filter(tt->rc, &rawir))
+                               event = true;
+                       break;
+               }
+       }
+
+       /* don't wakeup when there's nothing to do */
+       if (event)
+               ir_raw_event_handle(tt->rc);
+}
+
+static void ttusbir_urb_complete(struct urb *urb)
+{
+       struct ttusbir *tt = urb->context;
+       int rc;
+
+       switch (urb->status) {
+       case 0:
+               ttusbir_process_ir_data(tt, urb->transfer_buffer);
+               break;
+       case -ECONNRESET:
+       case -ENOENT:
+       case -ESHUTDOWN:
+               usb_unlink_urb(urb);
+               return;
+       case -EPIPE:
+       default:
+               dev_dbg(tt->dev, "Error: urb status = %d\n", urb->status);
+               break;
+       }
+
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
+       if (rc && rc != -ENODEV)
+               dev_warn(tt->dev, "failed to resubmit urb: %d\n", rc);
+}
+
+static int __devinit ttusbir_probe(struct usb_interface *intf,
+                                               const struct usb_device_id *id)
+{
+       struct ttusbir *tt;
+       struct usb_interface_descriptor *idesc;
+       struct usb_endpoint_descriptor *desc;
+       struct rc_dev *rc;
+       int i, j, ret;
+       int altsetting = -1;
+
+       tt = kzalloc(sizeof(*tt), GFP_KERNEL);
+       rc = rc_allocate_device();
+       if (!tt || !rc) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       /* find the correct alt setting */
+       for (i = 0; i < intf->num_altsetting && altsetting == -1; i++) {
+               int bulk_out_endp = -1, iso_in_endp = -1;
+
+               idesc = &intf->altsetting[i].desc;
+
+               for (j = 0; j < idesc->bNumEndpoints; j++) {
+                       desc = &intf->altsetting[i].endpoint[j].desc;
+                       if (usb_endpoint_dir_in(desc) &&
+                                       usb_endpoint_xfer_isoc(desc) &&
+                                       desc->wMaxPacketSize == 0x10)
+                               iso_in_endp = j;
+                       else if (usb_endpoint_dir_out(desc) &&
+                                       usb_endpoint_xfer_bulk(desc) &&
+                                       desc->wMaxPacketSize == 0x20)
+                               bulk_out_endp = j;
+
+                       if (bulk_out_endp != -1 && iso_in_endp != -1) {
+                               tt->bulk_out_endp = bulk_out_endp;
+                               tt->iso_in_endp = iso_in_endp;
+                               altsetting = i;
+                               break;
+                       }
+               }
+       }
+
+       if (altsetting == -1) {
+               dev_err(&intf->dev, "cannot find expected altsetting\n");
+               ret = -ENODEV;
+               goto out;
+       }
+
+       tt->dev = &intf->dev;
+       tt->udev = interface_to_usbdev(intf);
+       tt->rc = rc;
+
+       ret = usb_set_interface(tt->udev, 0, altsetting);
+       if (ret)
+               goto out;
+
+       for (i = 0; i < NUM_URBS; i++) {
+               struct urb *urb = usb_alloc_urb(8, GFP_KERNEL);
+               void *buffer;
+
+               if (!urb) {
+                       ret = -ENOMEM;
+                       goto out;
+               }
+
+               urb->dev = tt->udev;
+               urb->context = tt;
+               urb->pipe = usb_rcvisocpipe(tt->udev, tt->iso_in_endp);
+               urb->interval = 1;
+               buffer = usb_alloc_coherent(tt->udev, 128, GFP_KERNEL,
+                                               &urb->transfer_dma);
+               if (!buffer) {
+                       usb_free_urb(urb);
+                       ret = -ENOMEM;
+                       goto out;
+               }
+               urb->transfer_flags = URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP;
+               urb->transfer_buffer = buffer;
+               urb->complete = ttusbir_urb_complete;
+               urb->number_of_packets = 8;
+               urb->transfer_buffer_length = 128;
+
+               for (j = 0; j < 8; j++) {
+                       urb->iso_frame_desc[j].offset = j * 16;
+                       urb->iso_frame_desc[j].length = 16;
+               }
+
+               tt->urb[i] = urb;
+       }
+
+       tt->bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
+       if (!tt->bulk_urb) {
+               ret = -ENOMEM;
+               goto out;
+       }
+
+       tt->bulk_buffer[0] = 0xaa;
+       tt->bulk_buffer[1] = 0x01;
+       tt->bulk_buffer[2] = 0x05;
+       tt->bulk_buffer[3] = 0x01;
+
+       usb_fill_bulk_urb(tt->bulk_urb, tt->udev, usb_sndbulkpipe(tt->udev,
+               tt->bulk_out_endp), tt->bulk_buffer, sizeof(tt->bulk_buffer),
+                                               ttusbir_bulk_complete, tt);
+
+       tt->led.name = "ttusbir:green:power";
+       tt->led.brightness_set = ttusbir_brightness_set;
+       tt->led.brightness_get = ttusbir_brightness_get;
+       tt->is_led_on = tt->led_on = true;
+       atomic_set(&tt->led_complete, 0);
+       ret = led_classdev_register(&intf->dev, &tt->led);
+       if (ret)
+               goto out;
+
+       usb_make_path(tt->udev, tt->phys, sizeof(tt->phys));
+
+       rc->input_name = DRIVER_DESC;
+       rc->input_phys = tt->phys;
+       usb_to_input_id(tt->udev, &rc->input_id);
+       rc->dev.parent = &intf->dev;
+       rc->driver_type = RC_DRIVER_IR_RAW;
+       rc->allowed_protos = RC_TYPE_ALL;
+       rc->priv = tt;
+       rc->driver_name = DRIVER_NAME;
+       rc->map_name = RC_MAP_TT_1500;
+       rc->timeout = MS_TO_NS(100);
+       /*
+        * The precision is NS_PER_BIT, but since every 8th bit can be
+        * overwritten with garbage the accuracy is at best 2 * NS_PER_BIT.
+        */
+       rc->rx_resolution = NS_PER_BIT;
+
+       ret = rc_register_device(rc);
+       if (ret) {
+               dev_err(&intf->dev, "failed to register rc device %d\n", ret);
+               goto out2;
+       }
+
+       usb_set_intfdata(intf, tt);
+
+       for (i = 0; i < NUM_URBS; i++) {
+               ret = usb_submit_urb(tt->urb[i], GFP_KERNEL);
+               if (ret) {
+                       dev_err(tt->dev, "failed to submit urb %d\n", ret);
+                       goto out3;
+               }
+       }
+
+       return 0;
+out3:
+       rc_unregister_device(rc);
+out2:
+       led_classdev_unregister(&tt->led);
+out:
+       if (tt) {
+               for (i = 0; i < NUM_URBS && tt->urb[i]; i++) {
+                       struct urb *urb = tt->urb[i];
+
+                       usb_kill_urb(urb);
+                       usb_free_coherent(tt->udev, 128, urb->transfer_buffer,
+                                                       urb->transfer_dma);
+                       usb_free_urb(urb);
+               }
+               usb_kill_urb(tt->bulk_urb);
+               usb_free_urb(tt->bulk_urb);
+               kfree(tt);
+       }
+       rc_free_device(rc);
+
+       return ret;
+}
+
+static void __devexit ttusbir_disconnect(struct usb_interface *intf)
+{
+       struct ttusbir *tt = usb_get_intfdata(intf);
+       struct usb_device *udev = tt->udev;
+       int i;
+
+       tt->udev = NULL;
+
+       rc_unregister_device(tt->rc);
+       led_classdev_unregister(&tt->led);
+       for (i = 0; i < NUM_URBS; i++) {
+               usb_kill_urb(tt->urb[i]);
+               usb_free_coherent(udev, 128, tt->urb[i]->transfer_buffer,
+                                               tt->urb[i]->transfer_dma);
+               usb_free_urb(tt->urb[i]);
+       }
+       usb_kill_urb(tt->bulk_urb);
+       usb_free_urb(tt->bulk_urb);
+       usb_set_intfdata(intf, NULL);
+       kfree(tt);
+}
+
+static int ttusbir_suspend(struct usb_interface *intf, pm_message_t message)
+{
+       struct ttusbir *tt = usb_get_intfdata(intf);
+       int i;
+
+       for (i = 0; i < NUM_URBS; i++)
+               usb_kill_urb(tt->urb[i]);
+
+       led_classdev_suspend(&tt->led);
+       usb_kill_urb(tt->bulk_urb);
+
+       return 0;
+}
+
+static int ttusbir_resume(struct usb_interface *intf)
+{
+       struct ttusbir *tt = usb_get_intfdata(intf);
+       int i, rc;
+
+       led_classdev_resume(&tt->led);
+       tt->is_led_on = true;
+       ttusbir_set_led(tt);
+
+       for (i = 0; i < NUM_URBS; i++) {
+               rc = usb_submit_urb(tt->urb[i], GFP_KERNEL);
+               if (rc) {
+                       dev_warn(tt->dev, "failed to submit urb: %d\n", rc);
+                       break;
+               }
+       }
+
+       return rc;
+}
+
+static const struct usb_device_id ttusbir_table[] = {
+       { USB_DEVICE(0x0b48, 0x2003) },
+       { }
+};
+
+static struct usb_driver ttusbir_driver = {
+       .name = DRIVER_NAME,
+       .id_table = ttusbir_table,
+       .probe = ttusbir_probe,
+       .suspend = ttusbir_suspend,
+       .resume = ttusbir_resume,
+       .reset_resume = ttusbir_resume,
+       .disconnect = __devexit_p(ttusbir_disconnect)
+};
+
+module_usb_driver(ttusbir_driver);
+
+MODULE_DESCRIPTION(DRIVER_DESC);
+MODULE_AUTHOR("Sean Young <sean@mess.org>");
+MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(usb, ttusbir_table);
+
index 54ee34872d143cea7345f60a5ad9038e91266a51..30ae1f24abc3b536ec6e0735c3a3be9f5f270a74 100644 (file)
@@ -180,7 +180,6 @@ enum wbcir_rxstate {
 enum wbcir_txstate {
        WBCIR_TXSTATE_INACTIVE = 0,
        WBCIR_TXSTATE_ACTIVE,
-       WBCIR_TXSTATE_DONE,
        WBCIR_TXSTATE_ERROR
 };
 
@@ -216,7 +215,6 @@ struct wbcir_data {
        u32 txlen;
        u32 txoff;
        u32 *txbuf;
-       wait_queue_head_t txwaitq;
        u8 txmask;
        u32 txcarrier;
 };
@@ -358,7 +356,7 @@ wbcir_irq_rx(struct wbcir_data *data, struct pnp_dev *device)
                if (data->rxstate == WBCIR_RXSTATE_ERROR)
                        continue;
                rawir.pulse = irdata & 0x80 ? false : true;
-               rawir.duration = US_TO_NS((irdata & 0x7F) * 10);
+               rawir.duration = US_TO_NS(((irdata & 0x7F) + 1) * 10);
                ir_raw_event_store_with_filter(data->dev, &rawir);
        }
 
@@ -424,11 +422,11 @@ wbcir_irq_tx(struct wbcir_data *data)
                if (data->txstate == WBCIR_TXSTATE_ERROR)
                        /* Clear TX underrun bit */
                        outb(WBCIR_TX_UNDERRUN, data->sbase + WBCIR_REG_SP3_ASCR);
-               else
-                       data->txstate = WBCIR_TXSTATE_DONE;
                wbcir_set_irqmask(data, WBCIR_IRQ_RX | WBCIR_IRQ_ERR);
                led_trigger_event(data->txtrigger, LED_OFF);
-               wake_up(&data->txwaitq);
+               kfree(data->txbuf);
+               data->txbuf = NULL;
+               data->txstate = WBCIR_TXSTATE_INACTIVE;
        } else if (data->txoff == data->txlen) {
                /* At the end of transmission, tell the hw before last byte */
                outsb(data->sbase + WBCIR_REG_SP3_TXDATA, bytes, used - 1);
@@ -579,43 +577,37 @@ wbcir_txmask(struct rc_dev *dev, u32 mask)
 }
 
 static int
-wbcir_tx(struct rc_dev *dev, unsigned *buf, unsigned count)
+wbcir_tx(struct rc_dev *dev, unsigned *b, unsigned count)
 {
        struct wbcir_data *data = dev->priv;
+       unsigned *buf;
        unsigned i;
        unsigned long flags;
 
+       buf = kmalloc(count * sizeof(*b), GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+
+       /* Convert values to multiples of 10us */
+       for (i = 0; i < count; i++)
+               buf[i] = DIV_ROUND_CLOSEST(b[i], 10);
+
        /* Not sure if this is possible, but better safe than sorry */
        spin_lock_irqsave(&data->spinlock, flags);
        if (data->txstate != WBCIR_TXSTATE_INACTIVE) {
                spin_unlock_irqrestore(&data->spinlock, flags);
+               kfree(buf);
                return -EBUSY;
        }
 
-       /* Convert values to multiples of 10us */
-       for (i = 0; i < count; i++)
-               buf[i] = DIV_ROUND_CLOSEST(buf[i], 10);
-
        /* Fill the TX fifo once, the irq handler will do the rest */
        data->txbuf = buf;
        data->txlen = count;
        data->txoff = 0;
        wbcir_irq_tx(data);
 
-       /* Wait for the TX to complete */
-       while (data->txstate == WBCIR_TXSTATE_ACTIVE) {
-               spin_unlock_irqrestore(&data->spinlock, flags);
-               wait_event(data->txwaitq, data->txstate != WBCIR_TXSTATE_ACTIVE);
-               spin_lock_irqsave(&data->spinlock, flags);
-       }
-
        /* We're done */
-       if (data->txstate == WBCIR_TXSTATE_ERROR)
-               count = -EAGAIN;
-       data->txstate = WBCIR_TXSTATE_INACTIVE;
-       data->txbuf = NULL;
        spin_unlock_irqrestore(&data->spinlock, flags);
-
        return count;
 }
 
@@ -927,13 +919,11 @@ wbcir_init_hw(struct wbcir_data *data)
        ir_raw_event_reset(data->dev);
        ir_raw_event_handle(data->dev);
 
-       /*
-        * Check TX state, if we did a suspend/resume cycle while TX was
-        * active, we will have a process waiting in txwaitq.
-        */
+       /* Clear TX state */
        if (data->txstate == WBCIR_TXSTATE_ACTIVE) {
-               data->txstate = WBCIR_TXSTATE_ERROR;
-               wake_up(&data->txwaitq);
+               kfree(data->txbuf);
+               data->txbuf = NULL;
+               data->txstate = WBCIR_TXSTATE_INACTIVE;
        }
 
        /* Enable interrupts */
@@ -974,7 +964,6 @@ wbcir_probe(struct pnp_dev *device, const struct pnp_device_id *dev_id)
        pnp_set_drvdata(device, data);
 
        spin_lock_init(&data->spinlock);
-       init_waitqueue_head(&data->txwaitq);
        data->ebase = pnp_port_start(device, 0);
        data->wbase = pnp_port_start(device, 1);
        data->sbase = pnp_port_start(device, 2);
similarity index 72%
rename from drivers/media/common/tuners/Kconfig
rename to drivers/media/tuners/Kconfig
index 94c6ff7a5da3ad20bf8f10c5bc08b919153e45e5..e8fdf713fce89a5e4a027f633f57136f7c271451 100644 (file)
@@ -18,43 +18,31 @@ config MEDIA_ATTACH
 
          If unsure say Y.
 
+# Analog TV tuners, auto-loaded via tuner.ko
 config MEDIA_TUNER
        tristate
        depends on (MEDIA_ANALOG_TV_SUPPORT || MEDIA_RADIO_SUPPORT) && I2C
        default y
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC4000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MT20XX if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TEA5761 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT && EXPERIMENTAL
-       select MEDIA_TUNER_TEA5767 if !MEDIA_TUNER_CUSTOMISE && MEDIA_RADIO_SUPPORT
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA9887 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MC44S803 if !MEDIA_TUNER_CUSTOMISE
-
-config MEDIA_TUNER_CUSTOMISE
-       bool "Customize analog and hybrid tuner modules to build"
-       depends on MEDIA_TUNER
-       default y if EXPERT
-       help
-         This allows the user to deselect tuner drivers unnecessary
-         for their hardware from the build. Use this option with care
-         as deselecting tuner drivers which are in fact necessary will
-         result in V4L/DVB devices which cannot be tuned due to lack of
-         driver support
-
-         If unsure say N.
+       select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT20XX if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TEA5761 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_RADIO_SUPPORT
+       select MEDIA_TUNER_TEA5767 if MEDIA_SUBDRV_AUTOSELECT && MEDIA_RADIO_SUPPORT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA9887 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MC44S803 if MEDIA_SUBDRV_AUTOSELECT
 
 menu "Customize TV tuners"
-       visible if MEDIA_TUNER_CUSTOMISE
+       visible if !MEDIA_SUBDRV_AUTOSELECT
        depends on MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT || MEDIA_RADIO_SUPPORT
 
 config MEDIA_TUNER_SIMPLE
        tristate "Simple tuner support"
        depends on MEDIA_SUPPORT && I2C
        select MEDIA_TUNER_TDA9887
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for various simple tuners.
 
@@ -63,100 +51,99 @@ config MEDIA_TUNER_TDA8290
        depends on MEDIA_SUPPORT && I2C
        select MEDIA_TUNER_TDA827X
        select MEDIA_TUNER_TDA18271
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for Philips TDA8290+8275(a) tuner.
 
 config MEDIA_TUNER_TDA827X
        tristate "Philips TDA827X silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A DVB-T silicon tuner module. Say Y when you want to support this tuner.
 
 config MEDIA_TUNER_TDA18271
        tristate "NXP TDA18271 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A silicon tuner module. Say Y when you want to support this tuner.
 
 config MEDIA_TUNER_TDA9887
        tristate "TDA 9885/6/7 analog IF demodulator"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for Philips TDA9885/6/7
          analog IF demodulator.
 
 config MEDIA_TUNER_TEA5761
-       tristate "TEA 5761 radio tuner (EXPERIMENTAL)"
+       tristate "TEA 5761 radio tuner"
        depends on MEDIA_SUPPORT && I2C
-       depends on EXPERIMENTAL
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for the Philips TEA5761 radio tuner.
 
 config MEDIA_TUNER_TEA5767
        tristate "TEA 5767 radio tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for the Philips TEA5767 radio tuner.
 
 config MEDIA_TUNER_MT20XX
        tristate "Microtune 2032 / 2050 tuners"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for the MT2032 / MT2050 tuner.
 
 config MEDIA_TUNER_MT2060
        tristate "Microtune MT2060 silicon IF tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon IF tuner MT2060 from Microtune.
 
 config MEDIA_TUNER_MT2063
        tristate "Microtune MT2063 silicon IF tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon IF tuner MT2063 from Microtune.
 
 config MEDIA_TUNER_MT2266
        tristate "Microtune MT2266 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon baseband tuner MT2266 from Microtune.
 
 config MEDIA_TUNER_MT2131
        tristate "Microtune MT2131 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon baseband tuner MT2131 from Microtune.
 
 config MEDIA_TUNER_QT1010
        tristate "Quantek QT1010 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner QT1010 from Quantek.
 
 config MEDIA_TUNER_XC2028
        tristate "XCeive xc2028/xc3028 tuners"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to include support for the xc2028/xc3028 tuners.
 
 config MEDIA_TUNER_XC5000
        tristate "Xceive XC5000 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner XC5000 from Xceive.
          This device is only used inside a SiP called together with a
@@ -165,7 +152,7 @@ config MEDIA_TUNER_XC5000
 config MEDIA_TUNER_XC4000
        tristate "Xceive XC4000 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner XC4000 from Xceive.
          This device is only used inside a SiP called together with a
@@ -174,70 +161,84 @@ config MEDIA_TUNER_XC4000
 config MEDIA_TUNER_MXL5005S
        tristate "MaxLinear MSL5005S silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner MXL5005S from MaxLinear.
 
 config MEDIA_TUNER_MXL5007T
        tristate "MaxLinear MxL5007T silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner MxL5007T from MaxLinear.
 
 config MEDIA_TUNER_MC44S803
        tristate "Freescale MC44S803 Low Power CMOS Broadband tuners"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Say Y here to support the Freescale MC44S803 based tuners
 
 config MEDIA_TUNER_MAX2165
        tristate "Maxim MAX2165 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          A driver for the silicon tuner MAX2165 from Maxim.
 
 config MEDIA_TUNER_TDA18218
        tristate "NXP TDA18218 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          NXP TDA18218 silicon tuner driver.
 
 config MEDIA_TUNER_FC0011
        tristate "Fitipower FC0011 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Fitipower FC0011 silicon tuner driver.
 
 config MEDIA_TUNER_FC0012
        tristate "Fitipower FC0012 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Fitipower FC0012 silicon tuner driver.
 
 config MEDIA_TUNER_FC0013
        tristate "Fitipower FC0013 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Fitipower FC0013 silicon tuner driver.
 
 config MEDIA_TUNER_TDA18212
        tristate "NXP TDA18212 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          NXP TDA18212 silicon tuner driver.
 
+config MEDIA_TUNER_E4000
+       tristate "Elonics E4000 silicon tuner"
+       depends on MEDIA_SUPPORT && I2C
+       default m if !MEDIA_SUBDRV_AUTOSELECT
+       help
+         Elonics E4000 silicon tuner driver.
+
+config MEDIA_TUNER_FC2580
+       tristate "FCI FC2580 silicon tuner"
+       depends on MEDIA_SUPPORT && I2C
+       default m if !MEDIA_SUBDRV_AUTOSELECT
+       help
+         FCI FC2580 silicon tuner driver.
+
 config MEDIA_TUNER_TUA9001
        tristate "Infineon TUA 9001 silicon tuner"
        depends on MEDIA_SUPPORT && I2C
-       default m if MEDIA_TUNER_CUSTOMISE
+       default m if !MEDIA_SUBDRV_AUTOSELECT
        help
          Infineon TUA 9001 silicon tuner driver.
 endmenu
similarity index 88%
rename from drivers/media/common/tuners/Makefile
rename to drivers/media/tuners/Makefile
index 891b80e60808d6aac66c81053c13eb4d106689bd..5e569b1083cf3fd74934af1aad0a9a91e75e93cb 100644 (file)
@@ -28,10 +28,12 @@ obj-$(CONFIG_MEDIA_TUNER_MC44S803) += mc44s803.o
 obj-$(CONFIG_MEDIA_TUNER_MAX2165) += max2165.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18218) += tda18218.o
 obj-$(CONFIG_MEDIA_TUNER_TDA18212) += tda18212.o
+obj-$(CONFIG_MEDIA_TUNER_E4000) += e4000.o
+obj-$(CONFIG_MEDIA_TUNER_FC2580) += fc2580.o
 obj-$(CONFIG_MEDIA_TUNER_TUA9001) += tua9001.o
 obj-$(CONFIG_MEDIA_TUNER_FC0011) += fc0011.o
 obj-$(CONFIG_MEDIA_TUNER_FC0012) += fc0012.o
 obj-$(CONFIG_MEDIA_TUNER_FC0013) += fc0013.o
 
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
diff --git a/drivers/media/tuners/e4000.c b/drivers/media/tuners/e4000.c
new file mode 100644 (file)
index 0000000..1b33ed3
--- /dev/null
@@ -0,0 +1,409 @@
+/*
+ * Elonics E4000 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "e4000_priv.h"
+
+/* write multiple registers */
+static int e4000_wr_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[1 + len];
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = reg;
+       memcpy(&buf[1], val, len);
+
+       ret = i2c_transfer(priv->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+       return ret;
+}
+
+/* read multiple registers */
+static int e4000_rd_regs(struct e4000_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[len];
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = &reg,
+               }, {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       ret = i2c_transfer(priv->i2c, msg, 2);
+       if (ret == 2) {
+               memcpy(val, buf, len);
+               ret = 0;
+       } else {
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+
+       return ret;
+}
+
+/* write single register */
+static int e4000_wr_reg(struct e4000_priv *priv, u8 reg, u8 val)
+{
+       return e4000_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int e4000_rd_reg(struct e4000_priv *priv, u8 reg, u8 *val)
+{
+       return e4000_rd_regs(priv, reg, val, 1);
+}
+
+static int e4000_init(struct dvb_frontend *fe)
+{
+       struct e4000_priv *priv = fe->tuner_priv;
+       int ret;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* dummy I2C to ensure I2C wakes up */
+       ret = e4000_wr_reg(priv, 0x02, 0x40);
+
+       /* reset */
+       ret = e4000_wr_reg(priv, 0x00, 0x01);
+       if (ret < 0)
+               goto err;
+
+       /* disable output clock */
+       ret = e4000_wr_reg(priv, 0x06, 0x00);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x7a, 0x96);
+       if (ret < 0)
+               goto err;
+
+       /* configure gains */
+       ret = e4000_wr_regs(priv, 0x7e, "\x01\xfe", 2);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x82, 0x00);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x24, 0x05);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_regs(priv, 0x87, "\x20\x01", 2);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_regs(priv, 0x9f, "\x7f\x07", 2);
+       if (ret < 0)
+               goto err;
+
+       /*
+        * TODO: Implement DC offset control correctly.
+        * DC offsets has quite much effect for received signal quality in case
+        * of direct conversion tuners (Zero-IF). Surely we will now lose few
+        * decimals or even decibels from SNR...
+        */
+       /* DC offset control */
+       ret = e4000_wr_reg(priv, 0x2d, 0x0c);
+       if (ret < 0)
+               goto err;
+
+       /* gain control */
+       ret = e4000_wr_reg(priv, 0x1a, 0x17);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x1f, 0x1a);
+       if (ret < 0)
+               goto err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int e4000_sleep(struct dvb_frontend *fe)
+{
+       struct e4000_priv *priv = fe->tuner_priv;
+       int ret;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = e4000_wr_reg(priv, 0x00, 0x00);
+       if (ret < 0)
+               goto err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int e4000_set_params(struct dvb_frontend *fe)
+{
+       struct e4000_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret, i, sigma_delta;
+       unsigned int f_VCO;
+       u8 buf[5];
+
+       dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
+                       "bandwidth_hz=%d\n", __func__,
+                       c->delivery_system, c->frequency, c->bandwidth_hz);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* gain control manual */
+       ret = e4000_wr_reg(priv, 0x1a, 0x00);
+       if (ret < 0)
+               goto err;
+
+       /* PLL */
+       for (i = 0; i < ARRAY_SIZE(e4000_pll_lut); i++) {
+               if (c->frequency <= e4000_pll_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(e4000_pll_lut))
+               goto err;
+
+       /*
+        * Note: Currently f_VCO overflows when c->frequency is 1 073 741 824 Hz
+        * or more.
+        */
+       f_VCO = c->frequency * e4000_pll_lut[i].mul;
+       sigma_delta = 0x10000UL * (f_VCO % priv->cfg->clock) / priv->cfg->clock;
+       buf[0] = f_VCO / priv->cfg->clock;
+       buf[1] = (sigma_delta >> 0) & 0xff;
+       buf[2] = (sigma_delta >> 8) & 0xff;
+       buf[3] = 0x00;
+       buf[4] = e4000_pll_lut[i].div;
+
+       dev_dbg(&priv->i2c->dev, "%s: f_VCO=%u pll div=%d sigma_delta=%04x\n",
+                       __func__, f_VCO, buf[0], sigma_delta);
+
+       ret = e4000_wr_regs(priv, 0x09, buf, 5);
+       if (ret < 0)
+               goto err;
+
+       /* LNA filter (RF filter) */
+       for (i = 0; i < ARRAY_SIZE(e400_lna_filter_lut); i++) {
+               if (c->frequency <= e400_lna_filter_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(e400_lna_filter_lut))
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x10, e400_lna_filter_lut[i].val);
+       if (ret < 0)
+               goto err;
+
+       /* IF filters */
+       for (i = 0; i < ARRAY_SIZE(e4000_if_filter_lut); i++) {
+               if (c->bandwidth_hz <= e4000_if_filter_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(e4000_if_filter_lut))
+               goto err;
+
+       buf[0] = e4000_if_filter_lut[i].reg11_val;
+       buf[1] = e4000_if_filter_lut[i].reg12_val;
+
+       ret = e4000_wr_regs(priv, 0x11, buf, 2);
+       if (ret < 0)
+               goto err;
+
+       /* frequency band */
+       for (i = 0; i < ARRAY_SIZE(e4000_band_lut); i++) {
+               if (c->frequency <= e4000_band_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(e4000_band_lut))
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x07, e4000_band_lut[i].reg07_val);
+       if (ret < 0)
+               goto err;
+
+       ret = e4000_wr_reg(priv, 0x78, e4000_band_lut[i].reg78_val);
+       if (ret < 0)
+               goto err;
+
+       /* gain control auto */
+       ret = e4000_wr_reg(priv, 0x1a, 0x17);
+       if (ret < 0)
+               goto err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int e4000_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct e4000_priv *priv = fe->tuner_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       *frequency = 0; /* Zero-IF */
+
+       return 0;
+}
+
+static int e4000_release(struct dvb_frontend *fe)
+{
+       struct e4000_priv *priv = fe->tuner_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       kfree(fe->tuner_priv);
+
+       return 0;
+}
+
+static const struct dvb_tuner_ops e4000_tuner_ops = {
+       .info = {
+               .name           = "Elonics E4000",
+               .frequency_min  = 174000000,
+               .frequency_max  = 862000000,
+       },
+
+       .release = e4000_release,
+
+       .init = e4000_init,
+       .sleep = e4000_sleep,
+       .set_params = e4000_set_params,
+
+       .get_if_frequency = e4000_get_if_frequency,
+};
+
+struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
+               struct i2c_adapter *i2c, const struct e4000_config *cfg)
+{
+       struct e4000_priv *priv;
+       int ret;
+       u8 chip_id;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       priv = kzalloc(sizeof(struct e4000_priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
+               goto err;
+       }
+
+       priv->cfg = cfg;
+       priv->i2c = i2c;
+
+       /* check if the tuner is there */
+       ret = e4000_rd_reg(priv, 0x02, &chip_id);
+       if (ret < 0)
+               goto err;
+
+       dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+
+       if (chip_id != 0x40)
+               goto err;
+
+       /* put sleep as chip seems to be in normal mode by default */
+       ret = e4000_wr_reg(priv, 0x00, 0x00);
+       if (ret < 0)
+               goto err;
+
+       dev_info(&priv->i2c->dev,
+                       "%s: Elonics E4000 successfully identified\n",
+                       KBUILD_MODNAME);
+
+       fe->tuner_priv = priv;
+       memcpy(&fe->ops.tuner_ops, &e4000_tuner_ops,
+                       sizeof(struct dvb_tuner_ops));
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return fe;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+       kfree(priv);
+       return NULL;
+}
+EXPORT_SYMBOL(e4000_attach);
+
+MODULE_DESCRIPTION("Elonics E4000 silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/e4000.h b/drivers/media/tuners/e4000.h
new file mode 100644 (file)
index 0000000..71b1935
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * Elonics E4000 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef E4000_H
+#define E4000_H
+
+#include "dvb_frontend.h"
+
+struct e4000_config {
+       /*
+        * I2C address
+        * 0x64, 0x65, 0x66, 0x67
+        */
+       u8 i2c_addr;
+
+       /*
+        * clock
+        */
+       u32 clock;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_E4000) || \
+       (defined(CONFIG_MEDIA_TUNER_E4000_MODULE) && defined(MODULE))
+extern struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
+               struct i2c_adapter *i2c, const struct e4000_config *cfg);
+#else
+static inline struct dvb_frontend *e4000_attach(struct dvb_frontend *fe,
+               struct i2c_adapter *i2c, const struct e4000_config *cfg)
+{
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/tuners/e4000_priv.h b/drivers/media/tuners/e4000_priv.h
new file mode 100644 (file)
index 0000000..a385505
--- /dev/null
@@ -0,0 +1,147 @@
+/*
+ * Elonics E4000 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef E4000_PRIV_H
+#define E4000_PRIV_H
+
+#include "e4000.h"
+
+struct e4000_priv {
+       const struct e4000_config *cfg;
+       struct i2c_adapter *i2c;
+};
+
+struct e4000_pll {
+       u32 freq;
+       u8 div;
+       u8 mul;
+};
+
+static const struct e4000_pll e4000_pll_lut[] = {
+/*                                      VCO min    VCO max */
+       {   72400000, 0x0f, 48 }, /* .......... 3475200000 */
+       {   81200000, 0x0e, 40 }, /* 2896000000 3248000000 */
+       {  108300000, 0x0d, 32 }, /* 2598400000 3465600000 */
+       {  162500000, 0x0c, 24 }, /* 2599200000 3900000000 */
+       {  216600000, 0x0b, 16 }, /* 2600000000 3465600000 */
+       {  325000000, 0x0a, 12 }, /* 2599200000 3900000000 */
+       {  350000000, 0x09,  8 }, /* 2600000000 2800000000 */
+       {  432000000, 0x03,  8 }, /* 2800000000 3456000000 */
+       {  667000000, 0x02,  6 }, /* 2592000000 4002000000 */
+       { 1200000000, 0x01,  4 }, /* 2668000000 4800000000 */
+       { 0xffffffff, 0x00,  2 }, /* 2400000000 .......... */
+};
+
+struct e4000_lna_filter {
+       u32 freq;
+       u8 val;
+};
+
+static const struct e4000_lna_filter e400_lna_filter_lut[] = {
+       {  370000000,  0 },
+       {  392500000,  1 },
+       {  415000000,  2 },
+       {  437500000,  3 },
+       {  462500000,  4 },
+       {  490000000,  5 },
+       {  522500000,  6 },
+       {  557500000,  7 },
+       {  595000000,  8 },
+       {  642500000,  9 },
+       {  695000000, 10 },
+       {  740000000, 11 },
+       {  800000000, 12 },
+       {  865000000, 13 },
+       {  930000000, 14 },
+       { 1000000000, 15 },
+       { 1310000000,  0 },
+       { 1340000000,  1 },
+       { 1385000000,  2 },
+       { 1427500000,  3 },
+       { 1452500000,  4 },
+       { 1475000000,  5 },
+       { 1510000000,  6 },
+       { 1545000000,  7 },
+       { 1575000000,  8 },
+       { 1615000000,  9 },
+       { 1650000000, 10 },
+       { 1670000000, 11 },
+       { 1690000000, 12 },
+       { 1710000000, 13 },
+       { 1735000000, 14 },
+       { 0xffffffff, 15 },
+};
+
+struct e4000_band {
+       u32 freq;
+       u8 reg07_val;
+       u8 reg78_val;
+};
+
+static const struct e4000_band e4000_band_lut[] = {
+       {  140000000, 0x01, 0x03 },
+       {  350000000, 0x03, 0x03 },
+       { 1000000000, 0x05, 0x03 },
+       { 0xffffffff, 0x07, 0x00 },
+};
+
+struct e4000_if_filter {
+       u32 freq;
+       u8 reg11_val;
+       u8 reg12_val;
+};
+
+static const struct e4000_if_filter e4000_if_filter_lut[] = {
+       {    4300000, 0xfd, 0x1f },
+       {    4400000, 0xfd, 0x1e },
+       {    4480000, 0xfc, 0x1d },
+       {    4560000, 0xfc, 0x1c },
+       {    4600000, 0xfc, 0x1b },
+       {    4800000, 0xfc, 0x1a },
+       {    4900000, 0xfc, 0x19 },
+       {    5000000, 0xfc, 0x18 },
+       {    5100000, 0xfc, 0x17 },
+       {    5200000, 0xfc, 0x16 },
+       {    5400000, 0xfc, 0x15 },
+       {    5500000, 0xfc, 0x14 },
+       {    5600000, 0xfc, 0x13 },
+       {    5800000, 0xfb, 0x12 },
+       {    5900000, 0xfb, 0x11 },
+       {    6000000, 0xfb, 0x10 },
+       {    6200000, 0xfb, 0x0f },
+       {    6400000, 0xfa, 0x0e },
+       {    6600000, 0xfa, 0x0d },
+       {    6800000, 0xf9, 0x0c },
+       {    7200000, 0xf9, 0x0b },
+       {    7400000, 0xf9, 0x0a },
+       {    7600000, 0xf8, 0x09 },
+       {    7800000, 0xf8, 0x08 },
+       {    8200000, 0xf8, 0x07 },
+       {    8600000, 0xf7, 0x06 },
+       {    8800000, 0xf7, 0x05 },
+       {    9200000, 0xf7, 0x04 },
+       {    9600000, 0xf6, 0x03 },
+       {   10000000, 0xf6, 0x02 },
+       {   10600000, 0xf5, 0x01 },
+       {   11000000, 0xf5, 0x00 },
+       { 0xffffffff, 0x00, 0x20 },
+};
+
+#endif
diff --git a/drivers/media/tuners/fc2580.c b/drivers/media/tuners/fc2580.c
new file mode 100644 (file)
index 0000000..aff39ae
--- /dev/null
@@ -0,0 +1,529 @@
+/*
+ * FCI FC2580 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "fc2580_priv.h"
+
+/*
+ * TODO:
+ * I2C write and read works only for one single register. Multiple registers
+ * could not be accessed using normal register address auto-increment.
+ * There could be (very likely) register to change that behavior....
+ *
+ * Due to that limitation functions:
+ *   fc2580_wr_regs()
+ *   fc2580_rd_regs()
+ * could not be used for accessing more than one register at once.
+ *
+ * TODO:
+ * Currently it blind writes bunch of static registers from the
+ * fc2580_freq_regs_lut[] when fc2580_set_params() is called. Add some
+ * logic to reduce unneeded register writes.
+ * There is also don't-care registers, initialized with value 0xff, and those
+ * are also written to the chip currently (yes, not wise).
+ */
+
+/* write multiple registers */
+static int fc2580_wr_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[1 + len];
+       struct i2c_msg msg[1] = {
+               {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = 0,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       buf[0] = reg;
+       memcpy(&buf[1], val, len);
+
+       ret = i2c_transfer(priv->i2c, msg, 1);
+       if (ret == 1) {
+               ret = 0;
+       } else {
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+       return ret;
+}
+
+/* read multiple registers */
+static int fc2580_rd_regs(struct fc2580_priv *priv, u8 reg, u8 *val, int len)
+{
+       int ret;
+       u8 buf[len];
+       struct i2c_msg msg[2] = {
+               {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = 0,
+                       .len = 1,
+                       .buf = &reg,
+               }, {
+                       .addr = priv->cfg->i2c_addr,
+                       .flags = I2C_M_RD,
+                       .len = sizeof(buf),
+                       .buf = buf,
+               }
+       };
+
+       ret = i2c_transfer(priv->i2c, msg, 2);
+       if (ret == 2) {
+               memcpy(val, buf, len);
+               ret = 0;
+       } else {
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
+               ret = -EREMOTEIO;
+       }
+
+       return ret;
+}
+
+/* write single register */
+static int fc2580_wr_reg(struct fc2580_priv *priv, u8 reg, u8 val)
+{
+       return fc2580_wr_regs(priv, reg, &val, 1);
+}
+
+/* read single register */
+static int fc2580_rd_reg(struct fc2580_priv *priv, u8 reg, u8 *val)
+{
+       return fc2580_rd_regs(priv, reg, val, 1);
+}
+
+static int fc2580_set_params(struct dvb_frontend *fe)
+{
+       struct fc2580_priv *priv = fe->tuner_priv;
+       struct dtv_frontend_properties *c = &fe->dtv_property_cache;
+       int ret = 0, i;
+       unsigned int r_val, n_val, k_val, k_val_reg, f_ref;
+       u8 tmp_val, r18_val;
+       u64 f_vco;
+
+       /*
+        * Fractional-N synthesizer/PLL.
+        * Most likely all those PLL calculations are not correct. I am not
+        * sure, but it looks like it is divider based Fractional-N synthesizer.
+        * There is divider for reference clock too?
+        * Anyhow, synthesizer calculation results seems to be quite correct.
+        */
+
+       dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
+                       "bandwidth_hz=%d\n", __func__,
+                       c->delivery_system, c->frequency, c->bandwidth_hz);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       /* PLL */
+       for (i = 0; i < ARRAY_SIZE(fc2580_pll_lut); i++) {
+               if (c->frequency <= fc2580_pll_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(fc2580_pll_lut))
+               goto err;
+
+       f_vco = c->frequency;
+       f_vco *= fc2580_pll_lut[i].div;
+
+       if (f_vco >= 2600000000UL)
+               tmp_val = 0x0e | fc2580_pll_lut[i].band;
+       else
+               tmp_val = 0x06 | fc2580_pll_lut[i].band;
+
+       ret = fc2580_wr_reg(priv, 0x02, tmp_val);
+       if (ret < 0)
+               goto err;
+
+       if (f_vco >= 2UL * 76 * priv->cfg->clock) {
+               r_val = 1;
+               r18_val = 0x00;
+       } else if (f_vco >= 1UL * 76 * priv->cfg->clock) {
+               r_val = 2;
+               r18_val = 0x10;
+       } else {
+               r_val = 4;
+               r18_val = 0x20;
+       }
+
+       f_ref = 2UL * priv->cfg->clock / r_val;
+       n_val = div_u64_rem(f_vco, f_ref, &k_val);
+       k_val_reg = 1UL * k_val * (1 << 20) / f_ref;
+
+       ret = fc2580_wr_reg(priv, 0x18, r18_val | ((k_val_reg >> 16) & 0xff));
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x1a, (k_val_reg >> 8) & 0xff);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x1b, (k_val_reg >> 0) & 0xff);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x1c, n_val);
+       if (ret < 0)
+               goto err;
+
+       if (priv->cfg->clock >= 28000000) {
+               ret = fc2580_wr_reg(priv, 0x4b, 0x22);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (fc2580_pll_lut[i].band == 0x00) {
+               if (c->frequency <= 794000000)
+                       tmp_val = 0x9f;
+               else
+                       tmp_val = 0x8f;
+
+               ret = fc2580_wr_reg(priv, 0x2d, tmp_val);
+               if (ret < 0)
+                       goto err;
+       }
+
+       /* registers */
+       for (i = 0; i < ARRAY_SIZE(fc2580_freq_regs_lut); i++) {
+               if (c->frequency <= fc2580_freq_regs_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(fc2580_freq_regs_lut))
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x25, fc2580_freq_regs_lut[i].r25_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x27, fc2580_freq_regs_lut[i].r27_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x28, fc2580_freq_regs_lut[i].r28_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x29, fc2580_freq_regs_lut[i].r29_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x2b, fc2580_freq_regs_lut[i].r2b_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x2c, fc2580_freq_regs_lut[i].r2c_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x2d, fc2580_freq_regs_lut[i].r2d_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x30, fc2580_freq_regs_lut[i].r30_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x44, fc2580_freq_regs_lut[i].r44_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x50, fc2580_freq_regs_lut[i].r50_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x53, fc2580_freq_regs_lut[i].r53_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x5f, fc2580_freq_regs_lut[i].r5f_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x61, fc2580_freq_regs_lut[i].r61_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x62, fc2580_freq_regs_lut[i].r62_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x63, fc2580_freq_regs_lut[i].r63_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x67, fc2580_freq_regs_lut[i].r67_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x68, fc2580_freq_regs_lut[i].r68_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x69, fc2580_freq_regs_lut[i].r69_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6a, fc2580_freq_regs_lut[i].r6a_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6b, fc2580_freq_regs_lut[i].r6b_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6c, fc2580_freq_regs_lut[i].r6c_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6d, fc2580_freq_regs_lut[i].r6d_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6e, fc2580_freq_regs_lut[i].r6e_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x6f, fc2580_freq_regs_lut[i].r6f_val);
+       if (ret < 0)
+               goto err;
+
+       /* IF filters */
+       for (i = 0; i < ARRAY_SIZE(fc2580_if_filter_lut); i++) {
+               if (c->bandwidth_hz <= fc2580_if_filter_lut[i].freq)
+                       break;
+       }
+
+       if (i == ARRAY_SIZE(fc2580_if_filter_lut))
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x36, fc2580_if_filter_lut[i].r36_val);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x37, 1UL * priv->cfg->clock * \
+                       fc2580_if_filter_lut[i].mul / 1000000000);
+       if (ret < 0)
+               goto err;
+
+       ret = fc2580_wr_reg(priv, 0x39, fc2580_if_filter_lut[i].r39_val);
+       if (ret < 0)
+               goto err;
+
+       /* calibration? */
+       ret = fc2580_wr_reg(priv, 0x2e, 0x09);
+       if (ret < 0)
+               goto err;
+
+       for (i = 0; i < 5; i++) {
+               ret = fc2580_rd_reg(priv, 0x2f, &tmp_val);
+               if (ret < 0)
+                       goto err;
+
+               /* done when [7:6] are set */
+               if ((tmp_val & 0xc0) == 0xc0)
+                       break;
+
+               ret = fc2580_wr_reg(priv, 0x2e, 0x01);
+               if (ret < 0)
+                       goto err;
+
+               ret = fc2580_wr_reg(priv, 0x2e, 0x09);
+               if (ret < 0)
+                       goto err;
+
+               usleep_range(5000, 25000);
+       }
+
+       dev_dbg(&priv->i2c->dev, "%s: loop=%i\n", __func__, i);
+
+       ret = fc2580_wr_reg(priv, 0x2e, 0x01);
+       if (ret < 0)
+               goto err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int fc2580_init(struct dvb_frontend *fe)
+{
+       struct fc2580_priv *priv = fe->tuner_priv;
+       int ret, i;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       for (i = 0; i < ARRAY_SIZE(fc2580_init_reg_vals); i++) {
+               ret = fc2580_wr_reg(priv, fc2580_init_reg_vals[i].reg,
+                               fc2580_init_reg_vals[i].val);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int fc2580_sleep(struct dvb_frontend *fe)
+{
+       struct fc2580_priv *priv = fe->tuner_priv;
+       int ret;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       ret = fc2580_wr_reg(priv, 0x02, 0x0a);
+       if (ret < 0)
+               goto err;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return 0;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int fc2580_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct fc2580_priv *priv = fe->tuner_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       *frequency = 0; /* Zero-IF */
+
+       return 0;
+}
+
+static int fc2580_release(struct dvb_frontend *fe)
+{
+       struct fc2580_priv *priv = fe->tuner_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       kfree(fe->tuner_priv);
+
+       return 0;
+}
+
+static const struct dvb_tuner_ops fc2580_tuner_ops = {
+       .info = {
+               .name           = "FCI FC2580",
+               .frequency_min  = 174000000,
+               .frequency_max  = 862000000,
+       },
+
+       .release = fc2580_release,
+
+       .init = fc2580_init,
+       .sleep = fc2580_sleep,
+       .set_params = fc2580_set_params,
+
+       .get_if_frequency = fc2580_get_if_frequency,
+};
+
+struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
+               struct i2c_adapter *i2c, const struct fc2580_config *cfg)
+{
+       struct fc2580_priv *priv;
+       int ret;
+       u8 chip_id;
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 1);
+
+       priv = kzalloc(sizeof(struct fc2580_priv), GFP_KERNEL);
+       if (!priv) {
+               ret = -ENOMEM;
+               dev_err(&i2c->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
+               goto err;
+       }
+
+       priv->cfg = cfg;
+       priv->i2c = i2c;
+
+       /* check if the tuner is there */
+       ret = fc2580_rd_reg(priv, 0x01, &chip_id);
+       if (ret < 0)
+               goto err;
+
+       dev_dbg(&priv->i2c->dev, "%s: chip_id=%02x\n", __func__, chip_id);
+
+       switch (chip_id) {
+       case 0x56:
+       case 0x5a:
+               break;
+       default:
+               goto err;
+       }
+
+       dev_info(&priv->i2c->dev,
+                       "%s: FCI FC2580 successfully identified\n",
+                       KBUILD_MODNAME);
+
+       fe->tuner_priv = priv;
+       memcpy(&fe->ops.tuner_ops, &fc2580_tuner_ops,
+                       sizeof(struct dvb_tuner_ops));
+
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       return fe;
+err:
+       if (fe->ops.i2c_gate_ctrl)
+               fe->ops.i2c_gate_ctrl(fe, 0);
+
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+       kfree(priv);
+       return NULL;
+}
+EXPORT_SYMBOL(fc2580_attach);
+
+MODULE_DESCRIPTION("FCI FC2580 silicon tuner driver");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/tuners/fc2580.h b/drivers/media/tuners/fc2580.h
new file mode 100644 (file)
index 0000000..222601e
--- /dev/null
@@ -0,0 +1,52 @@
+/*
+ * FCI FC2580 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FC2580_H
+#define FC2580_H
+
+#include "dvb_frontend.h"
+
+struct fc2580_config {
+       /*
+        * I2C address
+        * 0x56, ...
+        */
+       u8 i2c_addr;
+
+       /*
+        * clock
+        */
+       u32 clock;
+};
+
+#if defined(CONFIG_MEDIA_TUNER_FC2580) || \
+       (defined(CONFIG_MEDIA_TUNER_FC2580_MODULE) && defined(MODULE))
+extern struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, const struct fc2580_config *cfg);
+#else
+static inline struct dvb_frontend *fc2580_attach(struct dvb_frontend *fe,
+       struct i2c_adapter *i2c, const struct fc2580_config *cfg)
+{
+       pr_warn("%s: driver disabled by Kconfig\n", __func__);
+       return NULL;
+}
+#endif
+
+#endif
diff --git a/drivers/media/tuners/fc2580_priv.h b/drivers/media/tuners/fc2580_priv.h
new file mode 100644 (file)
index 0000000..be38a9e
--- /dev/null
@@ -0,0 +1,134 @@
+/*
+ * FCI FC2580 silicon tuner driver
+ *
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef FC2580_PRIV_H
+#define FC2580_PRIV_H
+
+#include "fc2580.h"
+
+struct fc2580_reg_val {
+       u8 reg;
+       u8 val;
+};
+
+static const struct fc2580_reg_val fc2580_init_reg_vals[] = {
+       {0x00, 0x00},
+       {0x12, 0x86},
+       {0x14, 0x5c},
+       {0x16, 0x3c},
+       {0x1f, 0xd2},
+       {0x09, 0xd7},
+       {0x0b, 0xd5},
+       {0x0c, 0x32},
+       {0x0e, 0x43},
+       {0x21, 0x0a},
+       {0x22, 0x82},
+       {0x45, 0x10},
+       {0x4c, 0x00},
+       {0x3f, 0x88},
+       {0x02, 0x0e},
+       {0x58, 0x14},
+};
+
+struct fc2580_pll {
+       u32 freq;
+       u8 div;
+       u8 band;
+};
+
+static const struct fc2580_pll fc2580_pll_lut[] = {
+       /*                            VCO min    VCO max */
+       { 400000000, 12, 0x80}, /* .......... 4800000000 */
+       {1000000000,  4, 0x00}, /* 1600000000 4000000000 */
+       {0xffffffff,  2, 0x40}, /* 2000000000 .......... */
+};
+
+struct fc2580_if_filter {
+       u32 freq;
+       u16 mul;
+       u8 r36_val;
+       u8 r39_val;
+};
+
+static const struct fc2580_if_filter fc2580_if_filter_lut[] = {
+       {   6000000, 4400, 0x18, 0x00},
+       {   7000000, 3910, 0x18, 0x80},
+       {   8000000, 3300, 0x18, 0x80},
+       {0xffffffff, 3300, 0x18, 0x80},
+};
+
+struct fc2580_freq_regs {
+       u32 freq;
+       u8 r25_val;
+       u8 r27_val;
+       u8 r28_val;
+       u8 r29_val;
+       u8 r2b_val;
+       u8 r2c_val;
+       u8 r2d_val;
+       u8 r30_val;
+       u8 r44_val;
+       u8 r50_val;
+       u8 r53_val;
+       u8 r5f_val;
+       u8 r61_val;
+       u8 r62_val;
+       u8 r63_val;
+       u8 r67_val;
+       u8 r68_val;
+       u8 r69_val;
+       u8 r6a_val;
+       u8 r6b_val;
+       u8 r6c_val;
+       u8 r6d_val;
+       u8 r6e_val;
+       u8 r6f_val;
+};
+
+/* XXX: 0xff is used for don't-care! */
+static const struct fc2580_freq_regs fc2580_freq_regs_lut[] = {
+       { 400000000,
+               0xff, 0x77, 0x33, 0x40, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+               0x50, 0x0f, 0x07, 0x00, 0x15, 0x03, 0x05, 0x10, 0x12, 0x08,
+               0x0a, 0x78, 0x32, 0x54},
+       { 538000000,
+               0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+               0x50, 0x13, 0x07, 0x06, 0x15, 0x06, 0x08, 0x10, 0x12, 0x0b,
+               0x0c, 0x78, 0x32, 0x14},
+       { 794000000,
+               0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+               0x50, 0x15, 0x03, 0x03, 0x15, 0x03, 0x05, 0x0c, 0x0e, 0x0b,
+               0x0c, 0x78, 0x32, 0x14},
+       {1000000000,
+               0xf0, 0x77, 0x53, 0x60, 0xff, 0xff, 0xff, 0x09, 0xff, 0x8c,
+               0x50, 0x15, 0x07, 0x06, 0x15, 0x07, 0x09, 0x10, 0x12, 0x0b,
+               0x0c, 0x78, 0x32, 0x14},
+       {0xffffffff,
+               0xff, 0xff, 0xff, 0xff, 0x70, 0x37, 0xe7, 0x09, 0x20, 0x8c,
+               0x50, 0x0f, 0x0f, 0x00, 0x13, 0x00, 0x02, 0x0c, 0x0e, 0x08,
+               0x0a, 0xa0, 0x50, 0x14},
+};
+
+struct fc2580_priv {
+       const struct fc2580_config *cfg;
+       struct i2c_adapter *i2c;
+};
+
+#endif
similarity index 97%
rename from drivers/media/common/tuners/mc44s803.c
rename to drivers/media/tuners/mc44s803.c
index 5ddce7e326f743043d8cdaa87c5c1f3ca8c079d4..f1b76407466102950f75893f8cd3533a714595e4 100644 (file)
@@ -298,6 +298,12 @@ static int mc44s803_get_frequency(struct dvb_frontend *fe, u32 *frequency)
        return 0;
 }
 
+static int mc44s803_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       *frequency = MC44S803_IF2; /* 36.125 MHz */
+       return 0;
+}
+
 static const struct dvb_tuner_ops mc44s803_tuner_ops = {
        .info = {
                .name           = "Freescale MC44S803",
@@ -309,7 +315,8 @@ static const struct dvb_tuner_ops mc44s803_tuner_ops = {
        .release       = mc44s803_release,
        .init          = mc44s803_init,
        .set_params    = mc44s803_set_params,
-       .get_frequency = mc44s803_get_frequency
+       .get_frequency = mc44s803_get_frequency,
+       .get_if_frequency = mc44s803_get_if_frequency,
 };
 
 /* This functions tries to identify a MC44S803 tuner by reading the ID
similarity index 99%
rename from drivers/media/common/tuners/mxl5005s.c
rename to drivers/media/tuners/mxl5005s.c
index 6133315fb0e34ed5b48ba5e26c2bc48e249d8722..b473b76cb278b52f316cdb6249cba5da667e7d41 100644 (file)
@@ -4054,6 +4054,16 @@ static int mxl5005s_get_bandwidth(struct dvb_frontend *fe, u32 *bandwidth)
        return 0;
 }
 
+static int mxl5005s_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
+{
+       struct mxl5005s_state *state = fe->tuner_priv;
+       dprintk(1, "%s()\n", __func__);
+
+       *frequency = state->IF_OUT;
+
+       return 0;
+}
+
 static int mxl5005s_release(struct dvb_frontend *fe)
 {
        dprintk(1, "%s()\n", __func__);
@@ -4076,6 +4086,7 @@ static const struct dvb_tuner_ops mxl5005s_tuner_ops = {
        .set_params    = mxl5005s_set_params,
        .get_frequency = mxl5005s_get_frequency,
        .get_bandwidth = mxl5005s_get_bandwidth,
+       .get_if_frequency = mxl5005s_get_if_frequency,
 };
 
 struct dvb_frontend *mxl5005s_attach(struct dvb_frontend *fe,
similarity index 90%
rename from drivers/media/common/tuners/qt1010.c
rename to drivers/media/tuners/qt1010.c
index 2d79b1f5d5ebcebe9a00321ee278239ca64d0a7f..bc419f8a967152d02caf0bc11cb9491753b649a4 100644 (file)
 #include "qt1010.h"
 #include "qt1010_priv.h"
 
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
-#define dprintk(args...) \
-       do { \
-               if (debug) printk(KERN_DEBUG "QT1010: " args); \
-       } while (0)
-
 /* read single register */
 static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
 {
@@ -41,7 +32,8 @@ static int qt1010_readreg(struct qt1010_priv *priv, u8 reg, u8 *val)
        };
 
        if (i2c_transfer(priv->i2c, msg, 2) != 2) {
-               printk(KERN_WARNING "qt1010 I2C read failed\n");
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed reg=%02x\n",
+                               KBUILD_MODNAME, reg);
                return -EREMOTEIO;
        }
        return 0;
@@ -55,33 +47,13 @@ static int qt1010_writereg(struct qt1010_priv *priv, u8 reg, u8 val)
                               .flags = 0, .buf = buf, .len = 2 };
 
        if (i2c_transfer(priv->i2c, &msg, 1) != 1) {
-               printk(KERN_WARNING "qt1010 I2C write failed\n");
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed reg=%02x\n",
+                               KBUILD_MODNAME, reg);
                return -EREMOTEIO;
        }
        return 0;
 }
 
-/* dump all registers */
-static void qt1010_dump_regs(struct qt1010_priv *priv)
-{
-       u8 reg, val;
-
-       for (reg = 0; ; reg++) {
-               if (reg % 16 == 0) {
-                       if (reg)
-                               printk(KERN_CONT "\n");
-                       printk(KERN_DEBUG "%02x:", reg);
-               }
-               if (qt1010_readreg(priv, reg, &val) == 0)
-                       printk(KERN_CONT " %02x", val);
-               else
-                       printk(KERN_CONT " --");
-               if (reg == 0x2f)
-                       break;
-       }
-       printk(KERN_CONT "\n");
-}
-
 static int qt1010_set_params(struct dvb_frontend *fe)
 {
        struct dtv_frontend_properties *c = &fe->dtv_property_cache;
@@ -229,12 +201,14 @@ static int qt1010_set_params(struct dvb_frontend *fe)
        /* 00 */
        rd[45].val = 0x92; /* TODO: correct value calculation */
 
-       dprintk("freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
-               "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
-               "20:%02x 25:%02x 00:%02x", \
-               freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, rd[8].val, \
-               rd[10].val, rd[13].val, rd[14].val, rd[15].val, rd[35].val, \
-               rd[40].val, rd[41].val, rd[43].val, rd[45].val);
+       dev_dbg(&priv->i2c->dev,
+                       "%s: freq:%u 05:%02x 07:%02x 09:%02x 0a:%02x 0b:%02x " \
+                       "1a:%02x 11:%02x 12:%02x 22:%02x 05:%02x 1f:%02x " \
+                       "20:%02x 25:%02x 00:%02x\n", __func__, \
+                       freq, rd[2].val, rd[4].val, rd[6].val, rd[7].val, \
+                       rd[8].val, rd[10].val, rd[13].val, rd[14].val, \
+                       rd[15].val, rd[35].val, rd[40].val, rd[41].val, \
+                       rd[43].val, rd[45].val);
 
        for (i = 0; i < ARRAY_SIZE(rd); i++) {
                if (rd[i].oper == QT1010_WR) {
@@ -245,9 +219,6 @@ static int qt1010_set_params(struct dvb_frontend *fe)
                if (err) return err;
        }
 
-       if (debug)
-               qt1010_dump_regs(priv);
-
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 
@@ -281,14 +252,15 @@ static int qt1010_init_meas1(struct qt1010_priv *priv,
                val1 = val2;
                err = qt1010_readreg(priv, reg, &val2);
                if (err) return err;
-               dprintk("compare reg:%02x %02x %02x", reg, val1, val2);
+               dev_dbg(&priv->i2c->dev, "%s: compare reg:%02x %02x %02x\n",
+                               __func__, reg, val1, val2);
        } while (val1 != val2);
        *retval = val1;
 
        return qt1010_writereg(priv, 0x1e, 0x00);
 }
 
-static u8 qt1010_init_meas2(struct qt1010_priv *priv,
+static int qt1010_init_meas2(struct qt1010_priv *priv,
                            u8 reg_init_val, u8 *retval)
 {
        u8 i, val;
@@ -395,7 +367,8 @@ static int qt1010_init(struct dvb_frontend *fe)
                if ((err = qt1010_init_meas2(priv, i, &tmpval)))
                        return err;
 
-       c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
+       if (!c->frequency)
+               c->frequency = 545000000; /* Sigmatek DVB-110 545000000 */
                                      /* MSI Megasky 580 GL861 533000000 */
        return qt1010_set_params(fe);
 }
@@ -464,7 +437,10 @@ struct dvb_frontend * qt1010_attach(struct dvb_frontend *fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c_gate */
 
-       printk(KERN_INFO "Quantek QT1010 successfully identified.\n");
+       dev_info(&priv->i2c->dev,
+                       "%s: Quantek QT1010 successfully identified\n",
+                       KBUILD_MODNAME);
+
        memcpy(&fe->ops.tuner_ops, &qt1010_tuner_ops,
               sizeof(struct dvb_tuner_ops));
 
similarity index 91%
rename from drivers/media/common/tuners/tda18212.c
rename to drivers/media/tuners/tda18212.c
index 602c2e392b178c255a2d6fa476b8b2fa439f45d0..5d9f028425012e75ee7edefe97c149fb9f415df6 100644 (file)
@@ -18,8 +18,6 @@
  *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
-#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
-
 #include "tda18212.h"
 
 struct tda18212_priv {
@@ -29,16 +27,6 @@ struct tda18212_priv {
        u32 if_frequency;
 };
 
-#define dbg(fmt, arg...)                                       \
-do {                                                           \
-       if (debug)                                              \
-               pr_info("%s: " fmt, __func__, ##arg);           \
-} while (0)
-
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
 /* write multiple registers */
 static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
        int len)
@@ -61,8 +49,8 @@ static int tda18212_wr_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
        if (ret == 1) {
                ret = 0;
        } else {
-               pr_warn("i2c wr failed ret:%d reg:%02x len:%d\n",
-                       ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
        return ret;
@@ -93,8 +81,8 @@ static int tda18212_rd_regs(struct tda18212_priv *priv, u8 reg, u8 *val,
                memcpy(val, buf, len);
                ret = 0;
        } else {
-               pr_warn("i2c rd failed ret:%d reg:%02x len:%d\n",
-                       ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -157,8 +145,10 @@ static int tda18212_set_params(struct dvb_frontend *fe)
                [DVBC_8]  = { 0x92, 0x53, 0x03 },
        };
 
-       dbg("delsys=%d RF=%d BW=%d\n",
-           c->delivery_system, c->frequency, c->bandwidth_hz);
+       dev_dbg(&priv->i2c->dev,
+                       "%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
+                       __func__, c->delivery_system, c->frequency,
+                       c->bandwidth_hz);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1); /* open I2C-gate */
@@ -247,7 +237,7 @@ exit:
        return ret;
 
 error:
-       dbg("failed:%d\n", ret);
+       dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
        goto exit;
 }
 
@@ -287,7 +277,7 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
 {
        struct tda18212_priv *priv = NULL;
        int ret;
-       u8 val;
+       u8 uninitialized_var(val);
 
        priv = kzalloc(sizeof(struct tda18212_priv), GFP_KERNEL);
        if (priv == NULL)
@@ -306,13 +296,16 @@ struct dvb_frontend *tda18212_attach(struct dvb_frontend *fe,
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
-       dbg("ret:%d chip ID:%02x\n", ret, val);
+       dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret,
+                       val);
        if (ret || val != 0xc7) {
                kfree(priv);
                return NULL;
        }
 
-       pr_info("NXP TDA18212HN successfully identified\n");
+       dev_info(&priv->i2c->dev,
+                       "%s: NXP TDA18212HN successfully identified\n",
+                       KBUILD_MODNAME);
 
        memcpy(&fe->ops.tuner_ops, &tda18212_tuner_ops,
                sizeof(struct dvb_tuner_ops));
similarity index 87%
rename from drivers/media/common/tuners/tda18218.c
rename to drivers/media/tuners/tda18218.c
index dfb3a831df4540541757f5b6cc0ce7f23f989cd3..18198537be9f45c9f224947643f9884ac22348db 100644 (file)
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#include "tda18218.h"
 #include "tda18218_priv.h"
 
-static int debug;
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Turn on/off debugging (default:off).");
-
 /* write multiple registers */
 static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
 {
-       int ret = 0;
-       u8 buf[1+len], quotient, remainder, i, msg_len, msg_len_max;
+       int ret = 0, len2, remaining;
+       u8 buf[1 + len];
        struct i2c_msg msg[1] = {
                {
                        .addr = priv->cfg->i2c_address,
@@ -38,17 +33,15 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
                }
        };
 
-       msg_len_max = priv->cfg->i2c_wr_max - 1;
-       quotient = len / msg_len_max;
-       remainder = len % msg_len_max;
-       msg_len = msg_len_max;
-       for (i = 0; (i <= quotient && remainder); i++) {
-               if (i == quotient)  /* set len of the last msg */
-                       msg_len = remainder;
+       for (remaining = len; remaining > 0;
+                       remaining -= (priv->cfg->i2c_wr_max - 1)) {
+               len2 = remaining;
+               if (len2 > (priv->cfg->i2c_wr_max - 1))
+                       len2 = (priv->cfg->i2c_wr_max - 1);
 
-               msg[0].len = msg_len + 1;
-               buf[0] = reg + i * msg_len_max;
-               memcpy(&buf[1], &val[i * msg_len_max], msg_len);
+               msg[0].len = 1 + len2;
+               buf[0] = reg + len - remaining;
+               memcpy(&buf[1], &val[len - remaining], len2);
 
                ret = i2c_transfer(priv->i2c, msg, 1);
                if (ret != 1)
@@ -58,7 +51,8 @@ static int tda18218_wr_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
        if (ret == 1) {
                ret = 0;
        } else {
-               warn("i2c wr failed ret:%d reg:%02x len:%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -89,7 +83,8 @@ static int tda18218_rd_regs(struct tda18218_priv *priv, u8 reg, u8 *val, u8 len)
                memcpy(val, &buf[reg], len);
                ret = 0;
        } else {
-               warn("i2c rd failed ret:%d reg:%02x len:%d", ret, reg, len);
+               dev_warn(&priv->i2c->dev, "%s: i2c rd failed=%d reg=%02x " \
+                               "len=%d\n", KBUILD_MODNAME, ret, reg, len);
                ret = -EREMOTEIO;
        }
 
@@ -199,7 +194,7 @@ error:
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
        if (ret)
-               dbg("%s: failed ret:%d", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -208,7 +203,7 @@ static int tda18218_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
        struct tda18218_priv *priv = fe->tuner_priv;
        *frequency = priv->if_frequency;
-       dbg("%s: if=%d", __func__, *frequency);
+       dev_dbg(&priv->i2c->dev, "%s: if_frequency=%d\n", __func__, *frequency);
        return 0;
 }
 
@@ -227,7 +222,7 @@ static int tda18218_sleep(struct dvb_frontend *fe)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
        if (ret)
-               dbg("%s: failed ret:%d", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -248,7 +243,7 @@ static int tda18218_init(struct dvb_frontend *fe)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
 
        if (ret)
-               dbg("%s: failed ret:%d", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -282,7 +277,7 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
        struct i2c_adapter *i2c, struct tda18218_config *cfg)
 {
        struct tda18218_priv *priv = NULL;
-       u8 val;
+       u8 uninitialized_var(val);
        int ret;
        /* chip default registers values */
        static u8 def_regs[] = {
@@ -307,13 +302,16 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
 
        /* check if the tuner is there */
        ret = tda18218_rd_reg(priv, R00_ID, &val);
-       dbg("%s: ret:%d chip ID:%02x", __func__, ret, val);
+       dev_dbg(&priv->i2c->dev, "%s: ret=%d chip id=%02x\n", __func__, ret,
+                       val);
        if (ret || val != def_regs[R00_ID]) {
                kfree(priv);
                return NULL;
        }
 
-       info("NXP TDA18218HN successfully identified.");
+       dev_info(&priv->i2c->dev,
+                       "%s: NXP TDA18218HN successfully identified\n",
+                       KBUILD_MODNAME);
 
        memcpy(&fe->ops.tuner_ops, &tda18218_tuner_ops,
                sizeof(struct dvb_tuner_ops));
@@ -328,7 +326,7 @@ struct dvb_frontend *tda18218_attach(struct dvb_frontend *fe,
        /* standby */
        ret = tda18218_wr_reg(priv, R17_PD1, priv->regs[R17_PD1] | (1 << 0));
        if (ret)
-               dbg("%s: failed ret:%d", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close I2C-gate */
similarity index 90%
rename from drivers/media/common/tuners/tda18218_priv.h
rename to drivers/media/tuners/tda18218_priv.h
index dc52b72e14071015255cb026354d44e4cf248fc6..285b77366c8d0104c17db0c1a24b5c8cd0ff41d3 100644 (file)
 #ifndef TDA18218_PRIV_H
 #define TDA18218_PRIV_H
 
-#define LOG_PREFIX "tda18218"
-
-#undef dbg
-#define dbg(f, arg...) \
-       if (debug) \
-               printk(KERN_DEBUG   LOG_PREFIX": " f "\n" , ## arg)
-#undef err
-#define err(f, arg...)  printk(KERN_ERR     LOG_PREFIX": " f "\n" , ## arg)
-#undef info
-#define info(f, arg...) printk(KERN_INFO    LOG_PREFIX": " f "\n" , ## arg)
-#undef warn
-#define warn(f, arg...) printk(KERN_WARNING LOG_PREFIX": " f "\n" , ## arg)
+#include "tda18218.h"
 
 #define R00_ID         0x00    /* ID byte */
 #define R01_R1         0x01    /* Read byte 1 */
similarity index 99%
rename from drivers/media/common/tuners/tda18271-common.c
rename to drivers/media/tuners/tda18271-common.c
index 39c645787b628fb47f4d9512fa9bf2d1df72cab7..221171eeb0c32ab8d7e34c036abba3e70789e81b 100644 (file)
@@ -275,7 +275,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        case TDA18271HDC2:
                regs[R_ID]   = 0x84;
                break;
-       };
+       }
 
        regs[R_TM]   = 0x08;
        regs[R_PL]   = 0x80;
@@ -300,7 +300,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        case TDA18271HDC2:
                regs[R_EB1]  = 0xfc;
                break;
-       };
+       }
 
        regs[R_EB2]  = 0x01;
        regs[R_EB3]  = 0x84;
@@ -320,7 +320,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        case TDA18271HDC2:
                regs[R_EB12] = 0x33;
                break;
-       };
+       }
 
        regs[R_EB13] = 0xc1;
        regs[R_EB14] = 0x00;
@@ -335,7 +335,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        case TDA18271HDC2:
                regs[R_EB18] = 0x8c;
                break;
-       };
+       }
 
        regs[R_EB19] = 0x00;
        regs[R_EB20] = 0x20;
@@ -347,7 +347,7 @@ int tda18271_init_regs(struct dvb_frontend *fe)
        case TDA18271HDC2:
                regs[R_EB21] = 0xb3;
                break;
-       };
+       }
 
        regs[R_EB22] = 0x48;
        regs[R_EB23] = 0xb0;
similarity index 98%
rename from drivers/media/common/tuners/tda18271-fe.c
rename to drivers/media/tuners/tda18271-fe.c
index 2e67f44599045e175ba6f0881bbb56bb6c11c578..72c26fd77922883bf029a2b19d0af2ac52194c8b 100644 (file)
@@ -1159,11 +1159,19 @@ static int tda18271_get_id(struct dvb_frontend *fe)
        struct tda18271_priv *priv = fe->tuner_priv;
        unsigned char *regs = priv->tda18271_regs;
        char *name;
+       int ret;
 
        mutex_lock(&priv->lock);
-       tda18271_read_regs(fe);
+       ret = tda18271_read_regs(fe);
        mutex_unlock(&priv->lock);
 
+       if (ret) {
+               tda_info("Error reading device ID @ %d-%04x, bailing out.\n",
+                        i2c_adapter_id(priv->i2c_props.adap),
+                        priv->i2c_props.addr);
+               return -EIO;
+       }
+
        switch (regs[R_ID] & 0x7f) {
        case 3:
                name = "TDA18271HD/C1";
@@ -1278,6 +1286,11 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                if (tda_fail(ret))
                        goto fail;
 
+               /* if delay_cal is set, delay IR & RF calibration until init()
+                * module option 'cal' overrides this delay */
+               if ((cfg->delay_cal) && (!tda18271_need_cal_on_startup(cfg)))
+                       break;
+
                mutex_lock(&priv->lock);
                tda18271_init_regs(fe);
 
@@ -1285,6 +1298,10 @@ struct dvb_frontend *tda18271_attach(struct dvb_frontend *fe, u8 addr,
                    (priv->id == TDA18271HDC2))
                        tda18271c2_rf_cal_init(fe);
 
+               /* enter standby mode, with required output features enabled */
+               ret = tda18271_toggle_output(fe, 1);
+               tda_fail(ret);
+
                mutex_unlock(&priv->lock);
                break;
        default:
similarity index 95%
rename from drivers/media/common/tuners/tda18271.h
rename to drivers/media/tuners/tda18271.h
index 640bae4e6a5a85c6db5274e9654b1d02f61c419b..89b6c6d93fec75936072b4cdd2a9fd11a376420b 100644 (file)
@@ -105,6 +105,11 @@ struct tda18271_config {
        /* force rf tracking filter calibration on startup */
        unsigned int rf_cal_on_startup:1;
 
+       /* prevent any register access during attach(),
+        * delaying both IR & RF calibration until init()
+        * module option 'cal' overrides this delay */
+       unsigned int delay_cal:1;
+
        /* interface to saa713x / tda829x */
        unsigned int config;
 };
similarity index 65%
rename from drivers/media/common/tuners/tua9001.c
rename to drivers/media/tuners/tua9001.c
index de2607084672f813287a40bb7a916aea5a0403fe..389668474070cb045ceeabbf67c856a0d6980126 100644 (file)
@@ -39,8 +39,8 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
        if (ret == 1) {
                ret = 0;
        } else {
-               printk(KERN_WARNING "%s: I2C wr failed=%d reg=%02x\n",
-                               __func__, ret, reg);
+               dev_warn(&priv->i2c->dev, "%s: i2c wr failed=%d reg=%02x\n",
+                               KBUILD_MODNAME, ret, reg);
                ret = -EREMOTEIO;
        }
 
@@ -49,10 +49,19 @@ static int tua9001_wr_reg(struct tua9001_priv *priv, u8 reg, u16 val)
 
 static int tua9001_release(struct dvb_frontend *fe)
 {
+       struct tua9001_priv *priv = fe->tuner_priv;
+       int ret = 0;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->callback)
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_CEN, 0);
+
        kfree(fe->tuner_priv);
        fe->tuner_priv = NULL;
 
-       return 0;
+       return ret;
 }
 
 static int tua9001_init(struct dvb_frontend *fe)
@@ -78,20 +87,47 @@ static int tua9001_init(struct dvb_frontend *fe)
                { 0x34, 0x0a40 },
        };
 
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->callback) {
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RESETN, 0);
+               if (ret < 0)
+                       goto err;
+       }
+
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
 
        for (i = 0; i < ARRAY_SIZE(data); i++) {
                ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
-               if (ret)
-                       break;
+               if (ret < 0)
+                       goto err_i2c_gate_ctrl;
        }
 
+err_i2c_gate_ctrl:
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
+err:
+       if (ret < 0)
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
+
+       return ret;
+}
+
+static int tua9001_sleep(struct dvb_frontend *fe)
+{
+       struct tua9001_priv *priv = fe->tuner_priv;
+       int ret = 0;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
+       if (fe->callback)
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RESETN, 1);
 
        if (ret < 0)
-               pr_debug("%s: failed=%d\n", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -105,9 +141,9 @@ static int tua9001_set_params(struct dvb_frontend *fe)
        u32 frequency;
        struct reg_val data[2];
 
-       pr_debug("%s: delivery_system=%d frequency=%d bandwidth_hz=%d\n",
-                       __func__, c->delivery_system, c->frequency,
-                       c->bandwidth_hz);
+       dev_dbg(&priv->i2c->dev, "%s: delivery_system=%d frequency=%d " \
+                       "bandwidth_hz=%d\n", __func__,
+                       c->delivery_system, c->frequency, c->bandwidth_hz);
 
        switch (c->delivery_system) {
        case SYS_DVBT:
@@ -148,24 +184,42 @@ static int tua9001_set_params(struct dvb_frontend *fe)
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 1); /* open i2c-gate */
 
+       if (fe->callback) {
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RXEN, 0);
+               if (ret < 0)
+                       goto err_i2c_gate_ctrl;
+       }
+
        for (i = 0; i < ARRAY_SIZE(data); i++) {
                ret = tua9001_wr_reg(priv, data[i].reg, data[i].val);
                if (ret < 0)
-                       break;
+                       goto err_i2c_gate_ctrl;
+       }
+
+       if (fe->callback) {
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RXEN, 1);
+               if (ret < 0)
+                       goto err_i2c_gate_ctrl;
        }
 
+err_i2c_gate_ctrl:
        if (fe->ops.i2c_gate_ctrl)
                fe->ops.i2c_gate_ctrl(fe, 0); /* close i2c-gate */
-
 err:
        if (ret < 0)
-               pr_debug("%s: failed=%d\n", __func__, ret);
+               dev_dbg(&priv->i2c->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
 static int tua9001_get_if_frequency(struct dvb_frontend *fe, u32 *frequency)
 {
+       struct tua9001_priv *priv = fe->tuner_priv;
+
+       dev_dbg(&priv->i2c->dev, "%s:\n", __func__);
+
        *frequency = 0; /* Zero-IF */
 
        return 0;
@@ -183,6 +237,7 @@ static const struct dvb_tuner_ops tua9001_tuner_ops = {
        .release = tua9001_release,
 
        .init = tua9001_init,
+       .sleep = tua9001_sleep,
        .set_params = tua9001_set_params,
 
        .get_if_frequency = tua9001_get_if_frequency,
@@ -192,6 +247,7 @@ struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
                struct i2c_adapter *i2c, struct tua9001_config *cfg)
 {
        struct tua9001_priv *priv = NULL;
+       int ret;
 
        priv = kzalloc(sizeof(struct tua9001_priv), GFP_KERNEL);
        if (priv == NULL)
@@ -200,13 +256,36 @@ struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
        priv->cfg = cfg;
        priv->i2c = i2c;
 
-       printk(KERN_INFO "Infineon TUA 9001 successfully attached.");
+       if (fe->callback) {
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_CEN, 1);
+               if (ret < 0)
+                       goto err;
+
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RXEN, 0);
+               if (ret < 0)
+                       goto err;
+
+               ret = fe->callback(priv->i2c, DVB_FRONTEND_COMPONENT_TUNER,
+                               TUA9001_CMD_RESETN, 1);
+               if (ret < 0)
+                       goto err;
+       }
+
+       dev_info(&priv->i2c->dev,
+                       "%s: Infineon TUA 9001 successfully attached\n",
+                       KBUILD_MODNAME);
 
        memcpy(&fe->ops.tuner_ops, &tua9001_tuner_ops,
                        sizeof(struct dvb_tuner_ops));
 
        fe->tuner_priv = priv;
        return fe;
+err:
+       dev_dbg(&i2c->dev, "%s: failed=%d\n", __func__, ret);
+       kfree(priv);
+       return NULL;
 }
 EXPORT_SYMBOL(tua9001_attach);
 
similarity index 78%
rename from drivers/media/common/tuners/tua9001.h
rename to drivers/media/tuners/tua9001.h
index 38d6ae76b1d64a2626826fe8821f23b20d52658f..cf5b815feff999f992bab14fb720080395770ebc 100644 (file)
@@ -30,6 +30,26 @@ struct tua9001_config {
        u8 i2c_addr;
 };
 
+/*
+ * TUA9001 I/O PINs:
+ *
+ * CEN - chip enable
+ * 0 = chip disabled (chip off)
+ * 1 = chip enabled (chip on)
+ *
+ * RESETN - chip reset
+ * 0 = reset disabled (chip reset off)
+ * 1 = reset enabled (chip reset on)
+ *
+ * RXEN - RX enable
+ * 0 = RX disabled (chip idle)
+ * 1 = RX enabled (chip tuned)
+ */
+
+#define TUA9001_CMD_CEN     0
+#define TUA9001_CMD_RESETN  1
+#define TUA9001_CMD_RXEN    2
+
 #if defined(CONFIG_MEDIA_TUNER_TUA9001) || \
        (defined(CONFIG_MEDIA_TUNER_TUA9001_MODULE) && defined(MODULE))
 extern struct dvb_frontend *tua9001_attach(struct dvb_frontend *fe,
similarity index 99%
rename from drivers/media/common/tuners/tuner-xc2028.c
rename to drivers/media/tuners/tuner-xc2028.c
index ea0550eafe7d185f9d547a80af33cead4d007050..7bcb6b0ff1dff217bd717c2df46b20fb6e96b932 100644 (file)
@@ -1126,8 +1126,7 @@ static int generic_set_freq(struct dvb_frontend *fe, u32 freq /* in HZ */,
 
        priv->frequency = freq;
 
-       tuner_dbg("divisor= %02x %02x %02x %02x (freq=%d.%03d)\n",
-              buf[0], buf[1], buf[2], buf[3],
+       tuner_dbg("divisor= %*ph (freq=%d.%03d)\n", 4, buf,
               freq / 1000000, (freq % 1000000) / 1000);
 
        rc = 0;
@@ -1414,8 +1413,8 @@ static int xc2028_set_config(struct dvb_frontend *fe, void *priv_cfg)
                        tuner_err("Failed to request firmware %s\n",
                                  priv->fname);
                        priv->state = XC2028_NODEV;
-               }
-               priv->state = XC2028_WAITING_FIRMWARE;
+               } else
+                       priv->state = XC2028_WAITING_FIRMWARE;
        }
        mutex_unlock(&priv->lock);
 
similarity index 99%
rename from drivers/media/common/tuners/xc4000.c
rename to drivers/media/tuners/xc4000.c
index 68397110b7d932fec46c3cdd4ecc0b9d2e99ddf4..4937712278f67757ba114a0f5bfbc9227fc00ab6 100644 (file)
@@ -263,8 +263,7 @@ static int xc_send_i2c_data(struct xc4000_priv *priv, u8 *buf, int len)
                        printk(KERN_ERR "xc4000: I2C write failed (len=%i)\n",
                               len);
                        if (len == 4) {
-                               printk(KERN_ERR "bytes %02x %02x %02x %02x\n", buf[0],
-                                      buf[1], buf[2], buf[3]);
+                               printk(KERN_ERR "bytes %*ph\n", 4, buf);
                        }
                        return -EREMOTEIO;
                }
similarity index 88%
rename from drivers/media/common/tuners/xc5000.c
rename to drivers/media/tuners/xc5000.c
index 362a8d7c9738e018df797ed7504c215b4595d0de..dc93cf338f366fb3a2200ff0656ca290547f168c 100644 (file)
@@ -62,6 +62,9 @@ struct xc5000_priv {
        u8  radio_input;
 
        int chip_id;
+       u16 pll_register_no;
+       u8 init_status_supported;
+       u8 fw_checksum_supported;
 };
 
 /* Misc Defines */
@@ -111,6 +114,9 @@ struct xc5000_priv {
 #define XREG_PRODUCT_ID   0x08
 #define XREG_BUSY         0x09
 #define XREG_BUILD        0x0D
+#define XREG_TOTALGAIN    0x0F
+#define XREG_FW_CHECKSUM  0x12
+#define XREG_INIT_STATUS  0x13
 
 /*
    Basic firmware description. This will remain with
@@ -208,18 +214,25 @@ static struct XC_TV_STANDARD XC5000_Standard[MAX_TV_STANDARD] = {
 struct xc5000_fw_cfg {
        char *name;
        u16 size;
+       u16 pll_reg;
+       u8 init_status_supported;
+       u8 fw_checksum_supported;
 };
 
 #define XC5000A_FIRMWARE "dvb-fe-xc5000-1.6.114.fw"
 static const struct xc5000_fw_cfg xc5000a_1_6_114 = {
        .name = XC5000A_FIRMWARE,
        .size = 12401,
+       .pll_reg = 0x806c,
 };
 
-#define XC5000C_FIRMWARE "dvb-fe-xc5000c-41.024.5.fw"
+#define XC5000C_FIRMWARE "dvb-fe-xc5000c-4.1.30.7.fw"
 static const struct xc5000_fw_cfg xc5000c_41_024_5 = {
        .name = XC5000C_FIRMWARE,
        .size = 16497,
+       .pll_reg = 0x13,
+       .init_status_supported = 1,
+       .fw_checksum_supported = 1,
 };
 
 static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
@@ -233,7 +246,7 @@ static inline const struct xc5000_fw_cfg *xc5000_assign_firmware(int chip_id)
        }
 }
 
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe);
+static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force);
 static int xc5000_is_firmware_loaded(struct dvb_frontend *fe);
 static int xc5000_readreg(struct xc5000_priv *priv, u16 reg, u16 *val);
 static int xc5000_TunerReset(struct dvb_frontend *fe);
@@ -342,7 +355,7 @@ static int xc_write_reg(struct xc5000_priv *priv, u16 regAddr, u16 i2cData)
                        }
                }
        }
-       if (WatchDogTimer < 0)
+       if (WatchDogTimer <= 0)
                result = XC_RESULT_I2C_WRITE_FAILURE;
 
        return result;
@@ -541,6 +554,16 @@ static int xc_get_quality(struct xc5000_priv *priv, u16 *quality)
        return xc5000_readreg(priv, XREG_QUALITY, quality);
 }
 
+static int xc_get_analogsnr(struct xc5000_priv *priv, u16 *snr)
+{
+       return xc5000_readreg(priv, XREG_SNR, snr);
+}
+
+static int xc_get_totalgain(struct xc5000_priv *priv, u16 *totalgain)
+{
+       return xc5000_readreg(priv, XREG_TOTALGAIN, totalgain);
+}
+
 static u16 WaitForLock(struct xc5000_priv *priv)
 {
        u16 lockState = 0;
@@ -608,6 +631,9 @@ static int xc5000_fwupload(struct dvb_frontend *fe)
        int ret;
        const struct xc5000_fw_cfg *desired_fw =
                xc5000_assign_firmware(priv->chip_id);
+       priv->pll_register_no = desired_fw->pll_reg;
+       priv->init_status_supported = desired_fw->init_status_supported;
+       priv->fw_checksum_supported = desired_fw->fw_checksum_supported;
 
        /* request the firmware, this will block and timeout */
        printk(KERN_INFO "xc5000: waiting for firmware upload (%s)...\n",
@@ -652,9 +678,12 @@ static void xc_debug_dump(struct xc5000_priv *priv)
        u32 hsync_freq_hz = 0;
        u16 frame_lines;
        u16 quality;
+       u16 snr;
+       u16 totalgain;
        u8 hw_majorversion = 0, hw_minorversion = 0;
        u8 fw_majorversion = 0, fw_minorversion = 0;
        u16 fw_buildversion = 0;
+       u16 regval;
 
        /* Wait for stats to stabilize.
         * Frame Lines needs two frame times after initial lock
@@ -675,7 +704,7 @@ static void xc_debug_dump(struct xc5000_priv *priv)
        xc_get_version(priv,  &hw_majorversion, &hw_minorversion,
                &fw_majorversion, &fw_minorversion);
        xc_get_buildversion(priv,  &fw_buildversion);
-       dprintk(1, "*** HW: V%02x.%02x, FW: V%02x.%02x.%04x\n",
+       dprintk(1, "*** HW: V%d.%d, FW: V %d.%d.%d\n",
                hw_majorversion, hw_minorversion,
                fw_majorversion, fw_minorversion, fw_buildversion);
 
@@ -686,7 +715,19 @@ static void xc_debug_dump(struct xc5000_priv *priv)
        dprintk(1, "*** Frame lines = %d\n", frame_lines);
 
        xc_get_quality(priv,  &quality);
-       dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality);
+       dprintk(1, "*** Quality (0:<8dB, 7:>56dB) = %d\n", quality & 0x07);
+
+       xc_get_analogsnr(priv,  &snr);
+       dprintk(1, "*** Unweighted analog SNR = %d dB\n", snr & 0x3f);
+
+       xc_get_totalgain(priv,  &totalgain);
+       dprintk(1, "*** Total gain = %d.%d dB\n", totalgain / 256,
+               (totalgain % 256) * 100 / 256);
+
+       if (priv->pll_register_no) {
+               xc5000_readreg(priv, priv->pll_register_no, &regval);
+               dprintk(1, "*** PLL lock status = 0x%04x\n", regval);
+       }
 }
 
 static int xc5000_set_params(struct dvb_frontend *fe)
@@ -697,11 +738,9 @@ static int xc5000_set_params(struct dvb_frontend *fe)
        u32 freq = fe->dtv_property_cache.frequency;
        u32 delsys  = fe->dtv_property_cache.delivery_system;
 
-       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
-               if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
-                       dprintk(1, "Unable to load firmware and init tuner\n");
-                       return -EINVAL;
-               }
+       if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
+               dprintk(1, "Unable to load firmware and init tuner\n");
+               return -EINVAL;
        }
 
        dprintk(1, "%s() frequency=%d (Hz)\n", __func__, freq);
@@ -832,6 +871,7 @@ static int xc5000_set_tv_freq(struct dvb_frontend *fe,
        struct analog_parameters *params)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
+       u16 pll_lock_status;
        int ret;
 
        dprintk(1, "%s() frequency=%d (in units of 62.5khz)\n",
@@ -912,6 +952,21 @@ tune_channel:
        if (debug)
                xc_debug_dump(priv);
 
+       if (priv->pll_register_no != 0) {
+               msleep(20);
+               xc5000_readreg(priv, priv->pll_register_no, &pll_lock_status);
+               if (pll_lock_status > 63) {
+                       /* PLL is unlocked, force reload of the firmware */
+                       dprintk(1, "xc5000: PLL not locked (0x%x).  Reloading...\n",
+                               pll_lock_status);
+                       if (xc_load_fw_and_init_tuner(fe, 1) != XC_RESULT_SUCCESS) {
+                               printk(KERN_ERR "xc5000: Unable to reload fw\n");
+                               return -EREMOTEIO;
+                       }
+                       goto tune_channel;
+               }
+       }
+
        return 0;
 }
 
@@ -982,11 +1037,9 @@ static int xc5000_set_analog_params(struct dvb_frontend *fe,
        if (priv->i2c_props.adap == NULL)
                return -EINVAL;
 
-       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
-               if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
-                       dprintk(1, "Unable to load firmware and init tuner\n");
-                       return -EINVAL;
-               }
+       if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
+               dprintk(1, "Unable to load firmware and init tuner\n");
+               return -EINVAL;
        }
 
        switch (params->mode) {
@@ -1042,29 +1095,77 @@ static int xc5000_get_status(struct dvb_frontend *fe, u32 *status)
        return 0;
 }
 
-static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe)
+static int xc_load_fw_and_init_tuner(struct dvb_frontend *fe, int force)
 {
        struct xc5000_priv *priv = fe->tuner_priv;
-       int ret = 0;
+       int ret = XC_RESULT_SUCCESS;
+       u16 pll_lock_status;
+       u16 fw_ck;
+
+       if (force || xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
+
+fw_retry:
 
-       if (xc5000_is_firmware_loaded(fe) != XC_RESULT_SUCCESS) {
                ret = xc5000_fwupload(fe);
                if (ret != XC_RESULT_SUCCESS)
                        return ret;
-       }
 
-       /* Start the tuner self-calibration process */
-       ret |= xc_initialize(priv);
+               msleep(20);
 
-       /* Wait for calibration to complete.
-        * We could continue but XC5000 will clock stretch subsequent
-        * I2C transactions until calibration is complete.  This way we
-        * don't have to rely on clock stretching working.
-        */
-       xc_wait(100);
+               if (priv->fw_checksum_supported) {
+                       if (xc5000_readreg(priv, XREG_FW_CHECKSUM, &fw_ck)
+                           != XC_RESULT_SUCCESS) {
+                               dprintk(1, "%s() FW checksum reading failed.\n",
+                                       __func__);
+                               goto fw_retry;
+                       }
+
+                       if (fw_ck == 0) {
+                               dprintk(1, "%s() FW checksum failed = 0x%04x\n",
+                                       __func__, fw_ck);
+                               goto fw_retry;
+                       }
+               }
+
+               /* Start the tuner self-calibration process */
+               ret |= xc_initialize(priv);
 
-       /* Default to "CABLE" mode */
-       ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+               if (ret != XC_RESULT_SUCCESS)
+                       goto fw_retry;
+
+               /* Wait for calibration to complete.
+                * We could continue but XC5000 will clock stretch subsequent
+                * I2C transactions until calibration is complete.  This way we
+                * don't have to rely on clock stretching working.
+                */
+               xc_wait(100);
+
+               if (priv->init_status_supported) {
+                       if (xc5000_readreg(priv, XREG_INIT_STATUS, &fw_ck) != XC_RESULT_SUCCESS) {
+                               dprintk(1, "%s() FW failed reading init status.\n",
+                                       __func__);
+                               goto fw_retry;
+                       }
+
+                       if (fw_ck == 0) {
+                               dprintk(1, "%s() FW init status failed = 0x%04x\n", __func__, fw_ck);
+                               goto fw_retry;
+                       }
+               }
+
+               if (priv->pll_register_no) {
+                       xc5000_readreg(priv, priv->pll_register_no,
+                                      &pll_lock_status);
+                       if (pll_lock_status > 63) {
+                               /* PLL is unlocked, force reload of the firmware */
+                               printk(KERN_ERR "xc5000: PLL not running after fwload.\n");
+                               goto fw_retry;
+                       }
+               }
+
+               /* Default to "CABLE" mode */
+               ret |= xc_write_reg(priv, XREG_SIGNALSOURCE, XC_RF_MODE_CABLE);
+       }
 
        return ret;
 }
@@ -1097,7 +1198,7 @@ static int xc5000_init(struct dvb_frontend *fe)
        struct xc5000_priv *priv = fe->tuner_priv;
        dprintk(1, "%s()\n", __func__);
 
-       if (xc_load_fw_and_init_tuner(fe) != XC_RESULT_SUCCESS) {
+       if (xc_load_fw_and_init_tuner(fe, 0) != XC_RESULT_SUCCESS) {
                printk(KERN_ERR "xc5000: Unable to initialise tuner\n");
                return -EREMOTEIO;
        }
diff --git a/drivers/media/usb/Kconfig b/drivers/media/usb/Kconfig
new file mode 100644 (file)
index 0000000..6746994
--- /dev/null
@@ -0,0 +1,54 @@
+menuconfig MEDIA_USB_SUPPORT
+       bool "Media USB Adapters"
+       depends on USB && MEDIA_SUPPORT
+       help
+         Enable media drivers for USB bus.
+         If you have such devices, say Y.
+
+if MEDIA_USB_SUPPORT
+
+if MEDIA_CAMERA_SUPPORT
+       comment "Webcam devices"
+source "drivers/media/usb/uvc/Kconfig"
+source "drivers/media/usb/gspca/Kconfig"
+source "drivers/media/usb/pwc/Kconfig"
+source "drivers/media/usb/cpia2/Kconfig"
+source "drivers/media/usb/zr364xx/Kconfig"
+source "drivers/media/usb/stkwebcam/Kconfig"
+source "drivers/media/usb/s2255/Kconfig"
+source "drivers/media/usb/sn9c102/Kconfig"
+endif
+
+if MEDIA_ANALOG_TV_SUPPORT
+       comment "Analog TV USB devices"
+source "drivers/media/usb/au0828/Kconfig"
+source "drivers/media/usb/pvrusb2/Kconfig"
+source "drivers/media/usb/hdpvr/Kconfig"
+source "drivers/media/usb/tlg2300/Kconfig"
+source "drivers/media/usb/usbvision/Kconfig"
+source "drivers/media/usb/stk1160/Kconfig"
+endif
+
+if (MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
+       comment "Analog/digital TV USB devices"
+source "drivers/media/usb/cx231xx/Kconfig"
+source "drivers/media/usb/tm6000/Kconfig"
+endif
+
+
+if I2C && MEDIA_DIGITAL_TV_SUPPORT
+       comment "Digital TV USB devices"
+source "drivers/media/usb/dvb-usb/Kconfig"
+source "drivers/media/usb/dvb-usb-v2/Kconfig"
+source "drivers/media/usb/ttusb-budget/Kconfig"
+source "drivers/media/usb/ttusb-dec/Kconfig"
+source "drivers/media/usb/siano/Kconfig"
+source "drivers/media/usb/b2c2/Kconfig"
+endif
+
+if (MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT || MEDIA_DIGITAL_TV_SUPPORT)
+       comment "Webcam, TV (analog/digital) USB devices"
+source "drivers/media/usb/em28xx/Kconfig"
+endif
+
+endif #MEDIA_USB_SUPPORT
diff --git a/drivers/media/usb/Makefile b/drivers/media/usb/Makefile
new file mode 100644 (file)
index 0000000..7f51d7e
--- /dev/null
@@ -0,0 +1,22 @@
+#
+# Makefile for the USB media device drivers
+#
+
+# DVB USB-only drivers
+obj-y += ttusb-dec/ ttusb-budget/ dvb-usb/ dvb-usb-v2/ siano/ b2c2/
+obj-y += zr364xx/ stkwebcam/ s2255/
+
+obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
+obj-$(CONFIG_USB_GSPCA)         += gspca/
+obj-$(CONFIG_USB_PWC)           += pwc/
+obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
+obj-$(CONFIG_USB_SN9C102)       += sn9c102/
+obj-$(CONFIG_VIDEO_AU0828) += au0828/
+obj-$(CONFIG_VIDEO_HDPVR)      += hdpvr/
+obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
+obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
+obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
+obj-$(CONFIG_VIDEO_STK1160) += stk1160/
+obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
+obj-$(CONFIG_VIDEO_TM6000) += tm6000/
+obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
similarity index 54%
rename from drivers/media/video/au0828/Kconfig
rename to drivers/media/usb/au0828/Kconfig
index 23f7fd22f0eb508ecf5a32f8c3653e3bc51d8ff8..1766c0ce93be3736bd50c6b2991a622961cfa9d0 100644 (file)
@@ -2,15 +2,14 @@
 config VIDEO_AU0828
        tristate "Auvitek AU0828 support"
        depends on I2C && INPUT && DVB_CORE && USB && VIDEO_V4L2
-       depends on DVB_CAPTURE_DRIVERS
        select I2C_ALGOBIT
        select VIDEO_TVEEPROM
        select VIDEOBUF_VMALLOC
-       select DVB_AU8522_DTV if !DVB_FE_CUSTOMISE
-       select DVB_AU8522_V4L if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_MXL5007T if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_AU8522_DTV if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_AU8522_V4L if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          This is a video4linux driver for Auvitek's USB device.
 
similarity index 59%
rename from drivers/media/video/au0828/Makefile
rename to drivers/media/usb/au0828/Makefile
index bd22223f8d9f943a2a94fcf1aab1a4b625192f4d..98cc20cc0ffb2538cd025899e51931f9535715c2 100644 (file)
@@ -2,8 +2,8 @@ au0828-objs     := au0828-core.o au0828-i2c.o au0828-cards.o au0828-dvb.o au0828-vid
 
 obj-$(CONFIG_VIDEO_AU0828) += au0828.o
 
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
 
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
similarity index 99%
rename from drivers/media/video/au0828/au0828-cards.c
rename to drivers/media/usb/au0828/au0828-cards.c
index e3fe9a6637f66ad446786af6053f084962c42214..448361c6a13eea6e74adefab2ec9d50d448fe7a3 100644 (file)
@@ -46,7 +46,7 @@ struct au0828_board au0828_boards[] = {
                .name   = "Hauppauge HVR850",
                .tuner_type = TUNER_XC5000,
                .tuner_addr = 0x61,
-               .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
+               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
@@ -77,7 +77,7 @@ struct au0828_board au0828_boards[] = {
                   stretch fits inside of a normal clock cycle, or else the
                   au0828 fails to set the STOP bit.  A 30 KHz clock puts the
                   clock pulse width at 18us */
-               .i2c_clk_divider = AU0828_I2C_CLK_30KHZ,
+               .i2c_clk_divider = AU0828_I2C_CLK_20KHZ,
                .input = {
                        {
                                .type = AU0828_VMUX_TELEVISION,
similarity index 85%
rename from drivers/media/video/au0828/au0828-core.c
rename to drivers/media/usb/au0828/au0828-core.c
index 1e4ce5068ec2db52ca634f9a90e12ad66f755f6b..745a80a798c8b034f76401c43ce9935b71ce5569 100644 (file)
@@ -46,7 +46,7 @@ MODULE_PARM_DESC(disable_usb_speed_check,
 #define _BULKPIPESIZE 0xffff
 
 static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-       u16 index, unsigned char *cp, u16 size);
+                           u16 index);
 static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
        u16 index, unsigned char *cp, u16 size);
 
@@ -56,41 +56,25 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
 
 u32 au0828_readreg(struct au0828_dev *dev, u16 reg)
 {
-       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, dev->ctrlmsg, 1);
-       dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, dev->ctrlmsg[0]);
-       return dev->ctrlmsg[0];
+       u8 result = 0;
+
+       recv_control_msg(dev, CMD_REQUEST_IN, 0, reg, &result, 1);
+       dprintk(8, "%s(0x%04x) = 0x%02x\n", __func__, reg, result);
+
+       return result;
 }
 
 u32 au0828_writereg(struct au0828_dev *dev, u16 reg, u32 val)
 {
        dprintk(8, "%s(0x%04x, 0x%02x)\n", __func__, reg, val);
-       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg,
-                               dev->ctrlmsg, 0);
-}
-
-static void cmd_msg_dump(struct au0828_dev *dev)
-{
-       int i;
-
-       for (i = 0; i < sizeof(dev->ctrlmsg); i += 16)
-               dprintk(2, "%s() %02x %02x %02x %02x %02x %02x %02x %02x "
-                               "%02x %02x %02x %02x %02x %02x %02x %02x\n",
-                       __func__,
-                       dev->ctrlmsg[i+0], dev->ctrlmsg[i+1],
-                       dev->ctrlmsg[i+2], dev->ctrlmsg[i+3],
-                       dev->ctrlmsg[i+4], dev->ctrlmsg[i+5],
-                       dev->ctrlmsg[i+6], dev->ctrlmsg[i+7],
-                       dev->ctrlmsg[i+8], dev->ctrlmsg[i+9],
-                       dev->ctrlmsg[i+10], dev->ctrlmsg[i+11],
-                       dev->ctrlmsg[i+12], dev->ctrlmsg[i+13],
-                       dev->ctrlmsg[i+14], dev->ctrlmsg[i+15]);
+       return send_control_msg(dev, CMD_REQUEST_OUT, val, reg);
 }
 
 static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
-       u16 index, unsigned char *cp, u16 size)
+       u16 index)
 {
        int status = -ENODEV;
-       mutex_lock(&dev->mutex);
+
        if (dev->usbdev) {
 
                /* cp must be memory that has been allocated by kmalloc */
@@ -99,8 +83,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
                                request,
                                USB_DIR_OUT | USB_TYPE_VENDOR |
                                        USB_RECIP_DEVICE,
-                               value, index,
-                               cp, size, 1000);
+                               value, index, NULL, 0, 1000);
 
                status = min(status, 0);
 
@@ -110,7 +93,7 @@ static int send_control_msg(struct au0828_dev *dev, u16 request, u32 value,
                }
 
        }
-       mutex_unlock(&dev->mutex);
+
        return status;
 }
 
@@ -120,24 +103,23 @@ static int recv_control_msg(struct au0828_dev *dev, u16 request, u32 value,
        int status = -ENODEV;
        mutex_lock(&dev->mutex);
        if (dev->usbdev) {
-
-               memset(dev->ctrlmsg, 0, sizeof(dev->ctrlmsg));
-
-               /* cp must be memory that has been allocated by kmalloc */
                status = usb_control_msg(dev->usbdev,
                                usb_rcvctrlpipe(dev->usbdev, 0),
                                request,
                                USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
                                value, index,
-                               cp, size, 1000);
+                               dev->ctrlmsg, size, 1000);
 
                status = min(status, 0);
 
                if (status < 0) {
                        printk(KERN_ERR "%s() Failed receiving control message, error %d.\n",
                                __func__, status);
-               } else
-                       cmd_msg_dump(dev);
+               }
+
+               /* the host controller requires heap allocated memory, which
+                  is why we didn't just pass "cp" into usb_control_msg */
+               memcpy(cp, dev->ctrlmsg, size);
        }
        mutex_unlock(&dev->mutex);
        return status;
@@ -205,6 +187,8 @@ static int au0828_usb_probe(struct usb_interface *interface,
                return -ENOMEM;
        }
 
+       mutex_init(&dev->lock);
+       mutex_lock(&dev->lock);
        mutex_init(&dev->mutex);
        mutex_init(&dev->dvb.lock);
        dev->usbdev = usbdev;
@@ -215,6 +199,7 @@ static int au0828_usb_probe(struct usb_interface *interface,
        if (retval) {
                printk(KERN_ERR "%s() v4l2_device_register failed\n",
                       __func__);
+               mutex_unlock(&dev->lock);
                kfree(dev);
                return -EIO;
        }
@@ -245,6 +230,8 @@ static int au0828_usb_probe(struct usb_interface *interface,
        printk(KERN_INFO "Registered device AU0828 [%s]\n",
                dev->board.name == NULL ? "Unset" : dev->board.name);
 
+       mutex_unlock(&dev->lock);
+
        return 0;
 }
 
similarity index 90%
rename from drivers/media/video/au0828/au0828-dvb.c
rename to drivers/media/usb/au0828/au0828-dvb.c
index 39ece8e2498578d68664d49568ecec26aeb1a616..b328f6550d0b28714ff7339e08844e5491c8b407 100644 (file)
@@ -101,11 +101,14 @@ static struct tda18271_config hauppauge_woodbury_tunerconfig = {
        .gate    = TDA18271_GATE_DIGITAL,
 };
 
+static void au0828_restart_dvb_streaming(struct work_struct *work);
+
 /*-------------------------------------------------------------------*/
 static void urb_completion(struct urb *purb)
 {
        struct au0828_dev *dev = purb->context;
        int ptype = usb_pipetype(purb->pipe);
+       unsigned char *ptr;
 
        dprintk(2, "%s()\n", __func__);
 
@@ -121,6 +124,16 @@ static void urb_completion(struct urb *purb)
                return;
        }
 
+       /* See if the stream is corrupted (to work around a hardware
+          bug where the stream gets misaligned */
+       ptr = purb->transfer_buffer;
+       if (purb->actual_length > 0 && ptr[0] != 0x47) {
+               dprintk(1, "Need to restart streaming %02x len=%d!\n",
+                       ptr[0], purb->actual_length);
+               schedule_work(&dev->restart_streaming);
+               return;
+       }
+
        /* Feed the transport payload into the kernel demux */
        dvb_dmx_swfilter_packets(&dev->dvb.demux,
                purb->transfer_buffer, purb->actual_length / 188);
@@ -138,14 +151,13 @@ static int stop_urb_transfer(struct au0828_dev *dev)
 
        dprintk(2, "%s()\n", __func__);
 
+       dev->urb_streaming = 0;
        for (i = 0; i < URB_COUNT; i++) {
                usb_kill_urb(dev->urbs[i]);
                kfree(dev->urbs[i]->transfer_buffer);
                usb_free_urb(dev->urbs[i]);
        }
 
-       dev->urb_streaming = 0;
-
        return 0;
 }
 
@@ -246,11 +258,8 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
                mutex_lock(&dvb->lock);
                if (--dvb->feeding == 0) {
                        /* Stop transport */
-                       au0828_write(dev, 0x608, 0x00);
-                       au0828_write(dev, 0x609, 0x00);
-                       au0828_write(dev, 0x60a, 0x00);
-                       au0828_write(dev, 0x60b, 0x00);
                        ret = stop_urb_transfer(dev);
+                       au0828_write(dev, 0x60b, 0x00);
                }
                mutex_unlock(&dvb->lock);
        }
@@ -258,6 +267,37 @@ static int au0828_dvb_stop_feed(struct dvb_demux_feed *feed)
        return ret;
 }
 
+static void au0828_restart_dvb_streaming(struct work_struct *work)
+{
+       struct au0828_dev *dev = container_of(work, struct au0828_dev,
+                                             restart_streaming);
+       struct au0828_dvb *dvb = &dev->dvb;
+       int ret;
+
+       if (dev->urb_streaming == 0)
+               return;
+
+       dprintk(1, "Restarting streaming...!\n");
+
+       mutex_lock(&dvb->lock);
+
+       /* Stop transport */
+       ret = stop_urb_transfer(dev);
+       au0828_write(dev, 0x608, 0x00);
+       au0828_write(dev, 0x609, 0x00);
+       au0828_write(dev, 0x60a, 0x00);
+       au0828_write(dev, 0x60b, 0x00);
+
+       /* Start transport */
+       au0828_write(dev, 0x608, 0x90);
+       au0828_write(dev, 0x609, 0x72);
+       au0828_write(dev, 0x60a, 0x71);
+       au0828_write(dev, 0x60b, 0x01);
+       ret = start_urb_transfer(dev);
+
+       mutex_unlock(&dvb->lock);
+}
+
 static int dvb_register(struct au0828_dev *dev)
 {
        struct au0828_dvb *dvb = &dev->dvb;
@@ -265,6 +305,8 @@ static int dvb_register(struct au0828_dev *dev)
 
        dprintk(1, "%s()\n", __func__);
 
+       INIT_WORK(&dev->restart_streaming, au0828_restart_dvb_streaming);
+
        /* register adapter */
        result = dvb_register_adapter(&dvb->adapter, DRIVER_NAME, THIS_MODULE,
                                      &dev->usbdev->dev, adapter_nr);
similarity index 93%
rename from drivers/media/video/au0828/au0828-i2c.c
rename to drivers/media/usb/au0828/au0828-i2c.c
index 05c299fa5d79f5c90de3da3eca758ad45f7f2933..4ded17fe195792d53158e7936048213376c40e6b 100644 (file)
 #include <linux/io.h>
 
 #include "au0828.h"
-
+#include "media/tuner.h"
 #include <media/v4l2-common.h>
 
 static int i2c_scan;
 module_param(i2c_scan, int, 0444);
 MODULE_PARM_DESC(i2c_scan, "scan i2c bus at insmod time");
 
-#define I2C_WAIT_DELAY 512
-#define I2C_WAIT_RETRY 64
+#define I2C_WAIT_DELAY 25
+#define I2C_WAIT_RETRY 1000
 
 static inline int i2c_slave_did_write_ack(struct i2c_adapter *i2c_adap)
 {
@@ -147,8 +147,19 @@ static int i2c_sendbytes(struct i2c_adapter *i2c_adap,
        au0828_write(dev, AU0828_I2C_MULTIBYTE_MODE_2FF, 0x01);
 
        /* Set the I2C clock */
-       au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
-                    dev->board.i2c_clk_divider);
+       if (((dev->board.tuner_type == TUNER_XC5000) ||
+            (dev->board.tuner_type == TUNER_XC5000C)) &&
+           (dev->board.tuner_addr == msg->addr) &&
+           (msg->len == 64)) {
+               /* Hack to speed up firmware load.  The xc5000 lets us do up
+                  to 400 KHz when in firmware download mode */
+               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                            AU0828_I2C_CLK_250KHZ);
+       } else {
+               /* Use the i2c clock speed in the board configuration */
+               au0828_write(dev, AU0828_I2C_CLK_DIVIDER_202,
+                            dev->board.i2c_clk_divider);
+       }
 
        /* Hardware needs 8 bit addresses */
        au0828_write(dev, AU0828_I2C_DEST_ADDR_203, msg->addr << 1);
similarity index 98%
rename from drivers/media/video/au0828/au0828-reg.h
rename to drivers/media/usb/au0828/au0828-reg.h
index c39f3d2b721e22580b786f6a0a56f96394a1d563..2140f4cfb645679901e71853a940240a64024029 100644 (file)
@@ -63,3 +63,4 @@
 #define AU0828_I2C_CLK_250KHZ 0x07
 #define AU0828_I2C_CLK_100KHZ 0x14
 #define AU0828_I2C_CLK_30KHZ  0x40
+#define AU0828_I2C_CLK_20KHZ  0x60
similarity index 96%
rename from drivers/media/video/au0828/au0828-video.c
rename to drivers/media/usb/au0828/au0828-video.c
index ac3dd733ab815da3ce4345109bee032d6884bbb1..87058557057133f9d209e842c60f000e02f93fba 100644 (file)
@@ -864,17 +864,15 @@ static int res_get(struct au0828_fh *fh, unsigned int bit)
                return 1;
 
        /* is it free? */
-       mutex_lock(&dev->lock);
        if (dev->resources & bit) {
                /* no, someone else uses it */
-               mutex_unlock(&dev->lock);
                return 0;
        }
        /* it's free, grab it */
        fh->resources  |= bit;
        dev->resources |= bit;
        dprintk(1, "res: get %d\n", bit);
-       mutex_unlock(&dev->lock);
+
        return 1;
 }
 
@@ -894,11 +892,9 @@ static void res_free(struct au0828_fh *fh, unsigned int bits)
 
        BUG_ON((fh->resources & bits) != bits);
 
-       mutex_lock(&dev->lock);
        fh->resources  &= ~bits;
        dev->resources &= ~bits;
        dprintk(1, "res: put %d\n", bits);
-       mutex_unlock(&dev->lock);
 }
 
 static int get_ressource(struct au0828_fh *fh)
@@ -1023,7 +1019,8 @@ static int au0828_v4l2_open(struct file *filp)
                                    NULL, &dev->slock,
                                    V4L2_BUF_TYPE_VIDEO_CAPTURE,
                                    V4L2_FIELD_INTERLACED,
-                                   sizeof(struct au0828_buffer), fh, NULL);
+                                   sizeof(struct au0828_buffer), fh,
+                                   &dev->lock);
 
        /* VBI Setup */
        dev->vbi_width = 720;
@@ -1032,8 +1029,8 @@ static int au0828_v4l2_open(struct file *filp)
                                    NULL, &dev->slock,
                                    V4L2_BUF_TYPE_VBI_CAPTURE,
                                    V4L2_FIELD_SEQ_TB,
-                                   sizeof(struct au0828_buffer), fh, NULL);
-
+                                   sizeof(struct au0828_buffer), fh,
+                                   &dev->lock);
        return ret;
 }
 
@@ -1312,8 +1309,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        if (rc < 0)
                return rc;
 
-       mutex_lock(&dev->lock);
-
        if (videobuf_queue_is_busy(&fh->vb_vidq)) {
                printk(KERN_INFO "%s queue busy\n", __func__);
                rc = -EBUSY;
@@ -1322,7 +1317,6 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
 
        rc = au0828_set_format(dev, VIDIOC_S_FMT, f);
 out:
-       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -1331,11 +1325,19 @@ static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id * norm)
        struct au0828_fh *fh = priv;
        struct au0828_dev *dev = fh->dev;
 
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 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 */
 
        v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std, *norm);
+       dev->std_set_in_tuner_core = 1;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
        return 0;
 }
 
@@ -1463,7 +1465,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
        struct au0828_fh *fh = priv;
        struct au0828_dev *dev = fh->dev;
@@ -1515,9 +1517,18 @@ static int vidioc_s_tuner(struct file *file, void *priv,
                return -EINVAL;
 
        t->type = V4L2_TUNER_ANALOG_TV;
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+
        v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_tuner, t);
+
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
        dprintk(1, "VIDIOC_S_TUNER: signal = %x, afc = %x\n", t->signal,
                t->afc);
+
        return 0;
 
 }
@@ -1546,8 +1557,23 @@ static int vidioc_s_frequency(struct file *file, void *priv,
 
        dev->ctrl_freq = freq->frequency;
 
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 1);
+
+       if (dev->std_set_in_tuner_core == 0) {
+         /* If we've never sent the standard in tuner core, do so now.  We
+            don't do this at device probe because we don't want to incur
+            the cost of a firmware load */
+         v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                              dev->vdev->tvnorms);
+         dev->std_set_in_tuner_core = 1;
+       }
+
        v4l2_device_call_all(&dev->v4l2_dev, 0, tuner, s_frequency, freq);
 
+       if (dev->dvb.frontend && dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl)
+               dev->dvb.frontend->ops.analog_ops.i2c_gate_ctrl(dev->dvb.frontend, 0);
+
        au0828_analog_stream_reset(dev);
 
        return 0;
@@ -1692,14 +1718,18 @@ static int vidioc_streamoff(struct file *file, void *priv,
                        (AUVI_INPUT(i).audio_setup)(dev, 0);
                }
 
-               videobuf_streamoff(&fh->vb_vidq);
-               res_free(fh, AU0828_RESOURCE_VIDEO);
+               if (res_check(fh, AU0828_RESOURCE_VIDEO)) {
+                       videobuf_streamoff(&fh->vb_vidq);
+                       res_free(fh, AU0828_RESOURCE_VIDEO);
+               }
        } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                dev->vbi_timeout_running = 0;
                del_timer_sync(&dev->vbi_timeout);
 
-               videobuf_streamoff(&fh->vb_vbiq);
-               res_free(fh, AU0828_RESOURCE_VBI);
+               if (res_check(fh, AU0828_RESOURCE_VBI)) {
+                       videobuf_streamoff(&fh->vb_vbiq);
+                       res_free(fh, AU0828_RESOURCE_VBI);
+               }
        }
 
        return 0;
@@ -1717,8 +1747,12 @@ static int vidioc_g_register(struct file *file, void *priv,
                v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
                return 0;
        default:
-               return -EINVAL;
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
        }
+
+       reg->val = au0828_read(dev, reg->reg);
+       return 0;
 }
 
 static int vidioc_s_register(struct file *file, void *priv,
@@ -1732,9 +1766,10 @@ static int vidioc_s_register(struct file *file, void *priv,
                v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
                return 0;
        default:
-               return -EINVAL;
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
        }
-       return 0;
+       return au0828_writereg(dev, reg->reg, reg->val);
 }
 #endif
 
@@ -1827,7 +1862,7 @@ static struct v4l2_file_operations au0828_v4l_fops = {
        .read       = au0828_v4l2_read,
        .poll       = au0828_v4l2_poll,
        .mmap       = au0828_v4l2_mmap,
-       .ioctl      = video_ioctl2,
+       .unlocked_ioctl = video_ioctl2,
 };
 
 static const struct v4l2_ioctl_ops video_ioctl_ops = {
@@ -1917,7 +1952,6 @@ int au0828_analog_register(struct au0828_dev *dev,
 
        init_waitqueue_head(&dev->open);
        spin_lock_init(&dev->slock);
-       mutex_init(&dev->lock);
 
        /* init video dma queues */
        INIT_LIST_HEAD(&dev->vidq.active);
@@ -1958,11 +1992,13 @@ int au0828_analog_register(struct au0828_dev *dev,
        /* Fill the video capture device struct */
        *dev->vdev = au0828_video_template;
        dev->vdev->parent = &dev->usbdev->dev;
+       dev->vdev->lock = &dev->lock;
        strcpy(dev->vdev->name, "au0828a video");
 
        /* Setup the VBI device */
        *dev->vbi_dev = au0828_video_template;
        dev->vbi_dev->parent = &dev->usbdev->dev;
+       dev->vbi_dev->lock = &dev->lock;
        strcpy(dev->vbi_dev->name, "au0828a vbi");
 
        /* Register the v4l2 device */
similarity index 98%
rename from drivers/media/video/au0828/au0828.h
rename to drivers/media/usb/au0828/au0828.h
index 9cde3532182414dc1a72ec265714015453c29fbb..66a56ef7bbe4f4921a9ebc1af6911a293693573f 100644 (file)
@@ -197,6 +197,7 @@ struct au0828_dev {
 
        /* Digital */
        struct au0828_dvb               dvb;
+       struct work_struct              restart_streaming;
 
        /* Analog */
        struct v4l2_device v4l2_dev;
@@ -224,6 +225,7 @@ struct au0828_dev {
        unsigned int frame_count;
        int ctrl_freq;
        int input_type;
+       int std_set_in_tuner_core;
        unsigned int ctrl_input;
        enum au0828_dev_state dev_state;
        enum au0828_stream_state stream_state;
diff --git a/drivers/media/usb/b2c2/Kconfig b/drivers/media/usb/b2c2/Kconfig
new file mode 100644 (file)
index 0000000..17d3583
--- /dev/null
@@ -0,0 +1,15 @@
+config DVB_B2C2_FLEXCOP_USB
+       tristate "Technisat/B2C2 Air/Sky/Cable2PC USB"
+       depends on DVB_CORE && I2C
+       help
+         Support for the Air/Sky/Cable2PC USB1.1 box (DVB/ATSC) by Technisat/B2C2,
+
+         Say Y if you own such a device and want to use it.
+
+config DVB_B2C2_FLEXCOP_USB_DEBUG
+       bool "Enable debug for the B2C2 FlexCop drivers"
+       depends on DVB_B2C2_FLEXCOP_USB
+       select DVB_B2C2_FLEXCOP_DEBUG
+          help
+       Say Y if you want to enable the module option to control debug messages
+       of all B2C2 FlexCop drivers.
diff --git a/drivers/media/usb/b2c2/Makefile b/drivers/media/usb/b2c2/Makefile
new file mode 100644 (file)
index 0000000..2778c19
--- /dev/null
@@ -0,0 +1,5 @@
+b2c2-flexcop-usb-objs := flexcop-usb.o
+obj-$(CONFIG_DVB_B2C2_FLEXCOP_USB) += b2c2-flexcop-usb.o
+
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/common/b2c2/
similarity index 99%
rename from drivers/media/dvb/b2c2/flexcop-usb.c
rename to drivers/media/usb/b2c2/flexcop-usb.c
index 26c666dd3514a46ecfa98db63f3ee3152ef683f6..8b6275f859088d703fcc2893412dfe5c4ccd58b8 100644 (file)
@@ -324,10 +324,7 @@ static void flexcop_usb_process_frame(struct flexcop_usb *fc_usb,
                                        flexcop_pass_dmx_packets(
                                                        fc_usb->fc_dev, b+2, 1);
                                else
-                                       deb_ts(
-                                       "not ts packet %02x %02x %02x %02x \n",
-                                               *(b+2), *(b+3),
-                                               *(b+4), *(b+5));
+                                       deb_ts("not ts packet %*ph\n", 4, b+2);
                                b += 190;
                                l -= 190;
                                break;
similarity index 99%
rename from drivers/media/video/cpia2/cpia2_core.c
rename to drivers/media/usb/cpia2/cpia2_core.c
index 17188e234770fa8170502ab25d87959cc9b9c959..187012ce444bd2aef05235335c32e8302b3d3727 100644 (file)
 
 #include "cpia2.h"
 
+#include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/mm.h>
 #include <linux/vmalloc.h>
 #include <linux/firmware.h>
 
+#define FIRMWARE "cpia2/stv0672_vp4.bin"
+MODULE_FIRMWARE(FIRMWARE);
+
 /* #define _CPIA2_DEBUG_ */
 
 #ifdef _CPIA2_DEBUG_
@@ -898,7 +902,7 @@ static int cpia2_send_onebyte_command(struct camera_data *cam,
 static int apply_vp_patch(struct camera_data *cam)
 {
        const struct firmware *fw;
-       const char fw_name[] = "cpia2/stv0672_vp4.bin";
+       const char fw_name[] = FIRMWARE;
        int i, ret;
        struct cpia2_command cmd;
 
similarity index 97%
rename from drivers/media/video/cpia2/cpia2_v4l.c
rename to drivers/media/usb/cpia2/cpia2_v4l.c
index a62a7b739991806567231870dc143ceb3cac675a..aeb9d227572583e077a134e6133d9766793cc215 100644 (file)
@@ -84,21 +84,26 @@ MODULE_VERSION(CPIA_VERSION);
 static int cpia2_open(struct file *file)
 {
        struct camera_data *cam = video_drvdata(file);
-       int retval = v4l2_fh_open(file);
+       int retval;
 
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
+       retval = v4l2_fh_open(file);
        if (retval)
-               return retval;
+               goto open_unlock;
 
        if (v4l2_fh_is_singular_file(file)) {
                if (cpia2_allocate_buffers(cam)) {
                        v4l2_fh_release(file);
-                       return -ENOMEM;
+                       retval = -ENOMEM;
+                       goto open_unlock;
                }
 
                /* reset the camera */
                if (cpia2_reset_camera(cam) < 0) {
                        v4l2_fh_release(file);
-                       return -EIO;
+                       retval = -EIO;
+                       goto open_unlock;
                }
 
                cam->APP_len = 0;
@@ -106,7 +111,9 @@ static int cpia2_open(struct file *file)
        }
 
        cpia2_dbg_dump_registers(cam);
-       return 0;
+open_unlock:
+       mutex_unlock(&cam->v4l2_lock);
+       return retval;
 }
 
 /******************************************************************************
@@ -119,6 +126,7 @@ static int cpia2_close(struct file *file)
        struct video_device *dev = video_devdata(file);
        struct camera_data *cam = video_get_drvdata(dev);
 
+       mutex_lock(&cam->v4l2_lock);
        if (video_is_registered(&cam->vdev) && v4l2_fh_is_singular_file(file)) {
                cpia2_usb_stream_stop(cam);
 
@@ -133,6 +141,7 @@ static int cpia2_close(struct file *file)
                cam->stream_fh = NULL;
                cam->mmapped = 0;
        }
+       mutex_unlock(&cam->v4l2_lock);
        return v4l2_fh_release(file);
 }
 
@@ -146,11 +155,16 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
 {
        struct camera_data *cam = video_drvdata(file);
        int noblock = file->f_flags&O_NONBLOCK;
+       ssize_t ret;
 
        if(!cam)
                return -EINVAL;
 
-       return cpia2_read(cam, buf, count, noblock);
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
+       ret = cpia2_read(cam, buf, count, noblock);
+       mutex_unlock(&cam->v4l2_lock);
+       return ret;
 }
 
 
@@ -162,8 +176,12 @@ static ssize_t cpia2_v4l_read(struct file *file, char __user *buf, size_t count,
 static unsigned int cpia2_v4l_poll(struct file *filp, struct poll_table_struct *wait)
 {
        struct camera_data *cam = video_drvdata(filp);
+       unsigned int res;
 
-       return cpia2_poll(cam, filp, wait);
+       mutex_lock(&cam->v4l2_lock);
+       res = cpia2_poll(cam, filp, wait);
+       mutex_unlock(&cam->v4l2_lock);
+       return res;
 }
 
 
@@ -716,7 +734,8 @@ static int cpia2_g_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompres
  *
  *****************************************************************************/
 
-static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompression *parms)
+static int cpia2_s_jpegcomp(struct file *file, void *fh,
+               const struct v4l2_jpegcompression *parms)
 {
        struct camera_data *cam = video_drvdata(file);
 
@@ -725,8 +744,6 @@ static int cpia2_s_jpegcomp(struct file *file, void *fh, struct v4l2_jpegcompres
 
        cam->params.compression.inhibit_htables =
                !(parms->jpeg_markers & V4L2_JPEG_MARKER_DHT);
-       parms->jpeg_markers &= V4L2_JPEG_MARKER_DQT | V4L2_JPEG_MARKER_DRI |
-                              V4L2_JPEG_MARKER_DHT;
 
        if(parms->APP_len != 0) {
                if(parms->APP_len > 0 &&
@@ -987,10 +1004,13 @@ static int cpia2_mmap(struct file *file, struct vm_area_struct *area)
        struct camera_data *cam = video_drvdata(file);
        int retval;
 
+       if (mutex_lock_interruptible(&cam->v4l2_lock))
+               return -ERESTARTSYS;
        retval = cpia2_remap_buffer(cam, area);
 
        if(!retval)
                cam->stream_fh = file->private_data;
+       mutex_unlock(&cam->v4l2_lock);
        return retval;
 }
 
@@ -1147,10 +1167,6 @@ int cpia2_register_camera(struct camera_data *cam)
        cam->vdev.ctrl_handler = hdl;
        cam->vdev.v4l2_dev = &cam->v4l2_dev;
        set_bit(V4L2_FL_USE_FH_PRIO, &cam->vdev.flags);
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &cam->vdev.flags);
 
        reset_camera_struct_v4l(cam);
 
similarity index 86%
rename from drivers/media/video/cx231xx/Kconfig
rename to drivers/media/usb/cx231xx/Kconfig
index 446f692aabb740e175326f4017b925517f2ab52c..86feeeaf61c24a458df51f40ad2d3629901437e9 100644 (file)
@@ -40,11 +40,11 @@ config VIDEO_CX231XX_ALSA
 
 config VIDEO_CX231XX_DVB
        tristate "DVB/ATSC Support for Cx231xx based TV cards"
-       depends on VIDEO_CX231XX && DVB_CORE && DVB_CAPTURE_DRIVERS
+       depends on VIDEO_CX231XX && DVB_CORE
        select VIDEOBUF_DVB
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select DVB_MB86A20S if !DVB_FE_CUSTOMISE
+       select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MB86A20S if MEDIA_SUBDRV_AUTOSELECT
 
        ---help---
          This adds support for DVB cards based on the
similarity index 65%
rename from drivers/media/video/cx231xx/Makefile
rename to drivers/media/usb/cx231xx/Makefile
index b3348975c7c2039df3b72fc184ec9a3a43555665..52cf76935e69b02a666d5535d6f3fc23d5b759df 100644 (file)
@@ -8,9 +8,8 @@ obj-$(CONFIG_VIDEO_CX231XX) += cx231xx.o
 obj-$(CONFIG_VIDEO_CX231XX_ALSA) += cx231xx-alsa.o
 obj-$(CONFIG_VIDEO_CX231XX_DVB) += cx231xx-dvb.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
-ccflags-y += -Idrivers/media/dvb/dvb-usb
-
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/usb/dvb-usb
similarity index 99%
rename from drivers/media/video/cx231xx/cx231xx-417.c
rename to drivers/media/usb/cx231xx/cx231xx-417.c
index ce2f62238a19d8ae6fabf4df49532db7da0779c4..b024e5197a755fa01cc36fff2be2c7be1a876740 100644 (file)
@@ -2193,3 +2193,5 @@ int cx231xx_417_register(struct cx231xx *dev)
 
        return 0;
 }
+
+MODULE_FIRMWARE(CX231xx_FIRM_IMAGE_NAME);
similarity index 98%
rename from drivers/media/video/cx231xx/cx231xx-video.c
rename to drivers/media/usb/cx231xx/cx231xx-video.c
index 523aa49d6b868e5f0c68b2345e374cb5ddd45a5c..fedf7852a355c8e2fff3575769b0237c3fa33105 100644 (file)
@@ -1253,7 +1253,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
        struct cx231xx_fh *fh = priv;
        struct cx231xx *dev = fh->dev;
@@ -2096,7 +2096,7 @@ static int radio_s_tuner(struct file *file, void *priv, struct v4l2_tuner *t)
        return 0;
 }
 
-static int radio_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+static int radio_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
        return 0;
 }
@@ -2168,6 +2168,10 @@ static int cx231xx_v4l2_open(struct file *filp)
                cx231xx_errdev("cx231xx-video.c: Out of memory?!\n");
                return -ENOMEM;
        }
+       if (mutex_lock_interruptible(&dev->lock)) {
+               kfree(fh);
+               return -ERESTARTSYS;
+       }
        fh->dev = dev;
        fh->radio = radio;
        fh->type = fh_type;
@@ -2226,6 +2230,7 @@ static int cx231xx_v4l2_open(struct file *filp)
                                            sizeof(struct cx231xx_buffer),
                                            fh, &dev->lock);
        }
+       mutex_unlock(&dev->lock);
 
        return errCode;
 }
@@ -2272,11 +2277,11 @@ void cx231xx_release_analog_resources(struct cx231xx *dev)
 }
 
 /*
- * cx231xx_v4l2_close()
+ * cx231xx_close()
  * stops streaming and deallocates all resources allocated by the v4l2
  * calls and ioctls
  */
-static int cx231xx_v4l2_close(struct file *filp)
+static int cx231xx_close(struct file *filp)
 {
        struct cx231xx_fh *fh = filp->private_data;
        struct cx231xx *dev = fh->dev;
@@ -2355,6 +2360,18 @@ static int cx231xx_v4l2_close(struct file *filp)
        return 0;
 }
 
+static int cx231xx_v4l2_close(struct file *filp)
+{
+       struct cx231xx_fh *fh = filp->private_data;
+       struct cx231xx *dev = fh->dev;
+       int rc;
+
+       mutex_lock(&dev->lock);
+       rc = cx231xx_close(filp);
+       mutex_unlock(&dev->lock);
+       return rc;
+}
+
 /*
  * cx231xx_v4l2_read()
  * will allocate buffers when called for the first time
@@ -2378,8 +2395,12 @@ cx231xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
                if (unlikely(rc < 0))
                        return rc;
 
-               return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
+               rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
                                            filp->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
+               return rc;
        }
        return 0;
 }
@@ -2404,10 +2425,15 @@ static unsigned int cx231xx_v4l2_poll(struct file *filp, poll_table *wait)
                return POLLERR;
 
        if ((V4L2_BUF_TYPE_VIDEO_CAPTURE == fh->type) ||
-           (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type))
-               return videobuf_poll_stream(filp, &fh->vb_vidq, wait);
-       else
-               return POLLERR;
+           (V4L2_BUF_TYPE_VBI_CAPTURE == fh->type)) {
+               unsigned int res;
+
+               mutex_lock(&dev->lock);
+               res = videobuf_poll_stream(filp, &fh->vb_vidq, wait);
+               mutex_unlock(&dev->lock);
+               return res;
+       }
+       return POLLERR;
 }
 
 /*
@@ -2428,7 +2454,10 @@ static int cx231xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
        if (unlikely(rc < 0))
                return rc;
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
 
        cx231xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
                         (unsigned long)vma->vm_start,
@@ -2545,10 +2574,6 @@ static struct video_device *cx231xx_vdev_init(struct cx231xx *dev,
        vfd->release = video_device_release;
        vfd->debug = video_debug;
        vfd->lock = &dev->lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &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
new file mode 100644 (file)
index 0000000..834bfec
--- /dev/null
@@ -0,0 +1,149 @@
+config DVB_USB_V2
+       tristate "Support for various USB DVB devices v2"
+       depends on DVB_CORE && USB && I2C && RC_CORE
+       help
+         By enabling this you will be able to choose the various supported
+         USB1.1 and USB2.0 DVB devices.
+
+         Almost every USB device needs a firmware, please look into
+         <file:Documentation/dvb/README.dvb-usb>.
+
+         For a complete list of supported USB devices see the LinuxTV DVB Wiki:
+         <http://www.linuxtv.org/wiki/index.php/DVB_USB>
+
+         Say Y if you own a USB DVB device.
+
+config DVB_USB_CYPRESS_FIRMWARE
+       tristate "Cypress firmware helper routines"
+       depends on DVB_USB_V2
+
+config DVB_USB_AF9015
+       tristate "Afatech AF9015 DVB-T USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_AF9013
+       select DVB_PLL              if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2060   if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010   if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MC44S803 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Afatech AF9015 based DVB-T USB2.0 receiver
+
+config DVB_USB_AF9035
+       tristate "Afatech AF9035 DVB-T USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_AF9033
+       select MEDIA_TUNER_TUA9001 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_FC0011 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18218 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Afatech AF9035 based DVB USB receiver.
+
+config DVB_USB_ANYSEE
+       tristate "Anysee DVB-T/C USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18212 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ISL6423 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Anysee E30, Anysee E30 Plus or
+         Anysee E30 C Plus DVB USB2.0 receiver.
+
+config DVB_USB_AU6610
+       tristate "Alcor Micro AU6610 USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Sigmatek DVB-110 DVB-T USB2.0 receiver.
+
+config DVB_USB_AZ6007
+       tristate "AzureWave 6007 and clones DVB-T/C USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_USB_CYPRESS_FIRMWARE
+       select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2063 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the AZ6007 receivers like Terratec H7.
+
+config DVB_USB_CE6230
+       tristate "Intel CE6230 DVB-T USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_ZL10353
+       select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Intel CE6230 DVB-T USB2.0 receiver
+
+config DVB_USB_EC168
+       tristate "E3C EC168 DVB-T USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_EC100
+       select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the E3C EC168 DVB-T USB2.0 receiver.
+
+config DVB_USB_GL861
+       tristate "Genesys Logic GL861 USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the MSI Megasky 580 (55801) DVB-T USB2.0
+         receiver with USB ID 0db0:5581.
+
+config DVB_USB_IT913X
+       tristate "ITE IT913X DVB-T USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_IT913X_FE
+       help
+         Say Y here to support the ITE IT913X DVB-T USB2.0
+
+config DVB_USB_LME2510
+       tristate "LME DM04/QQBOX DVB-S USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_IX2505V if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_M88RS2000 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the LME DM04/QQBOX DVB-S USB2.0
+
+config DVB_USB_MXL111SF
+       tristate "MxL111SF DTV USB2.0 support"
+       depends on DVB_USB_V2
+       select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LG2160 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TVEEPROM
+       help
+         Say Y here to support the MxL111SF USB2.0 DTV receiver.
+
+config DVB_USB_RTL28XXU
+       tristate "Realtek RTL28xxU DVB USB support"
+       depends on DVB_USB_V2 && EXPERIMENTAL
+       select DVB_RTL2830
+       select DVB_RTL2832
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5005S if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_FC0012 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_FC0013 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_E4000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_FC2580 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Realtek RTL28xxU DVB USB receiver.
+
diff --git a/drivers/media/usb/dvb-usb-v2/Makefile b/drivers/media/usb/dvb-usb-v2/Makefile
new file mode 100644 (file)
index 0000000..b76f58e
--- /dev/null
@@ -0,0 +1,49 @@
+dvb_usb_v2-objs := dvb_usb_core.o dvb_usb_urb.o usb_urb.o
+obj-$(CONFIG_DVB_USB_V2) += dvb_usb_v2.o
+
+dvb_usb_cypress_firmware-objs := cypress_firmware.o
+obj-$(CONFIG_DVB_USB_CYPRESS_FIRMWARE) += dvb_usb_cypress_firmware.o
+
+dvb-usb-af9015-objs := af9015.o
+obj-$(CONFIG_DVB_USB_AF9015) += dvb-usb-af9015.o
+
+dvb-usb-af9035-objs := af9035.o
+obj-$(CONFIG_DVB_USB_AF9035) += dvb-usb-af9035.o
+
+dvb-usb-anysee-objs := anysee.o
+obj-$(CONFIG_DVB_USB_ANYSEE) += dvb-usb-anysee.o
+
+dvb-usb-au6610-objs := au6610.o
+obj-$(CONFIG_DVB_USB_AU6610) += dvb-usb-au6610.o
+
+dvb-usb-az6007-objs := az6007.o
+obj-$(CONFIG_DVB_USB_AZ6007) += dvb-usb-az6007.o
+
+dvb-usb-ce6230-objs := ce6230.o
+obj-$(CONFIG_DVB_USB_CE6230) += dvb-usb-ce6230.o
+
+dvb-usb-ec168-objs := ec168.o
+obj-$(CONFIG_DVB_USB_EC168) += dvb-usb-ec168.o
+
+dvb-usb-it913x-objs := it913x.o
+obj-$(CONFIG_DVB_USB_IT913X) += dvb-usb-it913x.o
+
+dvb-usb-lmedm04-objs := lmedm04.o
+obj-$(CONFIG_DVB_USB_LME2510) += dvb-usb-lmedm04.o
+
+dvb-usb-gl861-objs := gl861.o
+obj-$(CONFIG_DVB_USB_GL861) += dvb-usb-gl861.o
+
+dvb-usb-mxl111sf-objs += mxl111sf.o mxl111sf-phy.o mxl111sf-i2c.o
+dvb-usb-mxl111sf-objs += mxl111sf-gpio.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += dvb-usb-mxl111sf.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-demod.o
+obj-$(CONFIG_DVB_USB_MXL111SF) += mxl111sf-tuner.o
+
+dvb-usb-rtl28xxu-objs := rtl28xxu.o
+obj-$(CONFIG_DVB_USB_RTL28XXU) += dvb-usb-rtl28xxu.o
+
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
+ccflags-y += -I$(srctree)/drivers/media/tuners
+
diff --git a/drivers/media/usb/dvb-usb-v2/af9015.c b/drivers/media/usb/dvb-usb-v2/af9015.c
new file mode 100644 (file)
index 0000000..824f191
--- /dev/null
@@ -0,0 +1,1454 @@
+/*
+ * DVB USB Linux driver for Afatech AF9015 DVB-T USB2.0 receiver
+ *
+ * Copyright (C) 2007 Antti Palosaari <crope@iki.fi>
+ *
+ * Thanks to Afatech who kindly provided information.
+ *
+ *    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 "af9015.h"
+
+static int dvb_usb_af9015_remote;
+module_param_named(remote, dvb_usb_af9015_remote, int, 0644);
+MODULE_PARM_DESC(remote, "select remote");
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+static int af9015_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
+{
+#define BUF_LEN 63
+#define REQ_HDR_LEN 8 /* send header size */
+#define ACK_HDR_LEN 2 /* rece header size */
+       struct af9015_state *state = d_to_priv(d);
+       int ret, wlen, rlen;
+       u8 buf[BUF_LEN];
+       u8 write = 1;
+
+       buf[0] = req->cmd;
+       buf[1] = state->seq++;
+       buf[2] = req->i2c_addr;
+       buf[3] = req->addr >> 8;
+       buf[4] = req->addr & 0xff;
+       buf[5] = req->mbox;
+       buf[6] = req->addr_len;
+       buf[7] = req->data_len;
+
+       switch (req->cmd) {
+       case GET_CONFIG:
+       case READ_MEMORY:
+       case RECONNECT_USB:
+               write = 0;
+               break;
+       case READ_I2C:
+               write = 0;
+               buf[2] |= 0x01; /* set I2C direction */
+       case WRITE_I2C:
+               buf[0] = READ_WRITE_I2C;
+               break;
+       case WRITE_MEMORY:
+               if (((req->addr & 0xff00) == 0xff00) ||
+                   ((req->addr & 0xff00) == 0xae00))
+                       buf[0] = WRITE_VIRTUAL_MEMORY;
+       case WRITE_VIRTUAL_MEMORY:
+       case COPY_FIRMWARE:
+       case DOWNLOAD_FIRMWARE:
+       case BOOT:
+               break;
+       default:
+               dev_err(&d->udev->dev, "%s: unknown command=%d\n",
+                               KBUILD_MODNAME, req->cmd);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* buffer overflow check */
+       if ((write && (req->data_len > BUF_LEN - REQ_HDR_LEN)) ||
+                       (!write && (req->data_len > BUF_LEN - ACK_HDR_LEN))) {
+               dev_err(&d->udev->dev, "%s: too much data; cmd=%d len=%d\n",
+                               KBUILD_MODNAME, req->cmd, req->data_len);
+               ret = -EINVAL;
+               goto error;
+       }
+
+       /* write receives seq + status = 2 bytes
+          read receives seq + status + data = 2 + N bytes */
+       wlen = REQ_HDR_LEN;
+       rlen = ACK_HDR_LEN;
+       if (write) {
+               wlen += req->data_len;
+               memcpy(&buf[REQ_HDR_LEN], req->data, req->data_len);
+       } else {
+               rlen += req->data_len;
+       }
+
+       /* no ack for these packets */
+       if (req->cmd == DOWNLOAD_FIRMWARE || req->cmd == RECONNECT_USB)
+               rlen = 0;
+
+       ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
+       if (ret)
+               goto error;
+
+       /* check status */
+       if (rlen && buf[1]) {
+               dev_err(&d->udev->dev, "%s: command failed=%d\n",
+                               KBUILD_MODNAME, buf[1]);
+               ret = -EIO;
+               goto error;
+       }
+
+       /* read request, copy returned data to return buf */
+       if (!write)
+               memcpy(req->data, &buf[ACK_HDR_LEN], req->data_len);
+error:
+       return ret;
+}
+
+static int af9015_write_regs(struct dvb_usb_device *d, u16 addr, u8 *val,
+       u8 len)
+{
+       struct req_t req = {WRITE_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
+               val};
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_read_regs(struct dvb_usb_device *d, u16 addr, u8 *val, u8 len)
+{
+       struct req_t req = {READ_MEMORY, AF9015_I2C_DEMOD, addr, 0, 0, len,
+               val};
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_write_reg(struct dvb_usb_device *d, u16 addr, u8 val)
+{
+       return af9015_write_regs(d, addr, &val, 1);
+}
+
+static int af9015_read_reg(struct dvb_usb_device *d, u16 addr, u8 *val)
+{
+       return af9015_read_regs(d, addr, val, 1);
+}
+
+static int af9015_write_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+       u8 val)
+{
+       struct af9015_state *state = d_to_priv(d);
+       struct req_t req = {WRITE_I2C, addr, reg, 1, 1, 1, &val};
+
+       if (addr == state->af9013_config[0].i2c_addr ||
+           addr == state->af9013_config[1].i2c_addr)
+               req.addr_len = 3;
+
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_read_reg_i2c(struct dvb_usb_device *d, u8 addr, u16 reg,
+       u8 *val)
+{
+       struct af9015_state *state = d_to_priv(d);
+       struct req_t req = {READ_I2C, addr, reg, 0, 1, 1, val};
+
+       if (addr == state->af9013_config[0].i2c_addr ||
+           addr == state->af9013_config[1].i2c_addr)
+               req.addr_len = 3;
+
+       return af9015_ctrl_msg(d, &req);
+}
+
+static int af9015_do_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit, u8 op)
+{
+       int ret;
+       u8 val, mask = 0x01;
+
+       ret = af9015_read_reg(d, addr, &val);
+       if (ret)
+               return ret;
+
+       mask <<= bit;
+       if (op) {
+               /* set bit */
+               val |= mask;
+       } else {
+               /* clear bit */
+               mask ^= 0xff;
+               val &= mask;
+       }
+
+       return af9015_write_reg(d, addr, val);
+}
+
+static int af9015_set_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+       return af9015_do_reg_bit(d, addr, bit, 1);
+}
+
+static int af9015_clear_reg_bit(struct dvb_usb_device *d, u16 addr, u8 bit)
+{
+       return af9015_do_reg_bit(d, addr, bit, 0);
+}
+
+static int af9015_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+       int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       struct af9015_state *state = d_to_priv(d);
+       int ret = 0, i = 0;
+       u16 addr;
+       u8 uninitialized_var(mbox), addr_len;
+       struct req_t req;
+
+/*
+The bus lock is needed because there is two tuners both using same I2C-address.
+Due to that the only way to select correct tuner is use demodulator I2C-gate.
+
+................................................
+. AF9015 includes integrated AF9013 demodulator.
+. ____________                   ____________  .                ____________
+.|     uC     |                 |   demod    | .               |    tuner   |
+.|------------|                 |------------| .               |------------|
+.|   AF9015   |                 |  AF9013/5  | .               |   MXL5003  |
+.|            |--+----I2C-------|-----/ -----|-.-----I2C-------|            |
+.|            |  |              | addr 0x38  | .               |  addr 0xc6 |
+.|____________|  |              |____________| .               |____________|
+.................|..............................
+                |               ____________                   ____________
+                |              |   demod    |                 |    tuner   |
+                |              |------------|                 |------------|
+                |              |   AF9013   |                 |   MXL5003  |
+                +----I2C-------|-----/ -----|-------I2C-------|            |
+                               | addr 0x3a  |                 |  addr 0xc6 |
+                               |____________|                 |____________|
+*/
+       if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
+               return -EAGAIN;
+
+       while (i < num) {
+               if (msg[i].addr == state->af9013_config[0].i2c_addr ||
+                   msg[i].addr == state->af9013_config[1].i2c_addr) {
+                       addr = msg[i].buf[0] << 8;
+                       addr += msg[i].buf[1];
+                       mbox = msg[i].buf[2];
+                       addr_len = 3;
+               } else {
+                       addr = msg[i].buf[0];
+                       addr_len = 1;
+                       /* mbox is don't care in that case */
+               }
+
+               if (num > i + 1 && (msg[i+1].flags & I2C_M_RD)) {
+                       if (msg[i].len > 3 || msg[i+1].len > 61) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
+                       if (msg[i].addr == state->af9013_config[0].i2c_addr)
+                               req.cmd = READ_MEMORY;
+                       else
+                               req.cmd = READ_I2C;
+                       req.i2c_addr = msg[i].addr;
+                       req.addr = addr;
+                       req.mbox = mbox;
+                       req.addr_len = addr_len;
+                       req.data_len = msg[i+1].len;
+                       req.data = &msg[i+1].buf[0];
+                       ret = af9015_ctrl_msg(d, &req);
+                       i += 2;
+               } else if (msg[i].flags & I2C_M_RD) {
+                       if (msg[i].len > 61) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
+                       if (msg[i].addr == state->af9013_config[0].i2c_addr) {
+                               ret = -EINVAL;
+                               goto error;
+                       }
+                       req.cmd = READ_I2C;
+                       req.i2c_addr = msg[i].addr;
+                       req.addr = addr;
+                       req.mbox = mbox;
+                       req.addr_len = addr_len;
+                       req.data_len = msg[i].len;
+                       req.data = &msg[i].buf[0];
+                       ret = af9015_ctrl_msg(d, &req);
+                       i += 1;
+               } else {
+                       if (msg[i].len > 21) {
+                               ret = -EOPNOTSUPP;
+                               goto error;
+                       }
+                       if (msg[i].addr == state->af9013_config[0].i2c_addr)
+                               req.cmd = WRITE_MEMORY;
+                       else
+                               req.cmd = WRITE_I2C;
+                       req.i2c_addr = msg[i].addr;
+                       req.addr = addr;
+                       req.mbox = mbox;
+                       req.addr_len = addr_len;
+                       req.data_len = msg[i].len-addr_len;
+                       req.data = &msg[i].buf[addr_len];
+                       ret = af9015_ctrl_msg(d, &req);
+                       i += 1;
+               }
+               if (ret)
+                       goto error;
+
+       }
+       ret = i;
+
+error:
+       mutex_unlock(&d->i2c_mutex);
+
+       return ret;
+}
+
+static u32 af9015_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm af9015_i2c_algo = {
+       .master_xfer = af9015_i2c_xfer,
+       .functionality = af9015_i2c_func,
+};
+
+static int af9015_identify_state(struct dvb_usb_device *d, const char **name)
+{
+       int ret;
+       u8 reply;
+       struct req_t req = {GET_CONFIG, 0, 0, 0, 0, 1, &reply};
+
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret)
+               return ret;
+
+       dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply);
+
+       if (reply == 0x02)
+               ret = WARM;
+       else
+               ret = COLD;
+
+       return ret;
+}
+
+static int af9015_download_firmware(struct dvb_usb_device *d,
+       const struct firmware *fw)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int i, len, remaining, ret;
+       struct req_t req = {DOWNLOAD_FIRMWARE, 0, 0, 0, 0, 0, NULL};
+       u16 checksum = 0;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* calc checksum */
+       for (i = 0; i < fw->size; i++)
+               checksum += fw->data[i];
+
+       state->firmware_size = fw->size;
+       state->firmware_checksum = checksum;
+
+       #define FW_ADDR 0x5100 /* firmware start address */
+       #define LEN_MAX 55 /* max packet size */
+       for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
+               len = remaining;
+               if (len > LEN_MAX)
+                       len = LEN_MAX;
+
+               req.data_len = len;
+               req.data = (u8 *) &fw->data[fw->size - remaining];
+               req.addr = FW_ADDR + fw->size - remaining;
+
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret) {
+                       dev_err(&d->udev->dev,
+                                       "%s: firmware download failed=%d\n",
+                                       KBUILD_MODNAME, ret);
+                       goto error;
+               }
+       }
+
+       /* firmware loaded, request boot */
+       req.cmd = BOOT;
+       req.data_len = 0;
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret) {
+               dev_err(&d->udev->dev, "%s: firmware boot failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               goto error;
+       }
+
+error:
+       return ret;
+}
+
+/* hash (and dump) eeprom */
+static int af9015_eeprom_hash(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret, i;
+       static const unsigned int AF9015_EEPROM_SIZE = 256;
+       u8 buf[AF9015_EEPROM_SIZE];
+       struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, NULL};
+
+       /* read eeprom */
+       for (i = 0; i < AF9015_EEPROM_SIZE; i++) {
+               req.addr = i;
+               req.data = &buf[i];
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret < 0)
+                       goto err;
+       }
+
+       /* calculate checksum */
+       for (i = 0; i < AF9015_EEPROM_SIZE / sizeof(u32); i++) {
+               state->eeprom_sum *= GOLDEN_RATIO_PRIME_32;
+               state->eeprom_sum += le32_to_cpu(((u32 *)buf)[i]);
+       }
+
+       for (i = 0; i < AF9015_EEPROM_SIZE; i += 16)
+               dev_dbg(&d->udev->dev, "%s: %*ph\n", __func__, 16, buf + i);
+
+       dev_dbg(&d->udev->dev, "%s: eeprom sum=%.8x\n",
+                       __func__, state->eeprom_sum);
+       return 0;
+err:
+       dev_err(&d->udev->dev, "%s: eeprom failed=%d\n", KBUILD_MODNAME, ret);
+       return ret;
+}
+
+static int af9015_read_config(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       u8 val, i, offset = 0;
+       struct req_t req = {READ_I2C, AF9015_I2C_EEPROM, 0, 0, 1, 1, &val};
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* IR remote controller */
+       req.addr = AF9015_EEPROM_IR_MODE;
+       /* first message will timeout often due to possible hw bug */
+       for (i = 0; i < 4; i++) {
+               ret = af9015_ctrl_msg(d, &req);
+               if (!ret)
+                       break;
+       }
+       if (ret)
+               goto error;
+
+       ret = af9015_eeprom_hash(d);
+       if (ret)
+               goto error;
+
+       state->ir_mode = val;
+       dev_dbg(&d->udev->dev, "%s: IR mode=%d\n", __func__, val);
+
+       /* TS mode - one or two receivers */
+       req.addr = AF9015_EEPROM_TS_MODE;
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret)
+               goto error;
+
+       state->dual_mode = val;
+       dev_dbg(&d->udev->dev, "%s: TS mode=%d\n", __func__, state->dual_mode);
+
+       /* disable 2nd adapter because we don't have PID-filters */
+       if (d->udev->speed == USB_SPEED_FULL)
+               state->dual_mode = 0;
+
+       if (state->dual_mode) {
+               /* read 2nd demodulator I2C address */
+               req.addr = AF9015_EEPROM_DEMOD2_I2C;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+
+               state->af9013_config[1].i2c_addr = val;
+       }
+
+       for (i = 0; i < state->dual_mode + 1; i++) {
+               if (i == 1)
+                       offset = AF9015_EEPROM_OFFSET;
+               /* xtal */
+               req.addr = AF9015_EEPROM_XTAL_TYPE1 + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+               switch (val) {
+               case 0:
+                       state->af9013_config[i].clock = 28800000;
+                       break;
+               case 1:
+                       state->af9013_config[i].clock = 20480000;
+                       break;
+               case 2:
+                       state->af9013_config[i].clock = 28000000;
+                       break;
+               case 3:
+                       state->af9013_config[i].clock = 25000000;
+                       break;
+               };
+               dev_dbg(&d->udev->dev, "%s: [%d] xtal=%d set clock=%d\n",
+                               __func__, i, val,
+                               state->af9013_config[i].clock);
+
+               /* IF frequency */
+               req.addr = AF9015_EEPROM_IF1H + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+
+               state->af9013_config[i].if_frequency = val << 8;
+
+               req.addr = AF9015_EEPROM_IF1L + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+
+               state->af9013_config[i].if_frequency += val;
+               state->af9013_config[i].if_frequency *= 1000;
+               dev_dbg(&d->udev->dev, "%s: [%d] IF frequency=%d\n", __func__,
+                               i, state->af9013_config[i].if_frequency);
+
+               /* MT2060 IF1 */
+               req.addr = AF9015_EEPROM_MT2060_IF1H  + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+               state->mt2060_if1[i] = val << 8;
+               req.addr = AF9015_EEPROM_MT2060_IF1L + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+               state->mt2060_if1[i] += val;
+               dev_dbg(&d->udev->dev, "%s: [%d] MT2060 IF1=%d\n", __func__, i,
+                               state->mt2060_if1[i]);
+
+               /* tuner */
+               req.addr =  AF9015_EEPROM_TUNER_ID1 + offset;
+               ret = af9015_ctrl_msg(d, &req);
+               if (ret)
+                       goto error;
+               switch (val) {
+               case AF9013_TUNER_ENV77H11D5:
+               case AF9013_TUNER_MT2060:
+               case AF9013_TUNER_QT1010:
+               case AF9013_TUNER_UNKNOWN:
+               case AF9013_TUNER_MT2060_2:
+               case AF9013_TUNER_TDA18271:
+               case AF9013_TUNER_QT1010A:
+               case AF9013_TUNER_TDA18218:
+                       state->af9013_config[i].spec_inv = 1;
+                       break;
+               case AF9013_TUNER_MXL5003D:
+               case AF9013_TUNER_MXL5005D:
+               case AF9013_TUNER_MXL5005R:
+               case AF9013_TUNER_MXL5007T:
+                       state->af9013_config[i].spec_inv = 0;
+                       break;
+               case AF9013_TUNER_MC44S803:
+                       state->af9013_config[i].gpio[1] = AF9013_GPIO_LO;
+                       state->af9013_config[i].spec_inv = 1;
+                       break;
+               default:
+                       dev_err(&d->udev->dev, "%s: tuner id=%d not " \
+                                       "supported, please report!\n",
+                                       KBUILD_MODNAME, val);
+                       return -ENODEV;
+               };
+
+               state->af9013_config[i].tuner = val;
+               dev_dbg(&d->udev->dev, "%s: [%d] tuner id=%d\n",
+                               __func__, i, val);
+       }
+
+error:
+       if (ret)
+               dev_err(&d->udev->dev, "%s: eeprom read failed=%d\n",
+                               KBUILD_MODNAME, ret);
+
+       /* AverMedia AVerTV Volar Black HD (A850) device have bad EEPROM
+          content :-( Override some wrong values here. Ditto for the
+          AVerTV Red HD+ (A850T) device. */
+       if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_AVERMEDIA &&
+               ((le16_to_cpu(d->udev->descriptor.idProduct) ==
+                       USB_PID_AVERMEDIA_A850) ||
+               (le16_to_cpu(d->udev->descriptor.idProduct) ==
+                       USB_PID_AVERMEDIA_A850T))) {
+               dev_dbg(&d->udev->dev,
+                               "%s: AverMedia A850: overriding config\n",
+                               __func__);
+               /* disable dual mode */
+               state->dual_mode = 0;
+
+               /* set correct IF */
+               state->af9013_config[0].if_frequency = 4570000;
+       }
+
+       return ret;
+}
+
+static int af9015_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
+               struct usb_data_stream_properties *stream)
+{
+       struct dvb_usb_device *d = fe_to_d(fe);
+       dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, fe_to_adap(fe)->id);
+
+       if (d->udev->speed == USB_SPEED_FULL)
+               stream->u.bulk.buffersize = TS_USB11_FRAME_SIZE;
+
+       return 0;
+}
+
+static int af9015_get_adapter_count(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       return state->dual_mode + 1;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_set_frontend(struct dvb_frontend *fe)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->set_frontend[fe_to_adap(fe)->id](fe);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_read_status(struct dvb_frontend *fe,
+       fe_status_t *status)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->read_status[fe_to_adap(fe)->id](fe, status);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_init(struct dvb_frontend *fe)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->init[fe_to_adap(fe)->id](fe);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+/* override demod callbacks for resource locking */
+static int af9015_af9013_sleep(struct dvb_frontend *fe)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->sleep[fe_to_adap(fe)->id](fe);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+/* override tuner callbacks for resource locking */
+static int af9015_tuner_init(struct dvb_frontend *fe)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->tuner_init[fe_to_adap(fe)->id](fe);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+/* override tuner callbacks for resource locking */
+static int af9015_tuner_sleep(struct dvb_frontend *fe)
+{
+       int ret;
+       struct af9015_state *state = fe_to_priv(fe);
+
+       if (mutex_lock_interruptible(&state->fe_mutex))
+               return -EAGAIN;
+
+       ret = state->tuner_sleep[fe_to_adap(fe)->id](fe);
+
+       mutex_unlock(&state->fe_mutex);
+
+       return ret;
+}
+
+static int af9015_copy_firmware(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       u8 fw_params[4];
+       u8 val, i;
+       struct req_t req = {COPY_FIRMWARE, 0, 0x5100, 0, 0, sizeof(fw_params),
+               fw_params };
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       fw_params[0] = state->firmware_size >> 8;
+       fw_params[1] = state->firmware_size & 0xff;
+       fw_params[2] = state->firmware_checksum >> 8;
+       fw_params[3] = state->firmware_checksum & 0xff;
+
+       /* wait 2nd demodulator ready */
+       msleep(100);
+
+       ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr,
+                       0x98be, &val);
+       if (ret)
+               goto error;
+       else
+               dev_dbg(&d->udev->dev, "%s: firmware status=%02x\n",
+                               __func__, val);
+
+       if (val == 0x0c) /* fw is running, no need for download */
+               goto exit;
+
+       /* set I2C master clock to fast (to speed up firmware copy) */
+       ret = af9015_write_reg(d, 0xd416, 0x04); /* 0x04 * 400ns */
+       if (ret)
+               goto error;
+
+       msleep(50);
+
+       /* copy firmware */
+       ret = af9015_ctrl_msg(d, &req);
+       if (ret)
+               dev_err(&d->udev->dev, "%s: firmware copy cmd failed=%d\n",
+                               KBUILD_MODNAME, ret);
+
+       dev_dbg(&d->udev->dev, "%s: firmware copy done\n", __func__);
+
+       /* set I2C master clock back to normal */
+       ret = af9015_write_reg(d, 0xd416, 0x14); /* 0x14 * 400ns */
+       if (ret)
+               goto error;
+
+       /* request boot firmware */
+       ret = af9015_write_reg_i2c(d, state->af9013_config[1].i2c_addr,
+                       0xe205, 1);
+       dev_dbg(&d->udev->dev, "%s: firmware boot cmd status=%d\n",
+                       __func__, ret);
+       if (ret)
+               goto error;
+
+       for (i = 0; i < 15; i++) {
+               msleep(100);
+
+               /* check firmware status */
+               ret = af9015_read_reg_i2c(d, state->af9013_config[1].i2c_addr,
+                               0x98be, &val);
+               dev_dbg(&d->udev->dev, "%s: firmware status cmd status=%d " \
+                               "firmware status=%02x\n", __func__, ret, val);
+               if (ret)
+                       goto error;
+
+               if (val == 0x0c || val == 0x04) /* success or fail */
+                       break;
+       }
+
+       if (val == 0x04) {
+               dev_err(&d->udev->dev, "%s: firmware did not run\n",
+                               KBUILD_MODNAME);
+               ret = -ETIMEDOUT;
+       } else if (val != 0x0c) {
+               dev_err(&d->udev->dev, "%s: firmware boot timeout\n",
+                               KBUILD_MODNAME);
+               ret = -ETIMEDOUT;
+       }
+
+error:
+exit:
+       return ret;
+}
+
+static int af9015_af9013_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       struct af9015_state *state = adap_to_priv(adap);
+
+       if (adap->id == 0) {
+               state->af9013_config[0].ts_mode = AF9013_TS_USB;
+               memcpy(state->af9013_config[0].api_version, "\x0\x1\x9\x0", 4);
+               state->af9013_config[0].gpio[0] = AF9013_GPIO_HI;
+               state->af9013_config[0].gpio[3] = AF9013_GPIO_TUNER_ON;
+       } else if (adap->id == 1) {
+               state->af9013_config[1].ts_mode = AF9013_TS_SERIAL;
+               memcpy(state->af9013_config[1].api_version, "\x0\x1\x9\x0", 4);
+               state->af9013_config[1].gpio[0] = AF9013_GPIO_TUNER_ON;
+               state->af9013_config[1].gpio[1] = AF9013_GPIO_LO;
+
+               /* copy firmware to 2nd demodulator */
+               if (state->dual_mode) {
+                       ret = af9015_copy_firmware(adap_to_d(adap));
+                       if (ret) {
+                               dev_err(&adap_to_d(adap)->udev->dev,
+                                               "%s: firmware copy to 2nd " \
+                                               "frontend failed, will " \
+                                               "disable it\n", KBUILD_MODNAME);
+                               state->dual_mode = 0;
+                               return -ENODEV;
+                       }
+               } else {
+                       return -ENODEV;
+               }
+       }
+
+       /* attach demodulator */
+       adap->fe[0] = dvb_attach(af9013_attach,
+               &state->af9013_config[adap->id], &adap_to_d(adap)->i2c_adap);
+
+       /*
+        * AF9015 firmware does not like if it gets interrupted by I2C adapter
+        * request on some critical phases. During normal operation I2C adapter
+        * is used only 2nd demodulator and tuner on dual tuner devices.
+        * Override demodulator callbacks and use mutex for limit access to
+        * those "critical" paths to keep AF9015 happy.
+        */
+       if (adap->fe[0]) {
+               state->set_frontend[adap->id] =
+                       adap->fe[0]->ops.set_frontend;
+               adap->fe[0]->ops.set_frontend =
+                       af9015_af9013_set_frontend;
+
+               state->read_status[adap->id] =
+                       adap->fe[0]->ops.read_status;
+               adap->fe[0]->ops.read_status =
+                       af9015_af9013_read_status;
+
+               state->init[adap->id] = adap->fe[0]->ops.init;
+               adap->fe[0]->ops.init = af9015_af9013_init;
+
+               state->sleep[adap->id] = adap->fe[0]->ops.sleep;
+               adap->fe[0]->ops.sleep = af9015_af9013_sleep;
+       }
+
+       return adap->fe[0] == NULL ? -ENODEV : 0;
+}
+
+static struct mt2060_config af9015_mt2060_config = {
+       .i2c_address = 0xc0,
+       .clock_out = 0,
+};
+
+static struct qt1010_config af9015_qt1010_config = {
+       .i2c_address = 0xc4,
+};
+
+static struct tda18271_config af9015_tda18271_config = {
+       .gate = TDA18271_GATE_DIGITAL,
+       .small_i2c = TDA18271_16_BYTE_CHUNK_INIT,
+};
+
+static struct mxl5005s_config af9015_mxl5003_config = {
+       .i2c_address     = 0xc6,
+       .if_freq         = IF_FREQ_4570000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_DEFAULT,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
+static struct mxl5005s_config af9015_mxl5005_config = {
+       .i2c_address     = 0xc6,
+       .if_freq         = IF_FREQ_4570000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_OFF,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
+
+static struct mc44s803_config af9015_mc44s803_config = {
+       .i2c_address = 0xc0,
+       .dig_out = 1,
+};
+
+static struct tda18218_config af9015_tda18218_config = {
+       .i2c_address = 0xc0,
+       .i2c_wr_max = 21, /* max wr bytes AF9015 I2C adap can handle at once */
+};
+
+static struct mxl5007t_config af9015_mxl5007t_config = {
+       .xtal_freq_hz = MxL_XTAL_24_MHZ,
+       .if_freq_hz = MxL_IF_4_57_MHZ,
+};
+
+static int af9015_tuner_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       switch (state->af9013_config[adap->id].tuner) {
+       case AF9013_TUNER_MT2060:
+       case AF9013_TUNER_MT2060_2:
+               ret = dvb_attach(mt2060_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap, &af9015_mt2060_config,
+                       state->mt2060_if1[adap->id])
+                       == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_QT1010:
+       case AF9013_TUNER_QT1010A:
+               ret = dvb_attach(qt1010_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_qt1010_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_TDA18271:
+               ret = dvb_attach(tda18271_attach, adap->fe[0], 0xc0,
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_tda18271_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_TDA18218:
+               ret = dvb_attach(tda18218_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_tda18218_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MXL5003D:
+               ret = dvb_attach(mxl5005s_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_mxl5003_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MXL5005D:
+       case AF9013_TUNER_MXL5005R:
+               ret = dvb_attach(mxl5005s_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_mxl5005_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_ENV77H11D5:
+               ret = dvb_attach(dvb_pll_attach, adap->fe[0], 0xc0,
+                       &adap_to_d(adap)->i2c_adap,
+                       DVB_PLL_TDA665X) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MC44S803:
+               ret = dvb_attach(mc44s803_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &af9015_mc44s803_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_MXL5007T:
+               ret = dvb_attach(mxl5007t_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       0xc0, &af9015_mxl5007t_config) == NULL ? -ENODEV : 0;
+               break;
+       case AF9013_TUNER_UNKNOWN:
+       default:
+               dev_err(&d->udev->dev, "%s: unknown tuner id=%d\n",
+                               KBUILD_MODNAME,
+                               state->af9013_config[adap->id].tuner);
+               ret = -ENODEV;
+       }
+
+       if (adap->fe[0]->ops.tuner_ops.init) {
+               state->tuner_init[adap->id] =
+                       adap->fe[0]->ops.tuner_ops.init;
+               adap->fe[0]->ops.tuner_ops.init = af9015_tuner_init;
+       }
+
+       if (adap->fe[0]->ops.tuner_ops.sleep) {
+               state->tuner_sleep[adap->id] =
+                       adap->fe[0]->ops.tuner_ops.sleep;
+               adap->fe[0]->ops.tuner_ops.sleep = af9015_tuner_sleep;
+       }
+
+       return ret;
+}
+
+static int af9015_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       int ret;
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
+
+       if (onoff)
+               ret = af9015_set_reg_bit(d, 0xd503, 0);
+       else
+               ret = af9015_clear_reg_bit(d, 0xd503, 0);
+
+       return ret;
+}
+
+static int af9015_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
+       int onoff)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       int ret;
+       u8 idx;
+       dev_dbg(&d->udev->dev, "%s: index=%d pid=%04x onoff=%d\n",
+                       __func__, index, pid, onoff);
+
+       ret = af9015_write_reg(d, 0xd505, (pid & 0xff));
+       if (ret)
+               goto error;
+
+       ret = af9015_write_reg(d, 0xd506, (pid >> 8));
+       if (ret)
+               goto error;
+
+       idx = ((index & 0x1f) | (1 << 5));
+       ret = af9015_write_reg(d, 0xd504, idx);
+
+error:
+       return ret;
+}
+
+static int af9015_init_endpoint(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       u16 frame_size;
+       u8  packet_size;
+       dev_dbg(&d->udev->dev, "%s: USB speed=%d\n", __func__, d->udev->speed);
+
+       if (d->udev->speed == USB_SPEED_FULL) {
+               frame_size = TS_USB11_FRAME_SIZE/4;
+               packet_size = TS_USB11_MAX_PACKET_SIZE/4;
+       } else {
+               frame_size = TS_USB20_FRAME_SIZE/4;
+               packet_size = TS_USB20_MAX_PACKET_SIZE/4;
+       }
+
+       ret = af9015_set_reg_bit(d, 0xd507, 2); /* assert EP4 reset */
+       if (ret)
+               goto error;
+       ret = af9015_set_reg_bit(d, 0xd50b, 1); /* assert EP5 reset */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xdd11, 5); /* disable EP4 */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xdd11, 6); /* disable EP5 */
+       if (ret)
+               goto error;
+       ret = af9015_set_reg_bit(d, 0xdd11, 5); /* enable EP4 */
+       if (ret)
+               goto error;
+       if (state->dual_mode) {
+               ret = af9015_set_reg_bit(d, 0xdd11, 6); /* enable EP5 */
+               if (ret)
+                       goto error;
+       }
+       ret = af9015_clear_reg_bit(d, 0xdd13, 5); /* disable EP4 NAK */
+       if (ret)
+               goto error;
+       if (state->dual_mode) {
+               ret = af9015_clear_reg_bit(d, 0xdd13, 6); /* disable EP5 NAK */
+               if (ret)
+                       goto error;
+       }
+       /* EP4 xfer length */
+       ret = af9015_write_reg(d, 0xdd88, frame_size & 0xff);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd89, frame_size >> 8);
+       if (ret)
+               goto error;
+       /* EP5 xfer length */
+       ret = af9015_write_reg(d, 0xdd8a, frame_size & 0xff);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd8b, frame_size >> 8);
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd0c, packet_size); /* EP4 packet size */
+       if (ret)
+               goto error;
+       ret = af9015_write_reg(d, 0xdd0d, packet_size); /* EP5 packet size */
+       if (ret)
+               goto error;
+       ret = af9015_clear_reg_bit(d, 0xd507, 2); /* negate EP4 reset */
+       if (ret)
+               goto error;
+       if (state->dual_mode) {
+               ret = af9015_clear_reg_bit(d, 0xd50b, 1); /* negate EP5 reset */
+               if (ret)
+                       goto error;
+       }
+
+       /* enable / disable mp2if2 */
+       if (state->dual_mode)
+               ret = af9015_set_reg_bit(d, 0xd50b, 0);
+       else
+               ret = af9015_clear_reg_bit(d, 0xd50b, 0);
+
+error:
+       if (ret)
+               dev_err(&d->udev->dev, "%s: endpoint init failed=%d\n",
+                               KBUILD_MODNAME, ret);
+
+       return ret;
+}
+
+static int af9015_init(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       mutex_init(&state->fe_mutex);
+
+       /* init RC canary */
+       ret = af9015_write_reg(d, 0x98e9, 0xff);
+       if (ret)
+               goto error;
+
+       ret = af9015_init_endpoint(d);
+       if (ret)
+               goto error;
+
+error:
+       return ret;
+}
+
+struct af9015_rc_setup {
+       unsigned int id;
+       char *rc_codes;
+};
+
+static char *af9015_rc_setup_match(unsigned int id,
+       const struct af9015_rc_setup *table)
+{
+       for (; table->rc_codes; table++)
+               if (table->id == id)
+                       return table->rc_codes;
+       return NULL;
+}
+
+static const struct af9015_rc_setup af9015_rc_setup_modparam[] = {
+       { AF9015_REMOTE_A_LINK_DTU_M, RC_MAP_ALINK_DTU_M },
+       { AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3, RC_MAP_MSI_DIGIVOX_II },
+       { AF9015_REMOTE_MYGICTV_U718, RC_MAP_TOTAL_MEDIA_IN_HAND },
+       { AF9015_REMOTE_DIGITTRADE_DVB_T, RC_MAP_DIGITTRADE },
+       { AF9015_REMOTE_AVERMEDIA_KS, RC_MAP_AVERMEDIA_RM_KS },
+       { }
+};
+
+static const struct af9015_rc_setup af9015_rc_setup_hashes[] = {
+       { 0xb8feb708, RC_MAP_MSI_DIGIVOX_II },
+       { 0xa3703d00, RC_MAP_ALINK_DTU_M },
+       { 0x9b7dc64e, RC_MAP_TOTAL_MEDIA_IN_HAND }, /* MYGICTV U718 */
+       { 0x5d49e3db, RC_MAP_DIGITTRADE }, /* LC-Power LC-USB-DVBT */
+       { }
+};
+
+static int af9015_rc_query(struct dvb_usb_device *d)
+{
+       struct af9015_state *state = d_to_priv(d);
+       int ret;
+       u8 buf[17];
+
+       /* read registers needed to detect remote controller code */
+       ret = af9015_read_regs(d, 0x98d9, buf, sizeof(buf));
+       if (ret)
+               goto error;
+
+       /* If any of these are non-zero, assume invalid data */
+       if (buf[1] || buf[2] || buf[3]) {
+               dev_dbg(&d->udev->dev, "%s: invalid data\n", __func__);
+               return ret;
+       }
+
+       /* Check for repeat of previous code */
+       if ((state->rc_repeat != buf[6] || buf[0]) &&
+                       !memcmp(&buf[12], state->rc_last, 4)) {
+               dev_dbg(&d->udev->dev, "%s: key repeated\n", __func__);
+               rc_keydown(d->rc_dev, state->rc_keycode, 0);
+               state->rc_repeat = buf[6];
+               return ret;
+       }
+
+       /* Only process key if canary killed */
+       if (buf[16] != 0xff && buf[0] != 0x01) {
+               dev_dbg(&d->udev->dev, "%s: key pressed %*ph\n",
+                               __func__, 4, buf + 12);
+
+               /* Reset the canary */
+               ret = af9015_write_reg(d, 0x98e9, 0xff);
+               if (ret)
+                       goto error;
+
+               /* Remember this key */
+               memcpy(state->rc_last, &buf[12], 4);
+               if (buf[14] == (u8) ~buf[15]) {
+                       if (buf[12] == (u8) ~buf[13]) {
+                               /* NEC */
+                               state->rc_keycode = buf[12] << 8 | buf[14];
+                       } else {
+                               /* NEC extended*/
+                               state->rc_keycode = buf[12] << 16 |
+                                       buf[13] << 8 | buf[14];
+                       }
+               } else {
+                       /* 32 bit NEC */
+                       state->rc_keycode = buf[12] << 24 | buf[13] << 16 |
+                                       buf[14] << 8 | buf[15];
+               }
+               rc_keydown(d->rc_dev, state->rc_keycode, 0);
+       } else {
+               dev_dbg(&d->udev->dev, "%s: no key press\n", __func__);
+               /* Invalidate last keypress */
+               /* Not really needed, but helps with debug */
+               state->rc_last[2] = state->rc_last[3];
+       }
+
+       state->rc_repeat = buf[6];
+       state->rc_failed = false;
+
+error:
+       if (ret) {
+               dev_warn(&d->udev->dev, "%s: rc query failed=%d\n",
+                               KBUILD_MODNAME, ret);
+
+               /* allow random errors as dvb-usb will stop polling on error */
+               if (!state->rc_failed)
+                       ret = 0;
+
+               state->rc_failed = true;
+       }
+
+       return ret;
+}
+
+static int af9015_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
+{
+       struct af9015_state *state = d_to_priv(d);
+       u16 vid = le16_to_cpu(d->udev->descriptor.idVendor);
+
+       if (state->ir_mode == AF9015_IR_MODE_DISABLED)
+               return 0;
+
+       /* try to load remote based module param */
+       if (!rc->map_name)
+               rc->map_name = af9015_rc_setup_match(dvb_usb_af9015_remote,
+                               af9015_rc_setup_modparam);
+
+       /* try to load remote based eeprom hash */
+       if (!rc->map_name)
+               rc->map_name = af9015_rc_setup_match(state->eeprom_sum,
+                               af9015_rc_setup_hashes);
+
+       /* try to load remote based USB iManufacturer string */
+       if (!rc->map_name && vid == USB_VID_AFATECH) {
+               /* Check USB manufacturer and product strings and try
+                  to determine correct remote in case of chip vendor
+                  reference IDs are used.
+                  DO NOT ADD ANYTHING NEW HERE. Use hashes instead. */
+               char manufacturer[10];
+               memset(manufacturer, 0, sizeof(manufacturer));
+               usb_string(d->udev, d->udev->descriptor.iManufacturer,
+                       manufacturer, sizeof(manufacturer));
+               if (!strcmp("MSI", manufacturer)) {
+                       /* iManufacturer 1 MSI
+                          iProduct      2 MSI K-VOX */
+                       rc->map_name = af9015_rc_setup_match(
+                                       AF9015_REMOTE_MSI_DIGIVOX_MINI_II_V3,
+                                       af9015_rc_setup_modparam);
+               }
+       }
+
+       /* load empty to enable rc */
+       if (!rc->map_name)
+               rc->map_name = RC_MAP_EMPTY;
+
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query = af9015_rc_query;
+       rc->interval = 500;
+
+       return 0;
+}
+
+/* interface 0 is used by DVB-T receiver and
+   interface 1 is for remote controller (HID) */
+static struct dvb_usb_device_properties af9015_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct af9015_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .identify_state = af9015_identify_state,
+       .firmware = AF9015_FIRMWARE,
+       .download_firmware = af9015_download_firmware,
+
+       .i2c_algo = &af9015_i2c_algo,
+       .read_config = af9015_read_config,
+       .frontend_attach = af9015_af9013_frontend_attach,
+       .tuner_attach = af9015_tuner_attach,
+       .init = af9015_init,
+       .get_rc_config = af9015_get_rc_config,
+       .get_stream_config = af9015_get_stream_config,
+
+       .get_adapter_count = af9015_get_adapter_count,
+       .adapter = {
+               {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER |
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                       .pid_filter_count = 32,
+                       .pid_filter = af9015_pid_filter,
+                       .pid_filter_ctrl = af9015_pid_filter_ctrl,
+
+                       .stream = DVB_USB_STREAM_BULK(0x84, 8, TS_USB20_FRAME_SIZE),
+               }, {
+                       .stream = DVB_USB_STREAM_BULK(0x85, 8, TS_USB20_FRAME_SIZE),
+               },
+       },
+};
+
+static const struct usb_device_id af9015_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9015,
+               &af9015_props, "Afatech AF9015 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9015_9016,
+               &af9015_props, "Afatech AF9015 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV_DONGLE_GOLD,
+               &af9015_props, "Leadtek WinFast DTV Dongle Gold", RC_MAP_LEADTEK_Y04G0051) },
+       { DVB_USB_DEVICE(USB_VID_PINNACLE, USB_PID_PINNACLE_PCTV71E,
+               &af9015_props, "Pinnacle PCTV 71e", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U,
+               &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_TINYTWIN,
+               &af9015_props, "DigitalNow TinyTwin", RC_MAP_AZUREWAVE_AD_TU700) },
+       { DVB_USB_DEVICE(USB_VID_VISIONPLUS, USB_PID_AZUREWAVE_AD_TU700,
+               &af9015_props, "TwinHan AzureWave AD-TU700(704J)", RC_MAP_AZUREWAVE_AD_TU700) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_USB_XE_REV2,
+               &af9015_props, "TerraTec Cinergy T USB XE", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_2T,
+               &af9015_props, "KWorld PlusTV Dual DVB-T PCI (DVB-T PC160-2T)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X,
+               &af9015_props, "AVerMedia AVerTV DVB-T Volar X", RC_MAP_AVERMEDIA_M135A) },
+       { DVB_USB_DEVICE(USB_VID_XTENSIONS, USB_PID_XTENSIONS_XD_380,
+               &af9015_props, "Xtensions XD-380", NULL) },
+       { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGIVOX_DUO,
+               &af9015_props, "MSI DIGIVOX Duo", RC_MAP_MSI_DIGIVOX_III) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_VOLAR_X_2,
+               &af9015_props, "Fujitsu-Siemens Slim Mobile USB DVB-T", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TELESTAR,  USB_PID_TELESTAR_STARSTICK_2,
+               &af9015_props, "Telestar Starstick 2", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A309,
+               &af9015_props, "AVerMedia A309", NULL) },
+       { DVB_USB_DEVICE(USB_VID_MSI_2, USB_PID_MSI_DIGI_VOX_MINI_III,
+               &af9015_props, "MSI Digi VOX mini III", RC_MAP_MSI_DIGIVOX_III) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U,
+               &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_2,
+               &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_3,
+               &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_TREKSTOR_DVBT,
+               &af9015_props, "TrekStor DVB-T USB Stick", RC_MAP_TREKSTOR) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850,
+               &af9015_props, "AverMedia AVerTV Volar Black HD (A850)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A805,
+               &af9015_props, "AverMedia AVerTV Volar GPS 805 (A805)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_CONCEPTRONIC_CTVDIGRCU,
+               &af9015_props, "Conceptronic USB2.0 DVB-T CTVDIGRCU V3.0", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_MC810,
+               &af9015_props, "KWorld Digial MC-810", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KYE, USB_PID_GENIUS_TVGO_DVB_T03,
+               &af9015_props, "Genius TVGo DVB-T03", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_399U_2,
+               &af9015_props, "KWorld PlusTV Dual DVB-T Stick (DVB-T 399U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_PC160_T,
+               &af9015_props, "KWorld PlusTV DVB-T PCI Pro Card (DVB-T PC160-T)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV20,
+               &af9015_props, "Sveon STV20 Tuner USB DVB-T HDTV", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_TINYTWIN_2,
+               &af9015_props, "DigitalNow TinyTwin v2", RC_MAP_DIGITALNOW_TINYTWIN) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, USB_PID_WINFAST_DTV2000DS,
+               &af9015_props, "Leadtek WinFast DTV2000DS", RC_MAP_LEADTEK_Y04G0051) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB383_T,
+               &af9015_props, "KWorld USB DVB-T Stick Mobile (UB383-T)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_395U_4,
+               &af9015_props, "KWorld USB DVB-T TV Stick II (VS-DVB-T 395U)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A815M,
+               &af9015_props, "AverMedia AVerTV Volar M (A815Mac)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_RC,
+               &af9015_props, "TerraTec Cinergy T Stick RC", RC_MAP_TERRATEC_SLIM_2) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_DUAL_RC,
+               &af9015_props, "TerraTec Cinergy T Stick Dual RC", RC_MAP_TERRATEC_SLIM) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A850T,
+               &af9015_props, "AverMedia AVerTV Red HD+ (A850T)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TINYTWIN_3,
+               &af9015_props, "DigitalNow TinyTwin v3", RC_MAP_DIGITALNOW_TINYTWIN) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22,
+               &af9015_props, "Sveon STV22 Dual USB DVB-T Tuner HDTV", RC_MAP_MSI_DIGIVOX_III) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, af9015_id_table);
+
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver af9015_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = af9015_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
+};
+
+module_usb_driver(af9015_usb_driver);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Afatech AF9015 driver");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(AF9015_FIRMWARE);
similarity index 78%
rename from drivers/media/dvb/dvb-usb/af9015.h
rename to drivers/media/usb/dvb-usb-v2/af9015.h
index 2f68419e899b670992f62366ec8563f4d28f9532..533637dedd23e6ea5e97badd2f7962ab90e18b80 100644 (file)
  *
  */
 
-#ifndef _DVB_USB_AF9015_H_
-#define _DVB_USB_AF9015_H_
+#ifndef AF9015_H
+#define AF9015_H
 
-#define DVB_USB_LOG_PREFIX "af9015"
-#include "dvb-usb.h"
+#include <linux/hash.h>
+#include "dvb_usb.h"
+#include "af9013.h"
+#include "dvb-pll.h"
+#include "mt2060.h"
+#include "qt1010.h"
+#include "tda18271.h"
+#include "mxl5005s.h"
+#include "mc44s803.h"
+#include "tda18218.h"
+#include "mxl5007t.h"
 
-#define deb_info(args...) dprintk(dvb_usb_af9015_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_af9015_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_af9015_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_af9015_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_af9015_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_af9015_debug, 0x20, args)
+#define AF9015_FIRMWARE "dvb-usb-af9015.fw"
+
+/* Windows driver uses packet count 21 for USB1.1 and 348 for USB2.0.
+   We use smaller - about 1/4 from the original, 5 and 87. */
+#define TS_PACKET_SIZE            188
+
+#define TS_USB20_PACKET_COUNT      87
+#define TS_USB20_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB20_PACKET_COUNT)
+
+#define TS_USB11_PACKET_COUNT       5
+#define TS_USB11_FRAME_SIZE       (TS_PACKET_SIZE*TS_USB11_PACKET_COUNT)
+
+#define TS_USB20_MAX_PACKET_SIZE  512
+#define TS_USB11_MAX_PACKET_SIZE   64
 
 #define AF9015_I2C_EEPROM  0xa0
 #define AF9015_I2C_DEMOD   0x38
@@ -99,9 +116,18 @@ enum af9015_ir_mode {
 };
 
 struct af9015_state {
+       u8 ir_mode;
        u8 rc_repeat;
        u32 rc_keycode;
        u8 rc_last[4];
+       bool rc_failed;
+       u8 dual_mode;
+       u8 seq; /* packet sequence number */
+       u16 mt2060_if1[2];
+       u16 firmware_size;
+       u16 firmware_checksum;
+       u32 eeprom_sum;
+       struct af9013_config af9013_config[2];
 
        /* for demod callback override */
        int (*set_frontend[2]) (struct dvb_frontend *fe);
@@ -110,14 +136,7 @@ struct af9015_state {
        int (*sleep[2]) (struct dvb_frontend *fe);
        int (*tuner_init[2]) (struct dvb_frontend *fe);
        int (*tuner_sleep[2]) (struct dvb_frontend *fe);
-};
-
-struct af9015_config {
-       u8  dual_mode:1;
-       u16 mt2060_if1[2];
-       u16 firmware_size;
-       u16 firmware_checksum;
-       u32 eeprom_sum;
+       struct mutex fe_mutex;
 };
 
 enum af9015_remote {
similarity index 57%
rename from drivers/media/dvb/dvb-usb/af9035.c
rename to drivers/media/usb/dvb-usb-v2/af9035.c
index e83b39d3993cebc70177891f5608f34b41ec2cc4..aabd3fc03ea7e1594c00aab276364b857e9459ff 100644 (file)
@@ -22,9 +22,6 @@
 #include "af9035.h"
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-static DEFINE_MUTEX(af9035_usb_mutex);
-static struct dvb_usb_device_properties af9035_properties[2];
-static int af9035_properties_count = ARRAY_SIZE(af9035_properties);
 
 static u16 af9035_checksum(const u8 *buf, size_t len)
 {
@@ -42,100 +39,80 @@ static u16 af9035_checksum(const u8 *buf, size_t len)
        return checksum;
 }
 
-static int af9035_ctrl_msg(struct usb_device *udev, struct usb_req *req)
+static int af9035_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
 {
 #define BUF_LEN 64
 #define REQ_HDR_LEN 4 /* send header size */
 #define ACK_HDR_LEN 3 /* rece header size */
 #define CHECKSUM_LEN 2
 #define USB_TIMEOUT 2000
-
-       int ret, msg_len, act_len;
+       struct state *state = d_to_priv(d);
+       int ret, wlen, rlen;
        u8 buf[BUF_LEN];
-       static u8 seq; /* packet sequence number */
        u16 checksum, tmp_checksum;
 
        /* buffer overflow check */
        if (req->wlen > (BUF_LEN - REQ_HDR_LEN - CHECKSUM_LEN) ||
-               req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
-               pr_debug("%s: too much data wlen=%d rlen=%d\n", __func__,
-                               req->wlen, req->rlen);
+                       req->rlen > (BUF_LEN - ACK_HDR_LEN - CHECKSUM_LEN)) {
+               dev_err(&d->udev->dev, "%s: too much data wlen=%d rlen=%d\n",
+                               __func__, req->wlen, req->rlen);
                return -EINVAL;
        }
 
-       if (mutex_lock_interruptible(&af9035_usb_mutex) < 0)
-               return -EAGAIN;
-
        buf[0] = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN - 1;
        buf[1] = req->mbox;
        buf[2] = req->cmd;
-       buf[3] = seq++;
-       if (req->wlen)
-               memcpy(&buf[4], req->wbuf, req->wlen);
+       buf[3] = state->seq++;
+       memcpy(&buf[REQ_HDR_LEN], req->wbuf, req->wlen);
+
+       wlen = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN;
+       rlen = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
 
        /* calc and add checksum */
        checksum = af9035_checksum(buf, buf[0] - 1);
        buf[buf[0] - 1] = (checksum >> 8);
        buf[buf[0] - 0] = (checksum & 0xff);
 
-       msg_len = REQ_HDR_LEN + req->wlen + CHECKSUM_LEN ;
+       /* no ack for these packets */
+       if (req->cmd == CMD_FW_DL)
+               rlen = 0;
 
-       /* send req */
-       ret = usb_bulk_msg(udev, usb_sndbulkpipe(udev, 0x02), buf, msg_len,
-                       &act_len, USB_TIMEOUT);
-       if (ret < 0)
-               err("bulk message failed=%d (%d/%d)", ret, msg_len, act_len);
-       else
-               if (act_len != msg_len)
-                       ret = -EIO; /* all data is not send */
-       if (ret < 0)
-               goto err_mutex_unlock;
+       ret = dvb_usbv2_generic_rw(d, buf, wlen, buf, rlen);
+       if (ret)
+               goto err;
 
        /* no ack for those packets */
        if (req->cmd == CMD_FW_DL)
-               goto exit_mutex_unlock;
-
-       /* receive ack and data if read req */
-       msg_len = ACK_HDR_LEN + req->rlen + CHECKSUM_LEN;
-       ret = usb_bulk_msg(udev, usb_rcvbulkpipe(udev, 0x81), buf, msg_len,
-                       &act_len, USB_TIMEOUT);
-       if (ret < 0) {
-               err("recv bulk message failed=%d", ret);
-               ret = -EIO;
-               goto err_mutex_unlock;
-       }
-
-       if (act_len != msg_len) {
-               err("recv bulk message truncated (%d != %d)", act_len, msg_len);
-               ret = -EIO;
-               goto err_mutex_unlock;
-       }
+               goto exit;
 
        /* verify checksum */
-       checksum = af9035_checksum(buf, act_len - 2);
-       tmp_checksum = (buf[act_len - 2] << 8) | buf[act_len - 1];
+       checksum = af9035_checksum(buf, rlen - 2);
+       tmp_checksum = (buf[rlen - 2] << 8) | buf[rlen - 1];
        if (tmp_checksum != checksum) {
-               err("%s: command=%02x checksum mismatch (%04x != %04x)",
-                   __func__, req->cmd, tmp_checksum, checksum);
+               dev_err(&d->udev->dev, "%s: command=%02x checksum mismatch " \
+                               "(%04x != %04x)\n", KBUILD_MODNAME, req->cmd,
+                               tmp_checksum, checksum);
                ret = -EIO;
-               goto err_mutex_unlock;
+               goto err;
        }
 
        /* check status */
        if (buf[2]) {
-               pr_debug("%s: command=%02x failed fw error=%d\n", __func__,
-                               req->cmd, buf[2]);
+               dev_dbg(&d->udev->dev, "%s: command=%02x failed fw error=%d\n",
+                               __func__, req->cmd, buf[2]);
                ret = -EIO;
-               goto err_mutex_unlock;
+               goto err;
        }
 
        /* read request, copy returned data to return buf */
        if (req->rlen)
                memcpy(req->rbuf, &buf[ACK_HDR_LEN], req->rlen);
 
-err_mutex_unlock:
-exit_mutex_unlock:
-       mutex_unlock(&af9035_usb_mutex);
+exit:
+       return 0;
+
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -155,7 +132,7 @@ static int af9035_wr_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
        wbuf[5] = (reg >> 0) & 0xff;
        memcpy(&wbuf[6], val, len);
 
-       return af9035_ctrl_msg(d->udev, &req);
+       return af9035_ctrl_msg(d, &req);
 }
 
 /* read multiple registers */
@@ -165,7 +142,7 @@ static int af9035_rd_regs(struct dvb_usb_device *d, u32 reg, u8 *val, int len)
        u8 mbox = (reg >> 16) & 0xff;
        struct usb_req req = { CMD_MEM_RD, mbox, sizeof(wbuf), wbuf, len, val };
 
-       return af9035_ctrl_msg(d->udev, &req);
+       return af9035_ctrl_msg(d, &req);
 }
 
 /* write single register */
@@ -205,7 +182,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                struct i2c_msg msg[], int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
-       struct state *state = d->priv;
+       struct state *state = d_to_priv(d);
        int ret;
 
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
@@ -249,7 +226,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                        buf[3] = 0x00; /* reg addr MSB */
                        buf[4] = 0x00; /* reg addr LSB */
                        memcpy(&buf[5], msg[0].buf, msg[0].len);
-                       ret = af9035_ctrl_msg(d->udev, &req);
+                       ret = af9035_ctrl_msg(d, &req);
                }
        } else if (num == 1 && !(msg[0].flags & I2C_M_RD)) {
                if (msg[0].len > 40) {
@@ -272,7 +249,7 @@ static int af9035_i2c_master_xfer(struct i2c_adapter *adap,
                        buf[3] = 0x00; /* reg addr MSB */
                        buf[4] = 0x00; /* reg addr LSB */
                        memcpy(&buf[5], msg[0].buf, msg[0].len);
-                       ret = af9035_ctrl_msg(d->udev, &req);
+                       ret = af9035_ctrl_msg(d, &req);
                }
        } else {
                /*
@@ -301,87 +278,7 @@ static struct i2c_algorithm af9035_i2c_algo = {
        .functionality = af9035_i2c_functionality,
 };
 
-#define AF9035_POLL 250
-static int af9035_rc_query(struct dvb_usb_device *d)
-{
-       unsigned int key;
-       unsigned char b[4];
-       int ret;
-       struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
-
-       ret = af9035_ctrl_msg(d->udev, &req);
-       if (ret < 0)
-               goto err;
-
-       if ((b[2] + b[3]) == 0xff) {
-               if ((b[0] + b[1]) == 0xff) {
-                       /* NEC */
-                       key = b[0] << 8 | b[2];
-               } else {
-                       /* ext. NEC */
-                       key = b[0] << 16 | b[1] << 8 | b[2];
-               }
-       } else {
-               key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
-       }
-
-       rc_keydown(d->rc_dev, key, 0);
-
-err:
-       /* ignore errors */
-       return 0;
-}
-
-static int af9035_init(struct dvb_usb_device *d)
-{
-       struct state *state = d->priv;
-       int ret, i;
-       u16 frame_size = 87 * 188 / 4;
-       u8  packet_size = 512 / 4;
-       struct reg_val_mask tab[] = {
-               { 0x80f99d, 0x01, 0x01 },
-               { 0x80f9a4, 0x01, 0x01 },
-               { 0x00dd11, 0x00, 0x20 },
-               { 0x00dd11, 0x00, 0x40 },
-               { 0x00dd13, 0x00, 0x20 },
-               { 0x00dd13, 0x00, 0x40 },
-               { 0x00dd11, 0x20, 0x20 },
-               { 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
-               { 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
-               { 0x00dd0c, packet_size, 0xff},
-               { 0x00dd11, state->dual_mode << 6, 0x40 },
-               { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
-               { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
-               { 0x00dd0d, packet_size, 0xff },
-               { 0x80f9a3, 0x00, 0x01 },
-               { 0x80f9cd, 0x00, 0x01 },
-               { 0x80f99d, 0x00, 0x01 },
-               { 0x80f9a4, 0x00, 0x01 },
-       };
-
-       pr_debug("%s: USB speed=%d frame_size=%04x packet_size=%02x\n",
-               __func__, d->udev->speed, frame_size, packet_size);
-
-       /* init endpoints */
-       for (i = 0; i < ARRAY_SIZE(tab); i++) {
-               ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
-                               tab[i].mask);
-               if (ret < 0)
-                       goto err;
-       }
-
-       return 0;
-
-err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
-
-       return ret;
-}
-
-static int af9035_identify_state(struct usb_device *udev,
-               struct dvb_usb_device_properties *props,
-               struct dvb_usb_device_description **desc,
-               int *cold)
+static int af9035_identify_state(struct dvb_usb_device *d, const char **name)
 {
        int ret;
        u8 wbuf[1] = { 1 };
@@ -389,26 +286,25 @@ static int af9035_identify_state(struct usb_device *udev,
        struct usb_req req = { CMD_FW_QUERYINFO, 0, sizeof(wbuf), wbuf,
                        sizeof(rbuf), rbuf };
 
-       ret = af9035_ctrl_msg(udev, &req);
+       ret = af9035_ctrl_msg(d, &req);
        if (ret < 0)
                goto err;
 
-       pr_debug("%s: reply=%02x %02x %02x %02x\n", __func__,
-               rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
+       dev_dbg(&d->udev->dev, "%s: reply=%*ph\n", __func__, 4, rbuf);
        if (rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])
-               *cold = 0;
+               ret = WARM;
        else
-               *cold = 1;
+               ret = COLD;
 
-       return 0;
+       return ret;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-static int af9035_download_firmware(struct usb_device *udev,
+static int af9035_download_firmware(struct dvb_usb_device *d,
                const struct firmware *fw)
 {
        int ret, i, j, len;
@@ -443,19 +339,19 @@ static int af9035_download_firmware(struct usb_device *udev,
                hdr_checksum = fw->data[fw->size - i + 5] << 8;
                hdr_checksum |= fw->data[fw->size - i + 6] << 0;
 
-               pr_debug("%s: core=%d addr=%04x data_len=%d checksum=%04x\n",
-                               __func__, hdr_core, hdr_addr, hdr_data_len,
-                               hdr_checksum);
+               dev_dbg(&d->udev->dev, "%s: core=%d addr=%04x data_len=%d " \
+                               "checksum=%04x\n", __func__, hdr_core, hdr_addr,
+                               hdr_data_len, hdr_checksum);
 
                if (((hdr_core != 1) && (hdr_core != 2)) ||
                                (hdr_data_len > i)) {
-                       pr_debug("%s: bad firmware\n", __func__);
+                       dev_dbg(&d->udev->dev, "%s: bad firmware\n", __func__);
                        break;
                }
 
                /* download begin packet */
                req.cmd = CMD_FW_DL_BEGIN;
-               ret = af9035_ctrl_msg(udev, &req);
+               ret = af9035_ctrl_msg(d, &req);
                if (ret < 0)
                        goto err;
 
@@ -467,52 +363,54 @@ static int af9035_download_firmware(struct usb_device *udev,
                        req_fw_dl.wlen = len;
                        req_fw_dl.wbuf = (u8 *) &fw->data[fw->size - i +
                                        HDR_SIZE + hdr_data_len - j];
-                       ret = af9035_ctrl_msg(udev, &req_fw_dl);
+                       ret = af9035_ctrl_msg(d, &req_fw_dl);
                        if (ret < 0)
                                goto err;
                }
 
                /* download end packet */
                req.cmd = CMD_FW_DL_END;
-               ret = af9035_ctrl_msg(udev, &req);
+               ret = af9035_ctrl_msg(d, &req);
                if (ret < 0)
                        goto err;
 
                i -= hdr_data_len + HDR_SIZE;
 
-               pr_debug("%s: data uploaded=%zu\n", __func__, fw->size - i);
+               dev_dbg(&d->udev->dev, "%s: data uploaded=%zu\n",
+                               __func__, fw->size - i);
        }
 
        /* firmware loaded, request boot */
        req.cmd = CMD_FW_BOOT;
-       ret = af9035_ctrl_msg(udev, &req);
+       ret = af9035_ctrl_msg(d, &req);
        if (ret < 0)
                goto err;
 
        /* ensure firmware starts */
        wbuf[0] = 1;
-       ret = af9035_ctrl_msg(udev, &req_fw_ver);
+       ret = af9035_ctrl_msg(d, &req_fw_ver);
        if (ret < 0)
                goto err;
 
        if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
-               info("firmware did not run");
+               dev_err(&d->udev->dev, "%s: firmware did not run\n",
+                               KBUILD_MODNAME);
                ret = -ENODEV;
                goto err;
        }
 
-       info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
-                       rbuf[3]);
+       dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d",
+                       KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
 
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-static int af9035_download_firmware_it9135(struct usb_device *udev,
+static int af9035_download_firmware_it9135(struct dvb_usb_device *d,
                const struct firmware *fw)
 {
        int ret, i, i_prev;
@@ -545,47 +443,48 @@ static int af9035_download_firmware_it9135(struct usb_device *udev,
                        req_fw_dl.wlen = i - i_prev;
                        req_fw_dl.wbuf = (u8 *) &fw->data[i_prev];
                        i_prev = i;
-                       ret = af9035_ctrl_msg(udev, &req_fw_dl);
+                       ret = af9035_ctrl_msg(d, &req_fw_dl);
                        if (ret < 0)
                                goto err;
 
-                       pr_debug("%s: data uploaded=%d\n", __func__, i);
+                       dev_dbg(&d->udev->dev, "%s: data uploaded=%d\n",
+                                       __func__, i);
                }
        }
 
        /* firmware loaded, request boot */
        req.cmd = CMD_FW_BOOT;
-       ret = af9035_ctrl_msg(udev, &req);
+       ret = af9035_ctrl_msg(d, &req);
        if (ret < 0)
                goto err;
 
        /* ensure firmware starts */
        wbuf[0] = 1;
-       ret = af9035_ctrl_msg(udev, &req_fw_ver);
+       ret = af9035_ctrl_msg(d, &req_fw_ver);
        if (ret < 0)
                goto err;
 
        if (!(rbuf[0] || rbuf[1] || rbuf[2] || rbuf[3])) {
-               info("firmware did not run");
+               dev_err(&d->udev->dev, "%s: firmware did not run\n",
+                               KBUILD_MODNAME);
                ret = -ENODEV;
                goto err;
        }
 
-       info("firmware version=%d.%d.%d.%d", rbuf[0], rbuf[1], rbuf[2],
-                       rbuf[3]);
+       dev_info(&d->udev->dev, "%s: firmware version=%d.%d.%d.%d",
+                       KBUILD_MODNAME, rbuf[0], rbuf[1], rbuf[2], rbuf[3]);
 
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-/* abuse that callback as there is no better one for reading eeprom */
-static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
+static int af9035_read_config(struct dvb_usb_device *d)
 {
-       struct state *state = d->priv;
+       struct state *state = d_to_priv(d);
        int ret, i, eeprom_shift = 0;
        u8 tmp;
        u16 tmp16;
@@ -596,27 +495,31 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
                goto err;
 
        state->dual_mode = tmp;
-       pr_debug("%s: dual mode=%d\n", __func__, state->dual_mode);
+       dev_dbg(&d->udev->dev, "%s: dual mode=%d\n",
+                       __func__, state->dual_mode);
 
-       for (i = 0; i < af9035_properties[0].num_adapters; i++) {
+       for (i = 0; i < state->dual_mode + 1; i++) {
                /* tuner */
                ret = af9035_rd_reg(d, EEPROM_1_TUNER_ID + eeprom_shift, &tmp);
                if (ret < 0)
                        goto err;
 
                state->af9033_config[i].tuner = tmp;
-               pr_debug("%s: [%d]tuner=%02x\n", __func__, i, tmp);
+               dev_dbg(&d->udev->dev, "%s: [%d]tuner=%02x\n",
+                               __func__, i, tmp);
 
                switch (tmp) {
                case AF9033_TUNER_TUA9001:
                case AF9033_TUNER_FC0011:
                case AF9033_TUNER_MXL5007T:
                case AF9033_TUNER_TDA18218:
+               case AF9033_TUNER_FC2580:
                        state->af9033_config[i].spec_inv = 1;
                        break;
                default:
-                       warn("tuner ID=%02x not supported, please report!",
-                               tmp);
+                       dev_warn(&d->udev->dev, "%s: tuner id=%02x not " \
+                                       "supported, please report!",
+                                       KBUILD_MODNAME, tmp);
                };
 
                /* tuner IF frequency */
@@ -632,7 +535,7 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
 
                tmp16 |= tmp << 8;
 
-               pr_debug("%s: [%d]IF=%d\n", __func__, i, tmp16);
+               dev_dbg(&d->udev->dev, "%s: [%d]IF=%d\n", __func__, i, tmp16);
 
                eeprom_shift = 0x10; /* shift for the 2nd tuner params */
        }
@@ -644,47 +547,20 @@ static int af9035_read_mac_address(struct dvb_usb_device *d, u8 mac[6])
 
        tmp = (tmp >> 0) & 0x0f;
 
-       for (i = 0; i < af9035_properties[0].num_adapters; i++)
+       for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
                state->af9033_config[i].clock = clock_lut[tmp];
 
-       ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
-       if (ret < 0)
-               goto err;
-       pr_debug("%s: ir_mode=%02x\n", __func__, tmp);
-
-       /* don't activate rc if in HID mode or if not available */
-       if (tmp == 5) {
-               ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
-               if (ret < 0)
-                       goto err;
-               pr_debug("%s: ir_type=%02x\n", __func__, tmp);
-
-               switch (tmp) {
-               case 0: /* NEC */
-               default:
-                       d->props.rc.core.protocol = RC_TYPE_NEC;
-                       d->props.rc.core.allowed_protos = RC_TYPE_NEC;
-                       break;
-               case 1: /* RC6 */
-                       d->props.rc.core.protocol = RC_TYPE_RC6;
-                       d->props.rc.core.allowed_protos = RC_TYPE_RC6;
-                       break;
-               }
-               d->props.rc.core.rc_query = af9035_rc_query;
-       }
-
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-/* abuse that callback as there is no better one for reading eeprom */
-static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6])
+static int af9035_read_config_it9135(struct dvb_usb_device *d)
 {
-       struct state *state = d->priv;
+       struct state *state = d_to_priv(d);
        int ret, i;
        u8 tmp;
 
@@ -697,17 +573,63 @@ static int af9035_read_mac_address_it9135(struct dvb_usb_device *d, u8 mac[6])
 
        tmp = (tmp >> 0) & 0x0f;
 
-       for (i = 0; i < af9035_properties[0].num_adapters; i++)
+       for (i = 0; i < ARRAY_SIZE(state->af9033_config); i++)
                state->af9033_config[i].clock = clock_lut_it9135[tmp];
 
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+
+       return ret;
+}
+
+static int af9035_tua9001_tuner_callback(struct dvb_usb_device *d,
+               int cmd, int arg)
+{
+       int ret;
+       u8 val;
+
+       dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg);
+
+       /*
+        * CEN     always enabled by hardware wiring
+        * RESETN  GPIOT3
+        * RXEN    GPIOT2
+        */
+
+       switch (cmd) {
+       case TUA9001_CMD_RESETN:
+               if (arg)
+                       val = 0x00;
+               else
+                       val = 0x01;
+
+               ret = af9035_wr_reg_mask(d, 0x00d8e7, val, 0x01);
+               if (ret < 0)
+                       goto err;
+               break;
+       case TUA9001_CMD_RXEN:
+               if (arg)
+                       val = 0x01;
+               else
+                       val = 0x00;
+
+               ret = af9035_wr_reg_mask(d, 0x00d8eb, val, 0x01);
+               if (ret < 0)
+                       goto err;
+               break;
+       }
+
+       return 0;
+
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
+
 static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
                int cmd, int arg)
 {
@@ -768,23 +690,25 @@ static int af9035_fc0011_tuner_callback(struct dvb_usb_device *d,
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
 static int af9035_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
 {
-       struct state *state = d->priv;
+       struct state *state = d_to_priv(d);
 
        switch (state->af9033_config[0].tuner) {
        case AF9033_TUNER_FC0011:
                return af9035_fc0011_tuner_callback(d, cmd, arg);
+       case AF9033_TUNER_TUA9001:
+               return af9035_tua9001_tuner_callback(d, cmd, arg);
        default:
                break;
        }
 
-       return -ENODEV;
+       return 0;
 }
 
 static int af9035_frontend_callback(void *adapter_priv, int component,
@@ -793,6 +717,9 @@ static int af9035_frontend_callback(void *adapter_priv, int component,
        struct i2c_adapter *adap = adapter_priv;
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
 
+       dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n",
+                       __func__, component, cmd, arg);
+
        switch (component) {
        case DVB_FRONTEND_COMPONENT_TUNER:
                return af9035_tuner_callback(d, cmd, arg);
@@ -800,12 +727,13 @@ static int af9035_frontend_callback(void *adapter_priv, int component,
                break;
        }
 
-       return -EINVAL;
+       return 0;
 }
 
 static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       struct state *state = adap->dev->priv;
+       struct state *state = adap_to_priv(adap);
+       struct dvb_usb_device *d = adap_to_d(adap);
        int ret;
 
        if (!state->af9033_config[adap->id].tuner) {
@@ -818,33 +746,33 @@ static int af9035_frontend_attach(struct dvb_usb_adapter *adap)
                state->af9033_config[0].ts_mode = AF9033_TS_MODE_USB;
                state->af9033_config[1].ts_mode = AF9033_TS_MODE_SERIAL;
 
-               ret = af9035_wr_reg(adap->dev, 0x00417f,
+               ret = af9035_wr_reg(d, 0x00417f,
                                state->af9033_config[1].i2c_addr);
                if (ret < 0)
                        goto err;
 
-               ret = af9035_wr_reg(adap->dev, 0x00d81a,
+               ret = af9035_wr_reg(d, 0x00d81a,
                                state->dual_mode);
                if (ret < 0)
                        goto err;
        }
 
        /* attach demodulator */
-       adap->fe_adap[0].fe = dvb_attach(af9033_attach,
-                       &state->af9033_config[adap->id], &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL) {
+       adap->fe[0] = dvb_attach(af9033_attach,
+                       &state->af9033_config[adap->id], &d->i2c_adap);
+       if (adap->fe[0] == NULL) {
                ret = -ENODEV;
                goto err;
        }
 
        /* disable I2C-gate */
-       adap->fe_adap[0].fe->ops.i2c_gate_ctrl = NULL;
-       adap->fe_adap[0].fe->callback = af9035_frontend_callback;
+       adap->fe[0]->ops.i2c_gate_ctrl = NULL;
+       adap->fe[0]->callback = af9035_frontend_callback;
 
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
@@ -871,9 +799,15 @@ static struct tda18218_config af9035_tda18218_config = {
        .i2c_wr_max = 21,
 };
 
+static const struct fc2580_config af9035_fc2580_config = {
+       .i2c_addr = 0x56,
+       .clock = 16384000,
+};
+
 static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       struct state *state = adap->dev->priv;
+       struct state *state = adap_to_priv(adap);
+       struct dvb_usb_device *d = adap_to_d(adap);
        int ret;
        struct dvb_frontend *fe;
 
@@ -883,93 +817,95 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
                   AF9035 gpiot2 = TUA9001 RXEN */
 
                /* configure gpiot2 and gpiot2 as output */
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8ec, 0x01, 0x01);
+               ret = af9035_wr_reg_mask(d, 0x00d8ec, 0x01, 0x01);
                if (ret < 0)
                        goto err;
 
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8ed, 0x01, 0x01);
+               ret = af9035_wr_reg_mask(d, 0x00d8ed, 0x01, 0x01);
                if (ret < 0)
                        goto err;
 
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8e8, 0x01, 0x01);
+               ret = af9035_wr_reg_mask(d, 0x00d8e8, 0x01, 0x01);
                if (ret < 0)
                        goto err;
 
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8e9, 0x01, 0x01);
-               if (ret < 0)
-                       goto err;
-
-               /* reset tuner */
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x00, 0x01);
-               if (ret < 0)
-                       goto err;
-
-               usleep_range(2000, 20000);
-
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8e7, 0x01, 0x01);
-               if (ret < 0)
-                       goto err;
-
-               /* activate tuner RX */
-               /* TODO: use callback for TUA9001 RXEN */
-               ret = af9035_wr_reg_mask(adap->dev, 0x00d8eb, 0x01, 0x01);
+               ret = af9035_wr_reg_mask(d, 0x00d8e9, 0x01, 0x01);
                if (ret < 0)
                        goto err;
 
                /* attach tuner */
-               fe = dvb_attach(tua9001_attach, adap->fe_adap[0].fe,
-                               &adap->dev->i2c_adap, &af9035_tua9001_config);
+               fe = dvb_attach(tua9001_attach, adap->fe[0],
+                               &d->i2c_adap, &af9035_tua9001_config);
                break;
        case AF9033_TUNER_FC0011:
-               fe = dvb_attach(fc0011_attach, adap->fe_adap[0].fe,
-                               &adap->dev->i2c_adap, &af9035_fc0011_config);
+               fe = dvb_attach(fc0011_attach, adap->fe[0],
+                               &d->i2c_adap, &af9035_fc0011_config);
                break;
        case AF9033_TUNER_MXL5007T:
-               ret = af9035_wr_reg(adap->dev, 0x00d8e0, 1);
+               ret = af9035_wr_reg(d, 0x00d8e0, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8e1, 1);
+               ret = af9035_wr_reg(d, 0x00d8e1, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8df, 0);
+               ret = af9035_wr_reg(d, 0x00d8df, 0);
                if (ret < 0)
                        goto err;
 
                msleep(30);
 
-               ret = af9035_wr_reg(adap->dev, 0x00d8df, 1);
+               ret = af9035_wr_reg(d, 0x00d8df, 1);
                if (ret < 0)
                        goto err;
 
                msleep(300);
 
-               ret = af9035_wr_reg(adap->dev, 0x00d8c0, 1);
+               ret = af9035_wr_reg(d, 0x00d8c0, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8c1, 1);
+               ret = af9035_wr_reg(d, 0x00d8c1, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8bf, 0);
+               ret = af9035_wr_reg(d, 0x00d8bf, 0);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8b4, 1);
+               ret = af9035_wr_reg(d, 0x00d8b4, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8b5, 1);
+               ret = af9035_wr_reg(d, 0x00d8b5, 1);
                if (ret < 0)
                        goto err;
-               ret = af9035_wr_reg(adap->dev, 0x00d8b3, 1);
+               ret = af9035_wr_reg(d, 0x00d8b3, 1);
                if (ret < 0)
                        goto err;
 
                /* attach tuner */
-               fe = dvb_attach(mxl5007t_attach, adap->fe_adap[0].fe,
-                               &adap->dev->i2c_adap, 0x60, &af9035_mxl5007t_config);
+               fe = dvb_attach(mxl5007t_attach, adap->fe[0],
+                               &d->i2c_adap, 0x60, &af9035_mxl5007t_config);
                break;
        case AF9033_TUNER_TDA18218:
                /* attach tuner */
-               fe = dvb_attach(tda18218_attach, adap->fe_adap[0].fe,
-                               &adap->dev->i2c_adap, &af9035_tda18218_config);
+               fe = dvb_attach(tda18218_attach, adap->fe[0],
+                               &d->i2c_adap, &af9035_tda18218_config);
+               break;
+       case AF9033_TUNER_FC2580:
+               /* Tuner enable using gpiot2_o, gpiot2_en and gpiot2_on  */
+               ret = af9035_wr_reg_mask(d, 0xd8eb, 0x01, 0x01);
+               if (ret < 0)
+                       goto err;
+
+               ret = af9035_wr_reg_mask(d, 0xd8ec, 0x01, 0x01);
+               if (ret < 0)
+                       goto err;
+
+               ret = af9035_wr_reg_mask(d, 0xd8ed, 0x01, 0x01);
+               if (ret < 0)
+                       goto err;
+
+               usleep_range(10000, 50000);
+               /* attach tuner */
+               fe = dvb_attach(fc2580_attach, adap->fe[0],
+                               &d->i2c_adap, &af9035_fc2580_config);
                break;
        default:
                fe = NULL;
@@ -983,256 +919,234 @@ static int af9035_tuner_attach(struct dvb_usb_adapter *adap)
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-enum af9035_id_entry {
-       AF9035_15A4_9035,
-       AF9035_15A4_1000,
-       AF9035_15A4_1001,
-       AF9035_15A4_1002,
-       AF9035_15A4_1003,
-       AF9035_0CCD_0093,
-       AF9035_07CA_A835,
-       AF9035_07CA_B835,
-       AF9035_07CA_1867,
-       AF9035_07CA_A867,
-       AF9035_07CA_0825,
-};
-
-static struct usb_device_id af9035_id[] = {
-       [AF9035_15A4_9035] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035)},
-       [AF9035_15A4_1000] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000)},
-       [AF9035_15A4_1001] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001)},
-       [AF9035_15A4_1002] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002)},
-       [AF9035_15A4_1003] = {
-               USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003)},
-       [AF9035_0CCD_0093] = {
-               USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK)},
-       [AF9035_07CA_A835] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835)},
-       [AF9035_07CA_B835] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835)},
-       [AF9035_07CA_1867] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867)},
-       [AF9035_07CA_A867] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867)},
-       [AF9035_07CA_0825] = {
-               USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR)},
-       {},
-};
+static int af9035_init(struct dvb_usb_device *d)
+{
+       struct state *state = d_to_priv(d);
+       int ret, i;
+       u16 frame_size = 87 * 188 / 4;
+       u8  packet_size = 512 / 4;
+       struct reg_val_mask tab[] = {
+               { 0x80f99d, 0x01, 0x01 },
+               { 0x80f9a4, 0x01, 0x01 },
+               { 0x00dd11, 0x00, 0x20 },
+               { 0x00dd11, 0x00, 0x40 },
+               { 0x00dd13, 0x00, 0x20 },
+               { 0x00dd13, 0x00, 0x40 },
+               { 0x00dd11, 0x20, 0x20 },
+               { 0x00dd88, (frame_size >> 0) & 0xff, 0xff},
+               { 0x00dd89, (frame_size >> 8) & 0xff, 0xff},
+               { 0x00dd0c, packet_size, 0xff},
+               { 0x00dd11, state->dual_mode << 6, 0x40 },
+               { 0x00dd8a, (frame_size >> 0) & 0xff, 0xff},
+               { 0x00dd8b, (frame_size >> 8) & 0xff, 0xff},
+               { 0x00dd0d, packet_size, 0xff },
+               { 0x80f9a3, 0x00, 0x01 },
+               { 0x80f9cd, 0x00, 0x01 },
+               { 0x80f99d, 0x00, 0x01 },
+               { 0x80f9a4, 0x00, 0x01 },
+       };
 
-MODULE_DEVICE_TABLE(usb, af9035_id);
-
-static struct dvb_usb_device_properties af9035_properties[] = {
-       {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .download_firmware = af9035_download_firmware,
-               .firmware = "dvb-usb-af9035-02.fw",
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct state),
-
-               .num_adapters = 1,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = af9035_frontend_attach,
-                                               .tuner_attach = af9035_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x84,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = (87 * 188),
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
+       dev_dbg(&d->udev->dev, "%s: USB speed=%d frame_size=%04x " \
+                       "packet_size=%02x\n", __func__,
+                       d->udev->speed, frame_size, packet_size);
 
-               .identify_state = af9035_identify_state,
-               .read_mac_address = af9035_read_mac_address,
+       /* init endpoints */
+       for (i = 0; i < ARRAY_SIZE(tab); i++) {
+               ret = af9035_wr_reg_mask(d, tab[i].reg, tab[i].val,
+                               tab[i].mask);
+               if (ret < 0)
+                       goto err;
+       }
 
-               .i2c_algo = &af9035_i2c_algo,
+       return 0;
 
-               .rc.core = {
-                       .protocol       = RC_TYPE_UNKNOWN,
-                       .module_name    = "af9035",
-                       .rc_query       = NULL,
-                       .rc_interval    = AF9035_POLL,
-                       .allowed_protos = RC_TYPE_UNKNOWN,
-                       .rc_codes       = RC_MAP_EMPTY,
-               },
-               .num_device_descs = 5,
-               .devices = {
-                       {
-                               .name = "Afatech AF9035 reference design",
-                               .cold_ids = {
-                                       &af9035_id[AF9035_15A4_9035],
-                                       &af9035_id[AF9035_15A4_1000],
-                                       &af9035_id[AF9035_15A4_1001],
-                                       &af9035_id[AF9035_15A4_1002],
-                                       &af9035_id[AF9035_15A4_1003],
-                               },
-                       }, {
-                               .name = "TerraTec Cinergy T Stick",
-                               .cold_ids = {
-                                       &af9035_id[AF9035_0CCD_0093],
-                               },
-                       }, {
-                               .name = "AVerMedia AVerTV Volar HD/PRO (A835)",
-                               .cold_ids = {
-                                       &af9035_id[AF9035_07CA_A835],
-                                       &af9035_id[AF9035_07CA_B835],
-                               },
-                       }, {
-                               .name = "AVerMedia HD Volar (A867)",
-                               .cold_ids = {
-                                       &af9035_id[AF9035_07CA_1867],
-                                       &af9035_id[AF9035_07CA_A867],
-                               },
-                       }, {
-                               .name = "AVerMedia Twinstar (A825)",
-                               .cold_ids = {
-                                       &af9035_id[AF9035_07CA_0825],
-                               },
-                       },
-               }
-       },
-       {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .download_firmware = af9035_download_firmware_it9135,
-               .firmware = "dvb-usb-it9135-01.fw",
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct state),
-
-               .num_adapters = 1,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = af9035_frontend_attach,
-                                               .tuner_attach = af9035_tuner_attach,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x84,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = (87 * 188),
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
-               .identify_state = af9035_identify_state,
-               .read_mac_address = af9035_read_mac_address_it9135,
+       return ret;
+}
 
-               .i2c_algo = &af9035_i2c_algo,
+static int af9035_rc_query(struct dvb_usb_device *d)
+{
+       unsigned int key;
+       unsigned char b[4];
+       int ret;
+       struct usb_req req = { CMD_IR_GET, 0, 0, NULL, 4, b };
 
-               .num_device_descs = 0, /* disabled as no support for IT9135 */
-               .devices = {
-                       {
-                               .name = "ITE Tech. IT9135 reference design",
-                       },
-               }
-       },
-};
+       ret = af9035_ctrl_msg(d, &req);
+       if (ret < 0)
+               goto err;
 
-static int af9035_usb_probe(struct usb_interface *intf,
-                           const struct usb_device_id *id)
-{
-       int ret, i;
-       struct dvb_usb_device *d = NULL;
-       struct usb_device *udev;
-       bool found;
-
-       pr_debug("%s: interface=%d\n", __func__,
-                       intf->cur_altsetting->desc.bInterfaceNumber);
-
-       /* interface 0 is used by DVB-T receiver and
-          interface 1 is for remote controller (HID) */
-       if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-               return 0;
-
-       /* Dynamic USB ID support. Replaces first device ID with current one. */
-       udev = interface_to_usbdev(intf);
-
-       for (i = 0, found = false; i < ARRAY_SIZE(af9035_id) - 1; i++) {
-               if (af9035_id[i].idVendor ==
-                               le16_to_cpu(udev->descriptor.idVendor) &&
-                               af9035_id[i].idProduct ==
-                               le16_to_cpu(udev->descriptor.idProduct)) {
-                       found = true;
-                       break;
+       if ((b[2] + b[3]) == 0xff) {
+               if ((b[0] + b[1]) == 0xff) {
+                       /* NEC */
+                       key = b[0] << 8 | b[2];
+               } else {
+                       /* ext. NEC */
+                       key = b[0] << 16 | b[1] << 8 | b[2];
                }
+       } else {
+               key = b[0] << 24 | b[1] << 16 | b[2] << 8 | b[3];
        }
 
-       if (!found) {
-               pr_debug("%s: using dynamic ID %04x:%04x\n", __func__,
-                               le16_to_cpu(udev->descriptor.idVendor),
-                               le16_to_cpu(udev->descriptor.idProduct));
-               af9035_properties[0].devices[0].cold_ids[0]->idVendor =
-                               le16_to_cpu(udev->descriptor.idVendor);
-               af9035_properties[0].devices[0].cold_ids[0]->idProduct =
-                               le16_to_cpu(udev->descriptor.idProduct);
-       }
-
+       rc_keydown(d->rc_dev, key, 0);
 
-       for (i = 0; i < af9035_properties_count; i++) {
-               ret = dvb_usb_device_init(intf, &af9035_properties[i],
-                               THIS_MODULE, &d, adapter_nr);
+err:
+       /* ignore errors */
+       return 0;
+}
 
-               if (ret == -ENODEV)
-                       continue;
-               else
-                       break;
-       }
+static int af9035_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
+{
+       int ret;
+       u8 tmp;
 
+       ret = af9035_rd_reg(d, EEPROM_IR_MODE, &tmp);
        if (ret < 0)
                goto err;
 
-       if (d) {
-               ret = af9035_init(d);
+       dev_dbg(&d->udev->dev, "%s: ir_mode=%02x\n", __func__, tmp);
+
+       /* don't activate rc if in HID mode or if not available */
+       if (tmp == 5) {
+               ret = af9035_rd_reg(d, EEPROM_IR_TYPE, &tmp);
                if (ret < 0)
                        goto err;
+
+               dev_dbg(&d->udev->dev, "%s: ir_type=%02x\n", __func__, tmp);
+
+               switch (tmp) {
+               case 0: /* NEC */
+               default:
+                       rc->allowed_protos = RC_TYPE_NEC;
+                       break;
+               case 1: /* RC6 */
+                       rc->allowed_protos = RC_TYPE_RC6;
+                       break;
+               }
+
+               rc->query = af9035_rc_query;
+               rc->interval = 500;
+
+               /* load empty to enable rc */
+               if (!rc->map_name)
+                       rc->map_name = RC_MAP_EMPTY;
        }
 
        return 0;
 
 err:
-       pr_debug("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
 
        return ret;
 }
 
-/* usb specific object needed to register this driver with the usb subsystem */
+/* interface 0 is used by DVB-T receiver and
+   interface 1 is for remote controller (HID) */
+static const struct dvb_usb_device_properties af9035_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .identify_state = af9035_identify_state,
+       .firmware = AF9035_FIRMWARE_AF9035,
+       .download_firmware = af9035_download_firmware,
+
+       .i2c_algo = &af9035_i2c_algo,
+       .read_config = af9035_read_config,
+       .frontend_attach = af9035_frontend_attach,
+       .tuner_attach = af9035_tuner_attach,
+       .init = af9035_init,
+       .get_rc_config = af9035_get_rc_config,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
+               }, {
+                       .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
+               },
+       },
+};
+
+static const struct dvb_usb_device_properties it9135_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .identify_state = af9035_identify_state,
+       .firmware = AF9035_FIRMWARE_IT9135,
+       .download_firmware = af9035_download_firmware_it9135,
+
+       .i2c_algo = &af9035_i2c_algo,
+       .read_config = af9035_read_config_it9135,
+       .frontend_attach = af9035_frontend_attach,
+       .tuner_attach = af9035_tuner_attach,
+       .init = af9035_init,
+       .get_rc_config = af9035_get_rc_config,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_BULK(0x84, 6, 87 * 188),
+               }, {
+                       .stream = DVB_USB_STREAM_BULK(0x85, 6, 87 * 188),
+               },
+       },
+};
+
+static const struct usb_device_id af9035_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_9035,
+               &af9035_props, "Afatech AF9035 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1000,
+               &af9035_props, "Afatech AF9035 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1001,
+               &af9035_props, "Afatech AF9035 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1002,
+               &af9035_props, "Afatech AF9035 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AFATECH, USB_PID_AFATECH_AF9035_1003,
+               &af9035_props, "Afatech AF9035 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK,
+               &af9035_props, "TerraTec Cinergy T Stick", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A835,
+               &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_B835,
+               &af9035_props, "AVerMedia AVerTV Volar HD/PRO (A835)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_1867,
+               &af9035_props, "AVerMedia HD Volar (A867)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A867,
+               &af9035_props, "AVerMedia HD Volar (A867)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_TWINSTAR,
+               &af9035_props, "AVerMedia Twinstar (A825)", NULL) },
+       { DVB_USB_DEVICE(USB_VID_ASUS, USB_PID_ASUS_U3100MINI_PLUS,
+               &af9035_props, "Asus U3100Mini Plus", NULL) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, af9035_id_table);
+
 static struct usb_driver af9035_usb_driver = {
-       .name = "dvb_usb_af9035",
-       .probe = af9035_usb_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table = af9035_id,
+       .name = KBUILD_MODNAME,
+       .id_table = af9035_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
 module_usb_driver(af9035_usb_driver);
@@ -1240,3 +1154,5 @@ module_usb_driver(af9035_usb_driver);
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Afatech AF9035 driver");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(AF9035_FIRMWARE_AF9035);
+MODULE_FIRMWARE(AF9035_FIRMWARE_IT9135);
similarity index 93%
rename from drivers/media/dvb/dvb-usb/af9035.h
rename to drivers/media/usb/dvb-usb-v2/af9035.h
index 481a1a43dd2a65909ad9846f4b9332aa95f98bb4..75ef1ec13fbf0afecdf6560c95148153ec08d3d0 100644 (file)
 #ifndef AF9035_H
 #define AF9035_H
 
-/* prefix for dvb-usb log writings */
-#define DVB_USB_LOG_PREFIX "af9035"
-
-#include "dvb-usb.h"
+#include "dvb_usb.h"
 #include "af9033.h"
 #include "tua9001.h"
 #include "fc0011.h"
 #include "mxl5007t.h"
 #include "tda18218.h"
+#include "fc2580.h"
 
 struct reg_val {
        u32 reg;
@@ -53,6 +51,7 @@ struct usb_req {
 };
 
 struct state {
+       u8 seq; /* packet sequence number */
        bool dual_mode;
 
        struct af9033_config af9033_config[2];
@@ -86,6 +85,9 @@ u32 clock_lut_it9135[] = {
        22000000, /* 22.00 MHz */
 };
 
+#define AF9035_FIRMWARE_AF9035 "dvb-usb-af9035-02.fw"
+#define AF9035_FIRMWARE_IT9135 "dvb-usb-it9135-01.fw"
+
 /* EEPROM locations */
 #define EEPROM_IR_MODE            0x430d
 #define EEPROM_DUAL_MODE          0x4326
similarity index 67%
rename from drivers/media/dvb/dvb-usb/anysee.c
rename to drivers/media/usb/dvb-usb-v2/anysee.c
index 03c28655af1be54eec6e10486ab5fa71ccc58787..ec540140c81037ffb0317a3d726fbd30e58fa94e 100644 (file)
@@ -32,6 +32,7 @@
  */
 
 #include "anysee.h"
+#include "dvb-pll.h"
 #include "tda1002x.h"
 #include "mt352.h"
 #include "mt352_priv.h"
 #include "isl6423.h"
 #include "cxd2820r.h"
 
-/* debug */
-static int dvb_usb_anysee_debug;
-module_param_named(debug, dvb_usb_anysee_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
-static int dvb_usb_anysee_delsys;
-module_param_named(delsys, dvb_usb_anysee_delsys, int, 0644);
-MODULE_PARM_DESC(delsys, "select delivery mode (0=DVB-C, 1=DVB-T)");
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
-
 static DEFINE_MUTEX(anysee_usb_mutex);
 
 static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        u8 *rbuf, u8 rlen)
 {
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
        int act_len, ret, i;
        u8 buf[64];
 
        memcpy(&buf[0], sbuf, slen);
        buf[60] = state->seq++;
 
-       if (mutex_lock_interruptible(&anysee_usb_mutex) < 0)
-               return -EAGAIN;
+       mutex_lock(&anysee_usb_mutex);
 
-       deb_xfer(">>> ");
-       debug_dump(buf, slen, deb_xfer);
+       dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, slen, buf);
 
        /* We need receive one message more after dvb_usb_generic_rw due
           to weird transaction flow, which is 1 x send + 2 x receive. */
-       ret = dvb_usb_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf), 0);
+       ret = dvb_usbv2_generic_rw(d, buf, sizeof(buf), buf, sizeof(buf));
        if (ret)
                goto error_unlock;
 
@@ -91,18 +82,19 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
        for (i = 0; i < 3; i++) {
                /* receive 2nd answer */
                ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
-                       d->props.generic_bulk_ctrl_endpoint), buf, sizeof(buf),
+                       d->props->generic_bulk_ctrl_endpoint), buf, sizeof(buf),
                        &act_len, 2000);
 
                if (ret) {
-                       deb_info("%s: recv bulk message failed: %d",
-                                       __func__, ret);
+                       dev_dbg(&d->udev->dev, "%s: recv bulk message " \
+                                       "failed=%d\n", __func__, ret);
                } else {
-                       deb_xfer("<<< ");
-                       debug_dump(buf, rlen, deb_xfer);
+                       dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
+                                       rlen, buf);
 
                        if (buf[63] != 0x4f)
-                               deb_info("%s: cmd failed\n", __func__);
+                               dev_dbg(&d->udev->dev, "%s: cmd failed\n",
+                                               __func__);
 
                        break;
                }
@@ -110,7 +102,8 @@ static int anysee_ctrl_msg(struct dvb_usb_device *d, u8 *sbuf, u8 slen,
 
        if (ret) {
                /* all retries failed, it is fatal */
-               err("%s: recv bulk message failed: %d", __func__, ret);
+               dev_err(&d->udev->dev, "%s: recv bulk message failed=%d\n",
+                               KBUILD_MODNAME, ret);
                goto error_unlock;
        }
 
@@ -129,14 +122,14 @@ static int anysee_read_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
        u8 buf[] = {CMD_REG_READ, reg >> 8, reg & 0xff, 0x01};
        int ret;
        ret = anysee_ctrl_msg(d, buf, sizeof(buf), val, 1);
-       deb_info("%s: reg:%04x val:%02x\n", __func__, reg, *val);
+       dev_dbg(&d->udev->dev, "%s: reg=%04x val=%02x\n", __func__, reg, *val);
        return ret;
 }
 
 static int anysee_write_reg(struct dvb_usb_device *d, u16 reg, u8 val)
 {
        u8 buf[] = {CMD_REG_WRITE, reg >> 8, reg & 0xff, 0x01, val};
-       deb_info("%s: reg:%04x val:%02x\n", __func__, reg, val);
+       dev_dbg(&d->udev->dev, "%s: reg=%04x val=%02x\n", __func__, reg, val);
        return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
@@ -190,24 +183,25 @@ static int anysee_get_hw_info(struct dvb_usb_device *d, u8 *id)
        return anysee_ctrl_msg(d, buf, sizeof(buf), id, 3);
 }
 
-static int anysee_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+static int anysee_streaming_ctrl(struct dvb_frontend *fe, int onoff)
 {
        u8 buf[] = {CMD_STREAMING_CTRL, (u8)onoff, 0x00};
-       deb_info("%s: onoff:%02x\n", __func__, onoff);
-       return anysee_ctrl_msg(adap->dev, buf, sizeof(buf), NULL, 0);
+       dev_dbg(&fe_to_d(fe)->udev->dev, "%s: onoff=%d\n", __func__, onoff);
+       return anysee_ctrl_msg(fe_to_d(fe), buf, sizeof(buf), NULL, 0);
 }
 
 static int anysee_led_ctrl(struct dvb_usb_device *d, u8 mode, u8 interval)
 {
        u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x01, mode, interval};
-       deb_info("%s: state:%02x interval:%02x\n", __func__, mode, interval);
+       dev_dbg(&d->udev->dev, "%s: state=%d interval=%d\n", __func__,
+                       mode, interval);
        return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
 static int anysee_ir_ctrl(struct dvb_usb_device *d, u8 onoff)
 {
        u8 buf[] = {CMD_LED_AND_IR_CTRL, 0x02, onoff};
-       deb_info("%s: onoff:%02x\n", __func__, onoff);
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
        return anysee_ctrl_msg(d, buf, sizeof(buf), NULL, 0);
 }
 
@@ -509,23 +503,48 @@ static struct cxd2820r_config anysee_cxd2820r_config = {
  * IOE[5] STV0903 1=enabled
  */
 
+static int anysee_read_config(struct dvb_usb_device *d)
+{
+       struct anysee_state *state = d_to_priv(d);
+       int ret;
+       u8 hw_info[3];
+
+       /*
+        * Check which hardware we have.
+        * We must do this call two times to get reliable values (hw/fw bug).
+        */
+       ret = anysee_get_hw_info(d, hw_info);
+       if (ret)
+               goto error;
+
+       ret = anysee_get_hw_info(d, hw_info);
+       if (ret)
+               goto error;
+
+       /*
+        * Meaning of these info bytes are guessed.
+        */
+       dev_info(&d->udev->dev, "%s: firmware version %d.%d hardware id %d\n",
+                       KBUILD_MODNAME, hw_info[1], hw_info[2], hw_info[0]);
+
+       state->hw = hw_info[0];
+error:
+       return ret;
+}
 
 /* external I2C gate used for DNOD44CDH086A(TDA18212) tuner module */
 static int anysee_i2c_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-
        /* enable / disable tuner access on IOE[4] */
-       return anysee_wr_reg_mask(adap->dev, REG_IOE, (enable << 4), 0x10);
+       return anysee_wr_reg_mask(fe_to_d(fe), REG_IOE, (enable << 4), 0x10);
 }
 
 static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct anysee_state *state = adap->dev->priv;
+       struct anysee_state *state = fe_to_priv(fe);
+       struct dvb_usb_device *d = fe_to_d(fe);
        int ret;
-
-       deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+       dev_dbg(&d->udev->dev, "%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
 
        /* no frontend sleep control */
        if (onoff == 0)
@@ -536,40 +555,34 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
                /* E30 Combo Plus */
                /* E30 C Plus */
 
-               if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+               if (fe->id == 0)  {
                        /* disable DVB-T demod on IOD[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01);
                        if (ret)
                                goto error;
 
                        /* enable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-                               0x20);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20);
                        if (ret)
                                goto error;
 
                        /* enable DVB-C tuner on IOE[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01);
                        if (ret)
                                goto error;
                } else {
                        /* disable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-                               0x20);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20);
                        if (ret)
                                goto error;
 
                        /* enable DVB-T demod on IOD[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01);
                        if (ret)
                                goto error;
 
                        /* enable DVB-T tuner on IOE[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01);
                        if (ret)
                                goto error;
                }
@@ -580,40 +593,34 @@ static int anysee_frontend_ctrl(struct dvb_frontend *fe, int onoff)
                /* E7 TC */
                /* E7 PTC */
 
-               if ((fe->id ^ dvb_usb_anysee_delsys) == 0)  {
+               if (fe->id == 0)  {
                        /* disable DVB-T demod on IOD[6] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-                               0x40);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40);
                        if (ret)
                                goto error;
 
                        /* enable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-                               0x20);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20);
                        if (ret)
                                goto error;
 
                        /* enable IF route on IOE[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 0), 0x01);
                        if (ret)
                                goto error;
                } else {
                        /* disable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-                               0x20);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20);
                        if (ret)
                                goto error;
 
                        /* enable DVB-T demod on IOD[6] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
-                               0x40);
+                       ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40);
                        if (ret)
                                goto error;
 
                        /* enable IF route on IOE[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 0),
-                               0x01);
+                       ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 0), 0x01);
                        if (ret)
                                goto error;
                }
@@ -629,9 +636,9 @@ error:
 
 static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
 {
+       struct anysee_state *state = adap_to_priv(adap);
+       struct dvb_usb_device *d = adap_to_d(adap);
        int ret;
-       struct anysee_state *state = adap->dev->priv;
-       u8 hw_info[3];
        u8 tmp;
        struct i2c_msg msg[2] = {
                {
@@ -647,100 +654,63 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                }
        };
 
-       /* detect hardware only once */
-       if (adap->fe_adap[0].fe == NULL) {
-               /* Check which hardware we have.
-                * We must do this call two times to get reliable values
-                * (hw/fw bug).
-                */
-               ret = anysee_get_hw_info(adap->dev, hw_info);
-               if (ret)
-                       goto error;
-
-               ret = anysee_get_hw_info(adap->dev, hw_info);
-               if (ret)
-                       goto error;
-
-               /* Meaning of these info bytes are guessed. */
-               info("firmware version:%d.%d hardware id:%d",
-                       hw_info[1], hw_info[2], hw_info[0]);
-
-               state->hw = hw_info[0];
-       }
-
-       /* set current frondend ID for devices having two frondends */
-       if (adap->fe_adap[0].fe)
-               state->fe_id++;
-
        switch (state->hw) {
        case ANYSEE_HW_507T: /* 2 */
                /* E30 */
 
-               if (state->fe_id)
-                       break;
-
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(mt352_attach,
-                       &anysee_mt352_config, &adap->dev->i2c_adap);
-               if (adap->fe_adap[0].fe)
+               adap->fe[0] = dvb_attach(mt352_attach, &anysee_mt352_config,
+                               &d->i2c_adap);
+               if (adap->fe[0])
                        break;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-                       &anysee_zl10353_config, &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                               &d->i2c_adap);
 
                break;
        case ANYSEE_HW_507CD: /* 6 */
                /* E30 Plus */
 
-               if (state->fe_id)
-                       break;
-
                /* enable DVB-T demod on IOD[0] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01);
                if (ret)
                        goto error;
 
                /* enable transport stream on IOA[7] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOA, (0 << 7), 0x80);
+               ret = anysee_wr_reg_mask(d, REG_IOA, (0 << 7), 0x80);
                if (ret)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(zl10353_attach,
-                       &anysee_zl10353_config, &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(zl10353_attach, &anysee_zl10353_config,
+                               &d->i2c_adap);
 
                break;
        case ANYSEE_HW_507DC: /* 10 */
                /* E30 C Plus */
 
-               if (state->fe_id)
-                       break;
-
                /* enable DVB-C demod on IOD[0] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01);
                if (ret)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(tda10023_attach,
-                       &anysee_tda10023_config, &adap->dev->i2c_adap, 0x48);
+               adap->fe[0] = dvb_attach(tda10023_attach,
+                               &anysee_tda10023_config, &d->i2c_adap, 0x48);
 
                break;
        case ANYSEE_HW_507SI: /* 11 */
                /* E30 S2 Plus */
 
-               if (state->fe_id)
-                       break;
-
                /* enable DVB-S/S2 demod on IOD[0] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0), 0x01);
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01);
                if (ret)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(cx24116_attach,
-                       &anysee_cx24116_config, &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(cx24116_attach, &anysee_cx24116_config,
+                               &d->i2c_adap);
 
                break;
        case ANYSEE_HW_507FA: /* 15 */
@@ -748,84 +718,82 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                /* E30 C Plus */
 
                /* enable tuner on IOE[4] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 4), 0x10);
+               ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 4), 0x10);
                if (ret)
                        goto error;
 
                /* probe TDA18212 */
                tmp = 0;
-               ret = i2c_transfer(&adap->dev->i2c_adap, msg, 2);
+               ret = i2c_transfer(&d->i2c_adap, msg, 2);
                if (ret == 2 && tmp == 0xc7)
-                       deb_info("%s: TDA18212 found\n", __func__);
+                       dev_dbg(&d->udev->dev, "%s: TDA18212 found\n",
+                                       __func__);
                else
                        tmp = 0;
 
                /* disable tuner on IOE[4] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (0 << 4), 0x10);
+               ret = anysee_wr_reg_mask(d, REG_IOE, (0 << 4), 0x10);
                if (ret)
                        goto error;
 
-               if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
-                       /* disable DVB-T demod on IOD[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 0),
-                               0x01);
-                       if (ret)
-                               goto error;
+               /* disable DVB-T demod on IOD[0] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 0), 0x01);
+               if (ret)
+                       goto error;
 
-                       /* enable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-                               0x20);
-                       if (ret)
-                               goto error;
+               /* enable DVB-C demod on IOD[5] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20);
+               if (ret)
+                       goto error;
 
-                       /* attach demod */
-                       if (tmp == 0xc7) {
-                               /* TDA18212 config */
-                               adap->fe_adap[state->fe_id].fe = dvb_attach(
-                                       tda10023_attach,
+               /* attach demod */
+               if (tmp == 0xc7) {
+                       /* TDA18212 config */
+                       adap->fe[0] = dvb_attach(tda10023_attach,
                                        &anysee_tda10023_tda18212_config,
-                                       &adap->dev->i2c_adap, 0x48);
-                       } else {
-                               /* PLL config */
-                               adap->fe_adap[state->fe_id].fe = dvb_attach(
-                                       tda10023_attach,
-                                       &anysee_tda10023_config,
-                                       &adap->dev->i2c_adap, 0x48);
-                       }
+                                       &d->i2c_adap, 0x48);
+
+                       /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+                       if (adap->fe[0])
+                               adap->fe[0]->ops.i2c_gate_ctrl =
+                                               anysee_i2c_gate_ctrl;
                } else {
-                       /* disable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-                               0x20);
-                       if (ret)
-                               goto error;
+                       /* PLL config */
+                       adap->fe[0] = dvb_attach(tda10023_attach,
+                                       &anysee_tda10023_config,
+                                       &d->i2c_adap, 0x48);
+               }
 
-                       /* enable DVB-T demod on IOD[0] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 0),
-                               0x01);
-                       if (ret)
-                               goto error;
+               /* break out if first frontend attaching fails */
+               if (!adap->fe[0])
+                       break;
 
-                       /* attach demod */
-                       if (tmp == 0xc7) {
-                               /* TDA18212 config */
-                               adap->fe_adap[state->fe_id].fe = dvb_attach(
-                                       zl10353_attach,
-                                       &anysee_zl10353_tda18212_config2,
-                                       &adap->dev->i2c_adap);
-                       } else {
-                               /* PLL config */
-                               adap->fe_adap[state->fe_id].fe = dvb_attach(
-                                       zl10353_attach,
-                                       &anysee_zl10353_config,
-                                       &adap->dev->i2c_adap);
-                       }
-               }
+               /* disable DVB-C demod on IOD[5] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20);
+               if (ret)
+                       goto error;
 
-               /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+               /* enable DVB-T demod on IOD[0] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 0), 0x01);
+               if (ret)
+                       goto error;
+
+               /* attach demod */
                if (tmp == 0xc7) {
-                       if (adap->fe_adap[state->fe_id].fe)
-                               adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
-                                       anysee_i2c_gate_ctrl;
+                       /* TDA18212 config */
+                       adap->fe[1] = dvb_attach(zl10353_attach,
+                                       &anysee_zl10353_tda18212_config2,
+                                       &d->i2c_adap);
+
+                       /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+                       if (adap->fe[1])
+                               adap->fe[1]->ops.i2c_gate_ctrl =
+                                               anysee_i2c_gate_ctrl;
+               } else {
+                       /* PLL config */
+                       adap->fe[1] = dvb_attach(zl10353_attach,
+                                       &anysee_zl10353_config,
+                                       &d->i2c_adap);
                }
 
                break;
@@ -834,48 +802,47 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                /* E7 TC */
                /* E7 PTC */
 
-               if ((state->fe_id ^ dvb_usb_anysee_delsys) == 0)  {
-                       /* disable DVB-T demod on IOD[6] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 6),
-                               0x40);
-                       if (ret)
-                               goto error;
+               /* disable DVB-T demod on IOD[6] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 6), 0x40);
+               if (ret)
+                       goto error;
 
-                       /* enable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 5),
-                               0x20);
-                       if (ret)
-                               goto error;
+               /* enable DVB-C demod on IOD[5] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 5), 0x20);
+               if (ret)
+                       goto error;
 
-                       /* attach demod */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(tda10023_attach,
+               /* attach demod */
+               adap->fe[0] = dvb_attach(tda10023_attach,
                                &anysee_tda10023_tda18212_config,
-                               &adap->dev->i2c_adap, 0x48);
-               } else {
-                       /* disable DVB-C demod on IOD[5] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (0 << 5),
-                               0x20);
-                       if (ret)
-                               goto error;
+                               &d->i2c_adap, 0x48);
 
-                       /* enable DVB-T demod on IOD[6] */
-                       ret = anysee_wr_reg_mask(adap->dev, REG_IOD, (1 << 6),
-                               0x40);
-                       if (ret)
-                               goto error;
+               /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
+               if (adap->fe[0])
+                       adap->fe[0]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl;
+
+               /* break out if first frontend attaching fails */
+               if (!adap->fe[0])
+                       break;
+
+               /* disable DVB-C demod on IOD[5] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (0 << 5), 0x20);
+               if (ret)
+                       goto error;
 
-                       /* attach demod */
-                       adap->fe_adap[state->fe_id].fe =
-                               dvb_attach(zl10353_attach,
+               /* enable DVB-T demod on IOD[6] */
+               ret = anysee_wr_reg_mask(d, REG_IOD, (1 << 6), 0x40);
+               if (ret)
+                       goto error;
+
+               /* attach demod */
+               adap->fe[1] = dvb_attach(zl10353_attach,
                                &anysee_zl10353_tda18212_config,
-                               &adap->dev->i2c_adap);
-               }
+                               &d->i2c_adap);
 
                /* I2C gate for DNOD44CDH086A(TDA18212) tuner module */
-               if (adap->fe_adap[state->fe_id].fe)
-                       adap->fe_adap[state->fe_id].fe->ops.i2c_gate_ctrl =
-                               anysee_i2c_gate_ctrl;
+               if (adap->fe[1])
+                       adap->fe[1]->ops.i2c_gate_ctrl = anysee_i2c_gate_ctrl;
 
                state->has_ci = true;
 
@@ -885,17 +852,14 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
                /* E7 S2 */
                /* E7 PS2 */
 
-               if (state->fe_id)
-                       break;
-
                /* enable DVB-S/S2 demod on IOE[5] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
+               ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[0].fe = dvb_attach(stv0900_attach,
-                       &anysee_stv0900_config, &adap->dev->i2c_adap, 0);
+               adap->fe[0] = dvb_attach(stv0900_attach,
+                               &anysee_stv0900_config, &d->i2c_adap, 0);
 
                state->has_ci = true;
 
@@ -903,28 +867,27 @@ static int anysee_frontend_attach(struct dvb_usb_adapter *adap)
        case ANYSEE_HW_508T2C: /* 20 */
                /* E7 T2C */
 
-               if (state->fe_id)
-                       break;
-
                /* enable DVB-T/T2/C demod on IOE[5] */
-               ret = anysee_wr_reg_mask(adap->dev, REG_IOE, (1 << 5), 0x20);
+               ret = anysee_wr_reg_mask(d, REG_IOE, (1 << 5), 0x20);
                if (ret)
                        goto error;
 
                /* attach demod */
-               adap->fe_adap[state->fe_id].fe = dvb_attach(cxd2820r_attach,
-                               &anysee_cxd2820r_config, &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(cxd2820r_attach,
+                               &anysee_cxd2820r_config, &d->i2c_adap, NULL);
 
                state->has_ci = true;
 
                break;
        }
 
-       if (!adap->fe_adap[0].fe) {
+       if (!adap->fe[0]) {
                /* we have no frontend :-( */
                ret = -ENODEV;
-               err("Unsupported Anysee version. " \
-                       "Please report the <linux-media@vger.kernel.org>.");
+               dev_err(&d->udev->dev, "%s: Unsupported Anysee version. " \
+                               "Please report the " \
+                               "<linux-media@vger.kernel.org>.\n",
+                               KBUILD_MODNAME);
        }
 error:
        return ret;
@@ -932,44 +895,43 @@ error:
 
 static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       struct anysee_state *state = adap->dev->priv;
+       struct anysee_state *state = adap_to_priv(adap);
+       struct dvb_usb_device *d = adap_to_d(adap);
        struct dvb_frontend *fe;
        int ret;
-       deb_info("%s: fe=%d\n", __func__, state->fe_id);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
        switch (state->hw) {
        case ANYSEE_HW_507T: /* 2 */
                /* E30 */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-                       (0xc2 >> 1), NULL, DVB_PLL_THOMSON_DTT7579);
+               fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1), NULL,
+                               DVB_PLL_THOMSON_DTT7579);
 
                break;
        case ANYSEE_HW_507CD: /* 6 */
                /* E30 Plus */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-                       (0xc2 >> 1), &adap->dev->i2c_adap,
-                       DVB_PLL_THOMSON_DTT7579);
+               fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc2 >> 1),
+                               &d->i2c_adap, DVB_PLL_THOMSON_DTT7579);
 
                break;
        case ANYSEE_HW_507DC: /* 10 */
                /* E30 C Plus */
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[0].fe,
-                       (0xc0 >> 1), &adap->dev->i2c_adap,
-                       DVB_PLL_SAMSUNG_DTOS403IH102A);
+               fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1),
+                               &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
 
                break;
        case ANYSEE_HW_507SI: /* 11 */
                /* E30 S2 Plus */
 
                /* attach LNB controller */
-               fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap, &anysee_isl6423_config);
+               fe = dvb_attach(isl6423_attach, adap->fe[0], &d->i2c_adap,
+                               &anysee_isl6423_config);
 
                break;
        case ANYSEE_HW_507FA: /* 15 */
@@ -980,15 +942,28 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                 * fails attach old simple PLL. */
 
                /* attach tuner */
-               fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-                       &adap->dev->i2c_adap, &anysee_tda18212_config);
-               if (fe)
+               fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap,
+                               &anysee_tda18212_config);
+
+               if (fe && adap->fe[1]) {
+                       /* attach tuner for 2nd FE */
+                       fe = dvb_attach(tda18212_attach, adap->fe[1],
+                                       &d->i2c_adap, &anysee_tda18212_config);
+                       break;
+               } else if (fe) {
                        break;
+               }
 
                /* attach tuner */
-               fe = dvb_attach(dvb_pll_attach, adap->fe_adap[state->fe_id].fe,
-                       (0xc0 >> 1), &adap->dev->i2c_adap,
-                       DVB_PLL_SAMSUNG_DTOS403IH102A);
+               fe = dvb_attach(dvb_pll_attach, adap->fe[0], (0xc0 >> 1),
+                               &d->i2c_adap, DVB_PLL_SAMSUNG_DTOS403IH102A);
+
+               if (fe && adap->fe[1]) {
+                       /* attach tuner for 2nd FE */
+                       fe = dvb_attach(dvb_pll_attach, adap->fe[0],
+                                       (0xc0 >> 1), &d->i2c_adap,
+                                       DVB_PLL_SAMSUNG_DTOS403IH102A);
+               }
 
                break;
        case ANYSEE_HW_508TC: /* 18 */
@@ -997,8 +972,14 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* E7 PTC */
 
                /* attach tuner */
-               fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-                       &adap->dev->i2c_adap, &anysee_tda18212_config);
+               fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap,
+                               &anysee_tda18212_config);
+
+               if (fe) {
+                       /* attach tuner for 2nd FE */
+                       fe = dvb_attach(tda18212_attach, adap->fe[1],
+                                       &d->i2c_adap, &anysee_tda18212_config);
+               }
 
                break;
        case ANYSEE_HW_508S2: /* 19 */
@@ -1007,13 +988,13 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* E7 PS2 */
 
                /* attach tuner */
-               fe = dvb_attach(stv6110_attach, adap->fe_adap[0].fe,
-                       &anysee_stv6110_config, &adap->dev->i2c_adap);
+               fe = dvb_attach(stv6110_attach, adap->fe[0],
+                               &anysee_stv6110_config, &d->i2c_adap);
 
                if (fe) {
                        /* attach LNB controller */
-                       fe = dvb_attach(isl6423_attach, adap->fe_adap[0].fe,
-                               &adap->dev->i2c_adap, &anysee_isl6423_config);
+                       fe = dvb_attach(isl6423_attach, adap->fe[0],
+                                       &d->i2c_adap, &anysee_isl6423_config);
                }
 
                break;
@@ -1022,8 +1003,8 @@ static int anysee_tuner_attach(struct dvb_usb_adapter *adap)
                /* E7 T2C */
 
                /* attach tuner */
-               fe = dvb_attach(tda18212_attach, adap->fe_adap[state->fe_id].fe,
-                       &adap->dev->i2c_adap, &anysee_tda18212_config2);
+               fe = dvb_attach(tda18212_attach, adap->fe[0], &d->i2c_adap,
+                               &anysee_tda18212_config2);
 
                break;
        default:
@@ -1057,13 +1038,23 @@ static int anysee_rc_query(struct dvb_usb_device *d)
                return ret;
 
        if (ircode[0]) {
-               deb_rc("%s: key pressed %02x\n", __func__, ircode[1]);
+               dev_dbg(&d->udev->dev, "%s: key pressed %02x\n", __func__,
+                               ircode[1]);
                rc_keydown(d->rc_dev, 0x08 << 8 | ircode[1], 0);
        }
 
        return 0;
 }
 
+static int anysee_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
+{
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query          = anysee_rc_query;
+       rc->interval       = 250;  /* windows driver uses 500ms */
+
+       return 0;
+}
+
 static int anysee_ci_read_attribute_mem(struct dvb_ca_en50221 *ci, int slot,
        int addr)
 {
@@ -1126,7 +1117,7 @@ static int anysee_ci_slot_reset(struct dvb_ca_en50221 *ci, int slot)
 {
        struct dvb_usb_device *d = ci->data;
        int ret;
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
 
        state->ci_cam_ready = jiffies + msecs_to_jiffies(1000);
 
@@ -1177,7 +1168,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
        int open)
 {
        struct dvb_usb_device *d = ci->data;
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
        int ret;
        u8 tmp;
 
@@ -1196,7 +1187,7 @@ static int anysee_ci_poll_slot_status(struct dvb_ca_en50221 *ci, int slot,
 
 static int anysee_ci_init(struct dvb_usb_device *d)
 {
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
        int ret;
 
        state->ci.owner               = THIS_MODULE;
@@ -1226,15 +1217,17 @@ static int anysee_ci_init(struct dvb_usb_device *d)
        if (ret)
                return ret;
 
+       state->ci_attached = true;
+
        return 0;
 }
 
 static void anysee_ci_release(struct dvb_usb_device *d)
 {
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
 
        /* detach CI */
-       if (state->has_ci)
+       if (state->ci_attached)
                dvb_ca_en50221_release(&state->ci);
 
        return;
@@ -1242,9 +1235,17 @@ static void anysee_ci_release(struct dvb_usb_device *d)
 
 static int anysee_init(struct dvb_usb_device *d)
 {
-       struct anysee_state *state = d->priv;
+       struct anysee_state *state = d_to_priv(d);
        int ret;
 
+       /* There is one interface with two alternate settings.
+          Alternate setting 0 is for bulk transfer.
+          Alternate setting 1 is for isochronous transfer.
+          We use bulk transfer (alternate setting 0). */
+       ret = usb_set_interface(d->udev, 0, 0);
+       if (ret)
+               return ret;
+
        /* LED light */
        ret = anysee_led_ctrl(d, 0x01, 0x03);
        if (ret)
@@ -1258,148 +1259,68 @@ static int anysee_init(struct dvb_usb_device *d)
        /* attach CI */
        if (state->has_ci) {
                ret = anysee_ci_init(d);
-               if (ret) {
-                       state->has_ci = false;
+               if (ret)
                        return ret;
-               }
        }
 
        return 0;
 }
 
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties anysee_properties;
-
-static int anysee_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
+static void anysee_exit(struct dvb_usb_device *d)
 {
-       struct dvb_usb_device *d;
-       struct usb_host_interface *alt;
-       int ret;
-
-       /* There is one interface with two alternate settings.
-          Alternate setting 0 is for bulk transfer.
-          Alternate setting 1 is for isochronous transfer.
-          We use bulk transfer (alternate setting 0). */
-       if (intf->num_altsetting < 1)
-               return -ENODEV;
-
-       /*
-        * Anysee is always warm (its USB-bridge, Cypress FX2, uploads
-        * firmware from eeprom).  If dvb_usb_device_init() succeeds that
-        * means d is a valid pointer.
-        */
-       ret = dvb_usb_device_init(intf, &anysee_properties, THIS_MODULE, &d,
-               adapter_nr);
-       if (ret)
-               return ret;
-
-       alt = usb_altnum_to_altsetting(intf, 0);
-       if (alt == NULL) {
-               deb_info("%s: no alt found!\n", __func__);
-               return -ENODEV;
-       }
-
-       ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-               alt->desc.bAlternateSetting);
-       if (ret)
-               return ret;
-
-       return anysee_init(d);
+       return anysee_ci_release(d);
 }
 
-static void anysee_disconnect(struct usb_interface *intf)
-{
-       struct dvb_usb_device *d = usb_get_intfdata(intf);
-
-       anysee_ci_release(d);
-       dvb_usb_device_exit(intf);
-
-       return;
-}
-
-static struct usb_device_id anysee_table[] = {
-       { USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE) },
-       { USB_DEVICE(USB_VID_AMT,     USB_PID_ANYSEE) },
-       { }             /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, anysee_table);
-
-static struct dvb_usb_device_properties anysee_properties = {
-       .caps             = DVB_USB_IS_AN_I2C_ADAPTER,
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties anysee_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct anysee_state),
 
-       .usb_ctrl         = DEVICE_SPECIFIC,
+       .generic_bulk_ctrl_endpoint = 0x01,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
 
-       .size_of_priv     = sizeof(struct anysee_state),
+       .i2c_algo         = &anysee_i2c_algo,
+       .read_config      = anysee_read_config,
+       .frontend_attach  = anysee_frontend_attach,
+       .tuner_attach     = anysee_tuner_attach,
+       .init             = anysee_init,
+       .get_rc_config    = anysee_get_rc_config,
+       .frontend_ctrl    = anysee_frontend_ctrl,
+       .streaming_ctrl   = anysee_streaming_ctrl,
+       .exit             = anysee_exit,
 
        .num_adapters = 1,
        .adapter = {
                {
-               .num_frontends    = 2,
-               .frontend_ctrl    = anysee_frontend_ctrl,
-               .fe = { {
-                       .streaming_ctrl   = anysee_streaming_ctrl,
-                       .frontend_attach  = anysee_frontend_attach,
-                       .tuner_attach     = anysee_tuner_attach,
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 8,
-                               .endpoint = 0x82,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = (16*512),
-                                       }
-                               }
-                       },
-               }, {
-                       .streaming_ctrl   = anysee_streaming_ctrl,
-                       .frontend_attach  = anysee_frontend_attach,
-                       .tuner_attach     = anysee_tuner_attach,
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 8,
-                               .endpoint = 0x82,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = (16*512),
-                                       }
-                               }
-                       },
-               } },
+                       .stream = DVB_USB_STREAM_BULK(0x82, 8, 16 * 512),
                }
-       },
-
-       .rc.core = {
-               .rc_codes         = RC_MAP_ANYSEE,
-               .protocol         = RC_TYPE_OTHER,
-               .module_name      = "anysee",
-               .rc_query         = anysee_rc_query,
-               .rc_interval      = 250,  /* windows driver uses 500ms */
-       },
-
-       .i2c_algo         = &anysee_i2c_algo,
-
-       .generic_bulk_ctrl_endpoint = 1,
-
-       .num_device_descs = 1,
-       .devices = {
-               {
-                       .name = "Anysee DVB USB2.0",
-                       .cold_ids = {NULL},
-                       .warm_ids = {&anysee_table[0],
-                                    &anysee_table[1], NULL},
-               },
        }
 };
 
-static struct usb_driver anysee_driver = {
-       .name       = "dvb_usb_anysee",
-       .probe      = anysee_probe,
-       .disconnect = anysee_disconnect,
-       .id_table   = anysee_table,
+static const struct usb_device_id anysee_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_CYPRESS, USB_PID_ANYSEE,
+               &anysee_props, "Anysee", RC_MAP_ANYSEE) },
+       { DVB_USB_DEVICE(USB_VID_AMT, USB_PID_ANYSEE,
+               &anysee_props, "Anysee", RC_MAP_ANYSEE) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, anysee_id_table);
+
+static struct usb_driver anysee_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = anysee_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
-module_usb_driver(anysee_driver);
+module_usb_driver(anysee_usb_driver);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
 MODULE_DESCRIPTION("Driver Anysee E30 DVB-C & DVB-T USB2.0");
similarity index 97%
rename from drivers/media/dvb/dvb-usb/anysee.h
rename to drivers/media/usb/dvb-usb-v2/anysee.h
index 8ac8794315401d06a087dcf4614444ce98c8d12b..c1a4273f14ff8075f4e881fca7243b8197d4cc1a 100644 (file)
 #define _DVB_USB_ANYSEE_H_
 
 #define DVB_USB_LOG_PREFIX "anysee"
-#include "dvb-usb.h"
+#include "dvb_usb.h"
 #include "dvb_ca_en50221.h"
 
-#define deb_info(args...) dprintk(dvb_usb_anysee_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_anysee_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_anysee_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_anysee_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_anysee_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_anysee_debug, 0x20, args)
-
 enum cmd {
        CMD_I2C_READ            = 0x33,
        CMD_I2C_WRITE           = 0x31,
@@ -63,6 +56,7 @@ struct anysee_state {
        u8 seq;
        u8 fe_id:1; /* frondend ID */
        u8 has_ci:1;
+       u8 ci_attached:1;
        struct dvb_ca_en50221 ci;
        unsigned long ci_cam_ready; /* jiffies */
 };
similarity index 64%
rename from drivers/media/dvb/dvb-usb/au6610.c
rename to drivers/media/usb/dvb-usb-v2/au6610.c
index 16210c060302a6114c912bf67d8c7034f2487194..ae6a671b7fd55dae414501628918d4d00f4a5336 100644 (file)
 #include "zl10353.h"
 #include "qt1010.h"
 
-/* debug */
-static int dvb_usb_au6610_debug;
-module_param_named(debug, dvb_usb_au6610_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
@@ -52,7 +48,8 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
                index += wbuf[1];
                break;
        default:
-               warn("wlen = %x, aborting.", wlen);
+               dev_err(&d->udev->dev, "%s: wlen=%d, aborting\n",
+                               KBUILD_MODNAME, wlen);
                ret = -EINVAL;
                goto error;
        }
@@ -60,6 +57,11 @@ static int au6610_usb_msg(struct dvb_usb_device *d, u8 operation, u8 addr,
        ret = usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0), operation,
                              USB_TYPE_VENDOR|USB_DIR_IN, addr << 1, index,
                              usb_buf, 6, AU6610_USB_TIMEOUT);
+
+       dvb_usb_dbg_usb_control_msg(d->udev, operation,
+                       (USB_TYPE_VENDOR|USB_DIR_IN), addr << 1, index,
+                       usb_buf, 6);
+
        if (ret < 0)
                goto error;
 
@@ -140,9 +142,9 @@ static struct zl10353_config au6610_zl10353_config = {
 
 static int au6610_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &au6610_zl10353_config,
-               &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL)
+       adap->fe[0] = dvb_attach(zl10353_attach, &au6610_zl10353_config,
+                       &adap_to_d(adap)->i2c_adap);
+       if (adap->fe[0] == NULL)
                return -ENODEV;
 
        return 0;
@@ -154,94 +156,53 @@ static struct qt1010_config au6610_qt1010_config = {
 
 static int au6610_qt1010_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       return dvb_attach(qt1010_attach,
-                         adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-                         &au6610_qt1010_config) == NULL ? -ENODEV : 0;
+       return dvb_attach(qt1010_attach, adap->fe[0],
+                       &adap_to_d(adap)->i2c_adap,
+                       &au6610_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties au6610_properties;
-
-static int au6610_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
+static int au6610_init(struct dvb_usb_device *d)
 {
-       struct dvb_usb_device *d;
-       struct usb_host_interface *alt;
-       int ret;
-
-       if (intf->num_altsetting < AU6610_ALTSETTING_COUNT)
-               return -ENODEV;
-
-       ret = dvb_usb_device_init(intf, &au6610_properties, THIS_MODULE, &d,
-                                 adapter_nr);
-       if (ret == 0) {
-               alt = usb_altnum_to_altsetting(intf, AU6610_ALTSETTING);
-
-               if (alt == NULL) {
-                       deb_info("%s: no alt found!\n", __func__);
-                       return -ENODEV;
-               }
-               ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-                                       alt->desc.bAlternateSetting);
-       }
-
-       return ret;
+       /* TODO: this functionality belongs likely to the streaming control */
+       /* bInterfaceNumber 0, bAlternateSetting 5 */
+       return usb_set_interface(d->udev, 0, 5);
 }
 
-static struct usb_device_id au6610_table [] = {
-       { USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110) },
-       { }             /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, au6610_table);
+static struct dvb_usb_device_properties au6610_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
 
-static struct dvb_usb_device_properties au6610_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-       .usb_ctrl = DEVICE_SPECIFIC,
-
-       .size_of_priv = 0,
+       .i2c_algo = &au6610_i2c_algo,
+       .frontend_attach = au6610_zl10353_frontend_attach,
+       .tuner_attach = au6610_qt1010_tuner_attach,
+       .init = au6610_init,
 
        .num_adapters = 1,
        .adapter = {
                {
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = au6610_zl10353_frontend_attach,
-                       .tuner_attach     = au6610_qt1010_tuner_attach,
-
-                       .stream = {
-                               .type = USB_ISOC,
-                               .count = 5,
-                               .endpoint = 0x82,
-                               .u = {
-                                       .isoc = {
-                                               .framesperurb = 40,
-                                               .framesize = 942,
-                                               .interval = 1,
-                                       }
-                               }
-                       },
-               }},
-               }
+                       .stream = DVB_USB_STREAM_ISOC(0x82, 5, 40, 942, 1),
+               },
        },
+};
 
-       .i2c_algo = &au6610_i2c_algo,
-
-       .num_device_descs = 1,
-       .devices = {
-               {
-                       .name = "Sigmatek DVB-110 DVB-T USB2.0",
-                       .cold_ids = {NULL},
-                       .warm_ids = {&au6610_table[0], NULL},
-               },
-       }
+static const struct usb_device_id au6610_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_ALCOR_MICRO, USB_PID_SIGMATEK_DVB_110,
+               &au6610_props, "Sigmatek DVB-110", NULL) },
+       { }
 };
+MODULE_DEVICE_TABLE(usb, au6610_id_table);
 
 static struct usb_driver au6610_driver = {
-       .name       = "dvb_usb_au6610",
-       .probe      = au6610_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table   = au6610_table,
+       .name = KBUILD_MODNAME,
+       .id_table = au6610_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
 module_usb_driver(au6610_driver);
similarity index 80%
rename from drivers/media/dvb/dvb-usb/au6610.h
rename to drivers/media/usb/dvb-usb-v2/au6610.h
index 7849abe2c61433c685c58dd231f27c79575b7c9b..ea337bfc00b111aae5de96e85f370fddefa73cf2 100644 (file)
  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-#ifndef _DVB_USB_AU6610_H_
-#define _DVB_USB_AU6610_H_
-
-#define DVB_USB_LOG_PREFIX "au6610"
-#include "dvb-usb.h"
-
-#define deb_info(args...)   dprintk(dvb_usb_au6610_debug, 0x01, args)
+#ifndef AU6610_H
+#define AU6610_H
+#include "dvb_usb.h"
 
 #define AU6610_REQ_I2C_WRITE   0x14
 #define AU6610_REQ_I2C_READ    0x13
@@ -33,7 +29,4 @@
 
 #define AU6610_USB_TIMEOUT 1000
 
-#define AU6610_ALTSETTING_COUNT 6
-#define AU6610_ALTSETTING       5
-
 #endif
similarity index 63%
rename from drivers/media/dvb/dvb-usb/az6007.c
rename to drivers/media/usb/dvb-usb-v2/az6007.c
index 86861e6f86d23053ebe990aa58b24e7d377d7d45..54f1221d930df3c5eb0d554c4d56da63cc06583d 100644 (file)
@@ -7,9 +7,9 @@
  *     http://linux.terratec.de/files/TERRATEC_H7/20110323_TERRATEC_H7_Linux.tar.gz
  * The original driver's license is GPL, as declared with MODULE_LICENSE()
  *
- * Copyright (c) 2010-2011 Mauro Carvalho Chehab <mchehab@redhat.com>
+ * Copyright (c) 2010-2012 Mauro Carvalho Chehab <mchehab@redhat.com>
  *     Driver modified by in order to work with upstream drxk driver, and
- *     tons of bugs got fixed.
+ *     tons of bugs got fixed, and converted to use dvb-usb-v2.
  *
  * 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
 #include "drxk.h"
 #include "mt2063.h"
 #include "dvb_ca_en50221.h"
+#include "dvb_usb.h"
+#include "cypress_firmware.h"
 
-#define DVB_USB_LOG_PREFIX "az6007"
-#include "dvb-usb.h"
+#define AZ6007_FIRMWARE "dvb-usb-terratec-h7-az6007.fw"
 
-/* debug */
-int dvb_usb_az6007_debug;
-module_param_named(debug, dvb_usb_az6007_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info,xfer=2,rc=4 (or-able))."
-                DVB_USB_DEBUG_STATUS);
-
-#define deb_info(args...) dprintk(dvb_usb_az6007_debug, 0x01, args)
-#define deb_xfer(args...) dprintk(dvb_usb_az6007_debug, 0x02, args)
-#define deb_rc(args...)   dprintk(dvb_usb_az6007_debug, 0x04, args)
-#define deb_fe(args...)   dprintk(dvb_usb_az6007_debug, 0x08, args)
+static int az6007_xfer_debug;
+module_param_named(xfer_debug, az6007_xfer_debug, int, 0644);
+MODULE_PARM_DESC(xfer_debug, "Enable xfer debug");
 
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
@@ -70,23 +64,19 @@ static struct drxk_config terratec_h7_drxk = {
        .no_i2c_bridge = false,
        .chunk_size = 64,
        .mpeg_out_clk_strength = 0x02,
+       .qam_demod_parameter_count = 2,
        .microcode_name = "dvb-usb-terratec-h7-drxk.fw",
 };
 
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
 {
+       struct az6007_device_state *st = fe_to_priv(fe);
        struct dvb_usb_adapter *adap = fe->sec_priv;
-       struct az6007_device_state *st;
        int status = 0;
 
-       deb_info("%s: %s\n", __func__, enable ? "enable" : "disable");
-
-       if (!adap)
-               return -EINVAL;
-
-       st = adap->dev->priv;
+       pr_debug("%s: %s\n", __func__, enable ? "enable" : "disable");
 
-       if (!st)
+       if (!adap || !st)
                return -EINVAL;
 
        if (enable)
@@ -113,13 +103,16 @@ static int __az6007_read(struct usb_device *udev, u8 req, u16 value,
                              USB_TYPE_VENDOR | USB_DIR_IN,
                              value, index, b, blen, 5000);
        if (ret < 0) {
-               warn("usb read operation failed. (%d)", ret);
+               pr_warn("usb read operation failed. (%d)\n", ret);
                return -EIO;
        }
 
-       deb_xfer("in: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
-                index);
-       debug_dump(b, blen, deb_xfer);
+       if (az6007_xfer_debug) {
+               printk(KERN_DEBUG "az6007: IN  req: %02x, value: %04x, index: %04x\n",
+                      req, value, index);
+               print_hex_dump_bytes("az6007: payload: ",
+                                    DUMP_PREFIX_NONE, b, blen);
+       }
 
        return ret;
 }
@@ -145,13 +138,16 @@ static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
 {
        int ret;
 
-       deb_xfer("out: req. %02x, val: %04x, ind: %04x, buffer: ", req, value,
-                index);
-       debug_dump(b, blen, deb_xfer);
+       if (az6007_xfer_debug) {
+               printk(KERN_DEBUG "az6007: OUT req: %02x, value: %04x, index: %04x\n",
+                      req, value, index);
+               print_hex_dump_bytes("az6007: payload: ",
+                                    DUMP_PREFIX_NONE, b, blen);
+       }
 
        if (blen > 64) {
-               err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
-                   blen);
+               pr_err("az6007: tried to write %d bytes, but I2C max size is 64 bytes\n",
+                      blen);
                return -EOPNOTSUPP;
        }
 
@@ -161,7 +157,7 @@ static int __az6007_write(struct usb_device *udev, u8 req, u16 value,
                              USB_TYPE_VENDOR | USB_DIR_OUT,
                              value, index, b, blen, 5000);
        if (ret != blen) {
-               err("usb write operation failed. (%d)", ret);
+               pr_err("usb write operation failed. (%d)\n", ret);
                return -EIO;
        }
 
@@ -184,11 +180,11 @@ static int az6007_write(struct dvb_usb_device *d, u8 req, u16 value,
        return ret;
 }
 
-static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
+static int az6007_streaming_ctrl(struct dvb_frontend *fe, int onoff)
 {
-       struct dvb_usb_device *d = adap->dev;
+       struct dvb_usb_device *d = fe_to_d(fe);
 
-       deb_info("%s: %s", __func__, onoff ? "enable" : "disable");
+       pr_debug("%s: %s\n", __func__, onoff ? "enable" : "disable");
 
        return az6007_write(d, 0xbc, onoff, 0, NULL, 0);
 }
@@ -196,7 +192,7 @@ static int az6007_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
 /* remote control stuff (does not work with my box) */
 static int az6007_rc_query(struct dvb_usb_device *d)
 {
-       struct az6007_device_state *st = d->priv;
+       struct az6007_device_state *st = d_to_priv(d);
        unsigned code = 0;
 
        az6007_read(d, AZ6007_READ_IR, 0, 0, st->data, 10);
@@ -224,7 +220,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
                                        int address)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret;
        u8 req;
@@ -249,7 +245,7 @@ static int az6007_ci_read_attribute_mem(struct dvb_ca_en50221 *ca,
 
        ret = az6007_read(d, req, value, index, b, blen);
        if (ret < 0) {
-               warn("usb in operation failed. (%d)", ret);
+               pr_warn("usb in operation failed. (%d)\n", ret);
                ret = -EINVAL;
        } else {
                ret = b[0];
@@ -266,7 +262,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
                                         u8 value)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret;
        u8 req;
@@ -274,7 +270,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
        u16 index;
        int blen;
 
-       deb_info("%s %d", __func__, slot);
+       pr_debug("%s(), slot %d\n", __func__, slot);
        if (slot != 0)
                return -EINVAL;
 
@@ -286,7 +282,7 @@ static int az6007_ci_write_attribute_mem(struct dvb_ca_en50221 *ca,
 
        ret = az6007_write(d, req, value1, index, NULL, blen);
        if (ret != 0)
-               warn("usb out operation failed. (%d)", ret);
+               pr_warn("usb out operation failed. (%d)\n", ret);
 
        mutex_unlock(&state->ca_mutex);
        return ret;
@@ -297,7 +293,7 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
                                      u8 address)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret;
        u8 req;
@@ -322,14 +318,14 @@ static int az6007_ci_read_cam_control(struct dvb_ca_en50221 *ca,
 
        ret = az6007_read(d, req, value, index, b, blen);
        if (ret < 0) {
-               warn("usb in operation failed. (%d)", ret);
+               pr_warn("usb in operation failed. (%d)\n", ret);
                ret = -EINVAL;
        } else {
                if (b[0] == 0)
-                       warn("Read CI IO error");
+                       pr_warn("Read CI IO error\n");
 
                ret = b[1];
-               deb_info("read cam data = %x from 0x%x", b[1], value);
+               pr_debug("read cam data = %x from 0x%x\n", b[1], value);
        }
 
        mutex_unlock(&state->ca_mutex);
@@ -343,7 +339,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
                                       u8 value)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret;
        u8 req;
@@ -362,7 +358,7 @@ static int az6007_ci_write_cam_control(struct dvb_ca_en50221 *ca,
 
        ret = az6007_write(d, req, value1, index, NULL, blen);
        if (ret != 0) {
-               warn("usb out operation failed. (%d)", ret);
+               pr_warn("usb out operation failed. (%d)\n", ret);
                goto failed;
        }
 
@@ -393,7 +389,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
 
        ret = az6007_read(d, req, value, index, b, blen);
        if (ret < 0) {
-               warn("usb in operation failed. (%d)", ret);
+               pr_warn("usb in operation failed. (%d)\n", ret);
                ret = -EIO;
        } else{
                ret = b[0];
@@ -405,7 +401,7 @@ static int CI_CamReady(struct dvb_ca_en50221 *ca, int slot)
 static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret, i;
        u8 req;
@@ -422,7 +418,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 
        ret = az6007_write(d, req, value, index, NULL, blen);
        if (ret != 0) {
-               warn("usb out operation failed. (%d)", ret);
+               pr_warn("usb out operation failed. (%d)\n", ret);
                goto failed;
        }
 
@@ -434,7 +430,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
 
        ret = az6007_write(d, req, value, index, NULL, blen);
        if (ret != 0) {
-               warn("usb out operation failed. (%d)", ret);
+               pr_warn("usb out operation failed. (%d)\n", ret);
                goto failed;
        }
 
@@ -442,7 +438,7 @@ static int az6007_ci_slot_reset(struct dvb_ca_en50221 *ca, int slot)
                msleep(100);
 
                if (CI_CamReady(ca, slot)) {
-                       deb_info("CAM Ready");
+                       pr_debug("CAM Ready\n");
                        break;
                }
        }
@@ -461,7 +457,7 @@ static int az6007_ci_slot_shutdown(struct dvb_ca_en50221 *ca, int slot)
 static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
 
        int ret;
        u8 req;
@@ -469,7 +465,7 @@ static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
        u16 index;
        int blen;
 
-       deb_info("%s", __func__);
+       pr_debug("%s()\n", __func__);
        mutex_lock(&state->ca_mutex);
        req = 0xC7;
        value = 1;
@@ -478,7 +474,7 @@ static int az6007_ci_slot_ts_enable(struct dvb_ca_en50221 *ca, int slot)
 
        ret = az6007_write(d, req, value, index, NULL, blen);
        if (ret != 0) {
-               warn("usb out operation failed. (%d)", ret);
+               pr_warn("usb out operation failed. (%d)\n", ret);
                goto failed;
        }
 
@@ -490,7 +486,7 @@ failed:
 static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int open)
 {
        struct dvb_usb_device *d = (struct dvb_usb_device *)ca->data;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
        int ret;
        u8 req;
        u16 value;
@@ -510,7 +506,7 @@ static int az6007_ci_poll_slot_status(struct dvb_ca_en50221 *ca, int slot, int o
 
        ret = az6007_read(d, req, value, index, b, blen);
        if (ret < 0) {
-               warn("usb in operation failed. (%d)", ret);
+               pr_warn("usb in operation failed. (%d)\n", ret);
                ret = -EIO;
        } else
                ret = 0;
@@ -530,12 +526,12 @@ static void az6007_ci_uninit(struct dvb_usb_device *d)
 {
        struct az6007_device_state *state;
 
-       deb_info("%s", __func__);
+       pr_debug("%s()\n", __func__);
 
        if (NULL == d)
                return;
 
-       state = (struct az6007_device_state *)d->priv;
+       state = d_to_priv(d);
        if (NULL == state)
                return;
 
@@ -548,16 +544,15 @@ static void az6007_ci_uninit(struct dvb_usb_device *d)
 }
 
 
-static int az6007_ci_init(struct dvb_usb_adapter *a)
+static int az6007_ci_init(struct dvb_usb_adapter *adap)
 {
-       struct dvb_usb_device *d = a->dev;
-       struct az6007_device_state *state = (struct az6007_device_state *)d->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct az6007_device_state *state = adap_to_priv(adap);
        int ret;
 
-       deb_info("%s", __func__);
+       pr_debug("%s()\n", __func__);
 
        mutex_init(&state->ca_mutex);
-
        state->ca.owner                 = THIS_MODULE;
        state->ca.read_attribute_mem    = az6007_ci_read_attribute_mem;
        state->ca.write_attribute_mem   = az6007_ci_write_attribute_mem;
@@ -569,49 +564,51 @@ static int az6007_ci_init(struct dvb_usb_adapter *a)
        state->ca.poll_slot_status      = az6007_ci_poll_slot_status;
        state->ca.data                  = d;
 
-       ret = dvb_ca_en50221_init(&a->dvb_adap,
+       ret = dvb_ca_en50221_init(&adap->dvb_adap,
                                  &state->ca,
                                  0, /* flags */
                                  1);/* n_slots */
        if (ret != 0) {
-               err("Cannot initialize CI: Error %d.", ret);
+               pr_err("Cannot initialize CI: Error %d.\n", ret);
                memset(&state->ca, 0, sizeof(state->ca));
                return ret;
        }
 
-       deb_info("CI initialized.");
+       pr_debug("CI initialized.\n");
 
        return 0;
 }
 
-static int az6007_read_mac_addr(struct dvb_usb_device *d, u8 mac[6])
+static int az6007_read_mac_addr(struct dvb_usb_adapter *adap, u8 mac[6])
 {
-       struct az6007_device_state *st = d->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct az6007_device_state *st = adap_to_priv(adap);
        int ret;
 
        ret = az6007_read(d, AZ6007_READ_DATA, 6, 0, st->data, 6);
        memcpy(mac, st->data, 6);
 
        if (ret > 0)
-               deb_info("%s: mac is %pM\n", __func__, mac);
+               pr_debug("%s: mac is %pM\n", __func__, mac);
 
        return ret;
 }
 
 static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       struct az6007_device_state *st = adap->dev->priv;
+       struct az6007_device_state *st = adap_to_priv(adap);
+       struct dvb_usb_device *d = adap_to_d(adap);
 
-       deb_info("attaching demod drxk");
+       pr_debug("attaching demod drxk\n");
 
-       adap->fe_adap[0].fe = dvb_attach(drxk_attach, &terratec_h7_drxk,
-                                        &adap->dev->i2c_adap);
-       if (!adap->fe_adap[0].fe)
+       adap->fe[0] = dvb_attach(drxk_attach, &terratec_h7_drxk,
+                                &d->i2c_adap);
+       if (!adap->fe[0])
                return -EINVAL;
 
-       adap->fe_adap[0].fe->sec_priv = adap;
-       st->gate_ctrl = adap->fe_adap[0].fe->ops.i2c_gate_ctrl;
-       adap->fe_adap[0].fe->ops.i2c_gate_ctrl = drxk_gate_ctrl;
+       adap->fe[0]->sec_priv = adap;
+       st->gate_ctrl = adap->fe[0]->ops.i2c_gate_ctrl;
+       adap->fe[0]->ops.i2c_gate_ctrl = drxk_gate_ctrl;
 
        az6007_ci_init(adap);
 
@@ -620,31 +617,33 @@ static int az6007_frontend_attach(struct dvb_usb_adapter *adap)
 
 static int az6007_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       deb_info("attaching tuner mt2063");
+       struct dvb_usb_device *d = adap_to_d(adap);
+
+       pr_debug("attaching tuner mt2063\n");
 
        /* Attach mt2063 to DVB-C frontend */
-       if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-               adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 1);
-       if (!dvb_attach(mt2063_attach, adap->fe_adap[0].fe,
+       if (adap->fe[0]->ops.i2c_gate_ctrl)
+               adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 1);
+       if (!dvb_attach(mt2063_attach, adap->fe[0],
                        &az6007_mt2063_config,
-                       &adap->dev->i2c_adap))
+                       &d->i2c_adap))
                return -EINVAL;
 
-       if (adap->fe_adap[0].fe->ops.i2c_gate_ctrl)
-               adap->fe_adap[0].fe->ops.i2c_gate_ctrl(adap->fe_adap[0].fe, 0);
+       if (adap->fe[0]->ops.i2c_gate_ctrl)
+               adap->fe[0]->ops.i2c_gate_ctrl(adap->fe[0], 0);
 
        return 0;
 }
 
-int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
+static int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
-       struct az6007_device_state *st = d->priv;
+       struct az6007_device_state *state = d_to_priv(d);
        int ret;
 
-       deb_info("%s()\n", __func__);
+       pr_debug("%s()\n", __func__);
 
-       if (!st->warm) {
-               mutex_init(&st->mutex);
+       if (!state->warm) {
+               mutex_init(&state->mutex);
 
                ret = az6007_write(d, AZ6007_POWER, 0, 2, NULL, 0);
                if (ret < 0)
@@ -675,7 +674,7 @@ int az6007_power_ctrl(struct dvb_usb_device *d, int onoff)
                if (ret < 0)
                        return ret;
 
-               st->warm = true;
+               state->warm = true;
 
                return 0;
        }
@@ -694,7 +693,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                           int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
-       struct az6007_device_state *st = d->priv;
+       struct az6007_device_state *st = d_to_priv(d);
        int i, j, len;
        int ret = 0;
        u16 index;
@@ -709,7 +708,7 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                addr = msgs[i].addr << 1;
                if (((i + 1) < num)
                    && (msgs[i].len == 1)
-                   && (!msgs[i].flags & I2C_M_RD)
+                   && ((msgs[i].flags & I2C_M_RD) != I2C_M_RD)
                    && (msgs[i + 1].flags & I2C_M_RD)
                    && (msgs[i].addr == msgs[i + 1].addr)) {
                        /*
@@ -717,9 +716,8 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                         * the first xfer has just 1 byte length.
                         * Need to join both into one operation
                         */
-                       if (dvb_usb_az6007_debug & 2)
-                               printk(KERN_DEBUG
-                                      "az6007 I2C xfer write+read addr=0x%x len=%d/%d: ",
+                       if (az6007_xfer_debug)
+                               printk(KERN_DEBUG "az6007: I2C W/R addr=0x%x len=%d/%d\n",
                                       addr, msgs[i].len, msgs[i + 1].len);
                        req = AZ6007_I2C_RD;
                        index = msgs[i].buf[0];
@@ -729,42 +727,29 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                        ret = __az6007_read(d->udev, req, value, index,
                                            st->data, length);
                        if (ret >= len) {
-                               for (j = 0; j < len; j++) {
+                               for (j = 0; j < len; j++)
                                        msgs[i + 1].buf[j] = st->data[j + 5];
-                                       if (dvb_usb_az6007_debug & 2)
-                                               printk(KERN_CONT
-                                                      "0x%02x ",
-                                                      msgs[i + 1].buf[j]);
-                               }
                        } else
                                ret = -EIO;
                        i++;
                } else if (!(msgs[i].flags & I2C_M_RD)) {
                        /* write bytes */
-                       if (dvb_usb_az6007_debug & 2)
-                               printk(KERN_DEBUG
-                                      "az6007 I2C xfer write addr=0x%x len=%d: ",
+                       if (az6007_xfer_debug)
+                               printk(KERN_DEBUG "az6007: I2C W addr=0x%x len=%d\n",
                                       addr, msgs[i].len);
                        req = AZ6007_I2C_WR;
                        index = msgs[i].buf[0];
                        value = addr | (1 << 8);
                        length = msgs[i].len - 1;
                        len = msgs[i].len - 1;
-                       if (dvb_usb_az6007_debug & 2)
-                               printk(KERN_CONT "(0x%02x) ", msgs[i].buf[0]);
-                       for (j = 0; j < len; j++) {
+                       for (j = 0; j < len; j++)
                                st->data[j] = msgs[i].buf[j + 1];
-                               if (dvb_usb_az6007_debug & 2)
-                                       printk(KERN_CONT "0x%02x ",
-                                              st->data[j]);
-                       }
                        ret =  __az6007_write(d->udev, req, value, index,
                                              st->data, length);
                } else {
                        /* read bytes */
-                       if (dvb_usb_az6007_debug & 2)
-                               printk(KERN_DEBUG
-                                      "az6007 I2C xfer read addr=0x%x len=%d: ",
+                       if (az6007_xfer_debug)
+                               printk(KERN_DEBUG "az6007: I2C R addr=0x%x len=%d\n",
                                       addr, msgs[i].len);
                        req = AZ6007_I2C_RD;
                        index = msgs[i].buf[0];
@@ -773,15 +758,9 @@ static int az6007_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
                        len = msgs[i].len;
                        ret = __az6007_read(d->udev, req, value, index,
                                            st->data, length);
-                       for (j = 0; j < len; j++) {
+                       for (j = 0; j < len; j++)
                                msgs[i].buf[j] = st->data[j + 5];
-                               if (dvb_usb_az6007_debug & 2)
-                                       printk(KERN_CONT
-                                              "0x%02x ", st->data[j + 5]);
-                       }
                }
-               if (dvb_usb_az6007_debug & 2)
-                       printk(KERN_CONT "\n");
                if (ret < 0)
                        goto err;
        }
@@ -789,7 +768,7 @@ err:
        mutex_unlock(&st->mutex);
 
        if (ret < 0) {
-               info("%s ERROR: %i", __func__, ret);
+               pr_info("%s ERROR: %i\n", __func__, ret);
                return ret;
        }
        return num;
@@ -805,151 +784,136 @@ static struct i2c_algorithm az6007_i2c_algo = {
        .functionality = az6007_i2c_func,
 };
 
-int az6007_identify_state(struct usb_device *udev,
-                         struct dvb_usb_device_properties *props,
-                         struct dvb_usb_device_description **desc, int *cold)
+static int az6007_identify_state(struct dvb_usb_device *d, const char **name)
 {
        int ret;
        u8 *mac;
 
+       pr_debug("Identifying az6007 state\n");
+
        mac = kmalloc(6, GFP_ATOMIC);
        if (!mac)
                return -ENOMEM;
 
        /* Try to read the mac address */
-       ret = __az6007_read(udev, AZ6007_READ_DATA, 6, 0, mac, 6);
+       ret = __az6007_read(d->udev, AZ6007_READ_DATA, 6, 0, mac, 6);
        if (ret == 6)
-               *cold = 0;
+               ret = WARM;
        else
-               *cold = 1;
+               ret = COLD;
 
        kfree(mac);
 
-       if (*cold) {
-               __az6007_write(udev, 0x09, 1, 0, NULL, 0);
-               __az6007_write(udev, 0x00, 0, 0, NULL, 0);
-               __az6007_write(udev, 0x00, 0, 0, NULL, 0);
+       if (ret == COLD) {
+               __az6007_write(d->udev, 0x09, 1, 0, NULL, 0);
+               __az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
+               __az6007_write(d->udev, 0x00, 0, 0, NULL, 0);
        }
 
-       deb_info("Device is on %s state\n", *cold ? "warm" : "cold");
-       return 0;
+       pr_debug("Device is on %s state\n",
+                ret == WARM ? "warm" : "cold");
+       return ret;
 }
 
-static struct dvb_usb_device_properties az6007_properties;
-
 static void az6007_usb_disconnect(struct usb_interface *intf)
 {
        struct dvb_usb_device *d = usb_get_intfdata(intf);
        az6007_ci_uninit(d);
-       dvb_usb_device_exit(intf);
+       dvb_usbv2_disconnect(intf);
 }
 
-static int az6007_usb_probe(struct usb_interface *intf,
-                           const struct usb_device_id *id)
+static int az6007_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
 {
-       return dvb_usb_device_init(intf, &az6007_properties,
-                                  THIS_MODULE, NULL, adapter_nr);
+       pr_debug("Getting az6007 Remote Control properties\n");
+
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query          = az6007_rc_query;
+       rc->interval       = 400;
+
+       return 0;
 }
 
-static struct usb_device_id az6007_usb_table[] = {
-       {USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007)},
-       {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7)},
-       {USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2)},
-       {0},
-};
+static int az6007_download_firmware(struct dvb_usb_device *d,
+       const struct firmware *fw)
+{
+       pr_debug("Loading az6007 firmware\n");
 
-MODULE_DEVICE_TABLE(usb, az6007_usb_table);
+       return usbv2_cypress_load_firmware(d->udev, fw, CYPRESS_FX2);
+}
+
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties az6007_props = {
+       .driver_name         = KBUILD_MODNAME,
+       .owner               = THIS_MODULE,
+       .firmware            = AZ6007_FIRMWARE,
 
-static struct dvb_usb_device_properties az6007_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-       .usb_ctrl = CYPRESS_FX2,
-       .firmware            = "dvb-usb-terratec-h7-az6007.fw",
-       .no_reconnect        = 1,
+       .adapter_nr          = adapter_nr,
        .size_of_priv        = sizeof(struct az6007_device_state),
+       .i2c_algo            = &az6007_i2c_algo,
+       .tuner_attach        = az6007_tuner_attach,
+       .frontend_attach     = az6007_frontend_attach,
+       .streaming_ctrl      = az6007_streaming_ctrl,
+       .get_rc_config       = az6007_get_rc_config,
+       .read_mac_address    = az6007_read_mac_addr,
+       .download_firmware   = az6007_download_firmware,
        .identify_state      = az6007_identify_state,
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .num_frontends = 1,
-               .fe = {{
-                       .streaming_ctrl   = az6007_streaming_ctrl,
-                       .tuner_attach     = az6007_tuner_attach,
-                       .frontend_attach  = az6007_frontend_attach,
-
-                       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 10,
-                               .endpoint = 0x02,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = 4096,
-                                       }
-                               }
-                       },
-               } }
-       } },
-       .power_ctrl       = az6007_power_ctrl,
-       .read_mac_address = az6007_read_mac_addr,
-
-       .rc.core = {
-               .rc_interval      = 400,
-               .rc_codes         = RC_MAP_NEC_TERRATEC_CINERGY_XS,
-               .module_name      = "az6007",
-               .rc_query         = az6007_rc_query,
-               .allowed_protos   = RC_TYPE_NEC,
-       },
-       .i2c_algo         = &az6007_i2c_algo,
-
-       .num_device_descs = 2,
-       .devices = {
-               { .name = "AzureWave DTV StarBox DVB-T/C USB2.0 (az6007)",
-                 .cold_ids = { &az6007_usb_table[0], NULL },
-                 .warm_ids = { NULL },
-               },
-               { .name = "TerraTec DTV StarBox DVB-T/C USB2.0 (az6007)",
-                 .cold_ids = { &az6007_usb_table[1], &az6007_usb_table[2], NULL },
-                 .warm_ids = { NULL },
-               },
-               { NULL },
+       .power_ctrl          = az6007_power_ctrl,
+       .num_adapters        = 1,
+       .adapter             = {
+               { .stream = DVB_USB_STREAM_BULK(0x02, 10, 4096), }
        }
 };
 
-/* usb specific object needed to register this driver with the usb subsystem */
-static struct usb_driver az6007_usb_driver = {
-       .name           = "dvb_usb_az6007",
-       .probe          = az6007_usb_probe,
-       .disconnect     = az6007_usb_disconnect,
-       .id_table       = az6007_usb_table,
+static struct usb_device_id az6007_usb_table[] = {
+       {DVB_USB_DEVICE(USB_VID_AZUREWAVE, USB_PID_AZUREWAVE_6007,
+               &az6007_props, "Azurewave 6007", RC_MAP_EMPTY)},
+       {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7,
+               &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
+       {DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_H7_2,
+               &az6007_props, "Terratec H7", RC_MAP_NEC_TERRATEC_CINERGY_XS)},
+       {0},
 };
 
-/* module stuff */
-static int __init az6007_usb_module_init(void)
-{
-       int result;
-       deb_info("az6007 usb module init\n");
+MODULE_DEVICE_TABLE(usb, az6007_usb_table);
 
-       result = usb_register(&az6007_usb_driver);
-       if (result) {
-               err("usb_register failed. (%d)", result);
-               return result;
-       }
+static int az6007_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
 
-       return 0;
+       az6007_ci_uninit(d);
+       return dvb_usbv2_suspend(intf, msg);
 }
 
-static void __exit az6007_usb_module_exit(void)
+static int az6007_resume(struct usb_interface *intf)
 {
-       /* deregister this driver from the USB subsystem */
-       deb_info("az6007 usb module exit\n");
-       usb_deregister(&az6007_usb_driver);
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       struct dvb_usb_adapter *adap = &d->adapter[0];
+
+       az6007_ci_init(adap);
+       return dvb_usbv2_resume(intf);
 }
 
-module_init(az6007_usb_module_init);
-module_exit(az6007_usb_module_exit);
+/* usb specific object needed to register this driver with the usb subsystem */
+static struct usb_driver az6007_usb_driver = {
+       .name           = KBUILD_MODNAME,
+       .id_table       = az6007_usb_table,
+       .probe          = dvb_usbv2_probe,
+       .disconnect     = az6007_usb_disconnect,
+       .no_dynamic_id  = 1,
+       .soft_unbind    = 1,
+       /*
+        * FIXME: need to implement reset_resume, likely with
+        * dvb-usb-v2 core support
+        */
+       .suspend        = az6007_suspend,
+       .resume         = az6007_resume,
+};
+
+module_usb_driver(az6007_usb_driver);
 
 MODULE_AUTHOR("Henry Wang <Henry.wang@AzureWave.com>");
 MODULE_AUTHOR("Mauro Carvalho Chehab <mchehab@redhat.com>");
 MODULE_DESCRIPTION("Driver for AzureWave 6007 DVB-C/T USB2.0 and clones");
-MODULE_VERSION("1.1");
+MODULE_VERSION("2.0");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(AZ6007_FIRMWARE);
similarity index 58%
rename from drivers/media/dvb/dvb-usb/ce6230.c
rename to drivers/media/usb/dvb-usb-v2/ce6230.c
index fa637255729c50a7026565d0bdc5eba2cc3ba903..f67b14bc32e3e653174dbae9e6d64567c657b389 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
+ * Intel CE6230 DVB USB driver
  *
  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  *
  */
 
 #include "ce6230.h"
-#include "zl10353.h"
-#include "mxl5005s.h"
 
-/* debug */
-static int dvb_usb_ce6230_debug;
-module_param_named(debug, dvb_usb_ce6230_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static struct zl10353_config ce6230_zl10353_config;
-
-static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
+static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct usb_req *req)
 {
        int ret;
        unsigned int pipe;
@@ -57,8 +49,9 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
                requesttype = (USB_TYPE_VENDOR | USB_DIR_OUT);
                break;
        default:
-               err("unknown command:%02x", req->cmd);
-               ret = -EPERM;
+               dev_err(&d->udev->dev, "%s: unknown command=%02x\n",
+                               KBUILD_MODNAME, req->cmd);
+               ret = -EINVAL;
                goto error;
        }
 
@@ -71,22 +64,23 @@ static int ce6230_rw_udev(struct usb_device *udev, struct req_t *req)
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
                /* write */
                memcpy(buf, req->data, req->data_len);
-               pipe = usb_sndctrlpipe(udev, 0);
+               pipe = usb_sndctrlpipe(d->udev, 0);
        } else {
                /* read */
-               pipe = usb_rcvctrlpipe(udev, 0);
+               pipe = usb_rcvctrlpipe(d->udev, 0);
        }
 
        msleep(1); /* avoid I2C errors */
 
-       ret = usb_control_msg(udev, pipe, request, requesttype, value, index,
-                               buf, req->data_len, CE6230_USB_TIMEOUT);
+       ret = usb_control_msg(d->udev, pipe, request, requesttype, value, index,
+                       buf, req->data_len, CE6230_USB_TIMEOUT);
 
-       ce6230_debug_dump(request, requesttype, value, index, buf,
-               req->data_len, deb_xfer);
+       dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, value, index,
+                       buf, req->data_len);
 
        if (ret < 0)
-               deb_info("%s: usb_control_msg failed:%d\n", __func__, ret);
+               dev_err(&d->udev->dev, "%s: usb_control_msg() failed=%d\n",
+                               KBUILD_MODNAME, ret);
        else
                ret = 0;
 
@@ -99,23 +93,20 @@ error:
        return ret;
 }
 
-static int ce6230_ctrl_msg(struct dvb_usb_device *d, struct req_t *req)
-{
-       return ce6230_rw_udev(d->udev, req);
-}
-
 /* I2C */
-static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
-                          int num)
+static struct zl10353_config ce6230_zl10353_config;
+
+static int ce6230_i2c_master_xfer(struct i2c_adapter *adap,
+               struct i2c_msg msg[], int num)
 {
        struct dvb_usb_device *d = i2c_get_adapdata(adap);
-       int i = 0;
-       struct req_t req;
-       int ret = 0;
-       memset(&req, 0, sizeof(req));
+       int ret = 0, i = 0;
+       struct usb_req req;
 
        if (num > 2)
-               return -EINVAL;
+               return -EOPNOTSUPP;
+
+       memset(&req, 0, sizeof(req));
 
        if (mutex_lock_interruptible(&d->i2c_mutex) < 0)
                return -EAGAIN;
@@ -131,8 +122,10 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                                req.data = &msg[i+1].buf[0];
                                ret = ce6230_ctrl_msg(d, &req);
                        } else {
-                               err("i2c read not implemented");
-                               ret = -EPERM;
+                               dev_err(&d->udev->dev, "%s: I2C read not " \
+                                               "implemented\n",
+                                               KBUILD_MODNAME);
+                               ret = -EOPNOTSUPP;
                        }
                        i += 2;
                } else {
@@ -162,14 +155,14 @@ static int ce6230_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
        return ret ? ret : i;
 }
 
-static u32 ce6230_i2c_func(struct i2c_adapter *adapter)
+static u32 ce6230_i2c_functionality(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C;
 }
 
-static struct i2c_algorithm ce6230_i2c_algo = {
-       .master_xfer   = ce6230_i2c_xfer,
-       .functionality = ce6230_i2c_func,
+static struct i2c_algorithm ce6230_i2c_algorithm = {
+       .master_xfer   = ce6230_i2c_master_xfer,
+       .functionality = ce6230_i2c_functionality,
 };
 
 /* Callbacks for DVB USB */
@@ -185,11 +178,15 @@ static struct zl10353_config ce6230_zl10353_config = {
 
 static int ce6230_zl10353_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       deb_info("%s:\n", __func__);
-       adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
-               &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL)
+       struct dvb_usb_device *d = adap_to_d(adap);
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       adap->fe[0] = dvb_attach(zl10353_attach, &ce6230_zl10353_config,
+                       &d->i2c_adap);
+       if (adap->fe[0] == NULL)
                return -ENODEV;
+
        return 0;
 }
 
@@ -212,9 +209,12 @@ static struct mxl5005s_config ce6230_mxl5003s_config = {
 
 static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
+       struct dvb_usb_device *d = adap_to_d(adap);
        int ret;
-       deb_info("%s:\n", __func__);
-       ret = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       ret = dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap,
                        &ce6230_mxl5003s_config) == NULL ? -ENODEV : 0;
        return ret;
 }
@@ -222,103 +222,71 @@ static int ce6230_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 static int ce6230_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        int ret;
-       deb_info("%s: onoff:%d\n", __func__, onoff);
+
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
 
        /* InterfaceNumber 1 / AlternateSetting 0     idle
           InterfaceNumber 1 / AlternateSetting 1     streaming */
        ret = usb_set_interface(d->udev, 1, onoff);
        if (ret)
-               err("usb_set_interface failed with error:%d", ret);
+               dev_err(&d->udev->dev, "%s: usb_set_interface() failed=%d\n",
+                               KBUILD_MODNAME, ret);
 
        return ret;
 }
 
 /* DVB USB Driver stuff */
-static struct dvb_usb_device_properties ce6230_properties;
-
-static int ce6230_probe(struct usb_interface *intf,
-                       const struct usb_device_id *id)
-{
-       int ret = 0;
-       struct dvb_usb_device *d = NULL;
-
-       deb_info("%s: interface:%d\n", __func__,
-               intf->cur_altsetting->desc.bInterfaceNumber);
+static struct dvb_usb_device_properties ce6230_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .bInterfaceNumber = 1,
 
-       if (intf->cur_altsetting->desc.bInterfaceNumber == 1) {
-               ret = dvb_usb_device_init(intf, &ce6230_properties, THIS_MODULE,
-                       &d, adapter_nr);
-               if (ret)
-                       err("init failed with error:%d\n", ret);
-       }
-
-       return ret;
-}
-
-static struct usb_device_id ce6230_table[] = {
-       { USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500) },
-       { USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310) },
-       { } /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, ce6230_table);
-
-static struct dvb_usb_device_properties ce6230_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-       .usb_ctrl = DEVICE_SPECIFIC,
-       .no_reconnect = 1,
-
-       .size_of_priv = 0,
+       .i2c_algo = &ce6230_i2c_algorithm,
+       .power_ctrl = ce6230_power_ctrl,
+       .frontend_attach = ce6230_zl10353_frontend_attach,
+       .tuner_attach = ce6230_mxl5003s_tuner_attach,
 
        .num_adapters = 1,
        .adapter = {
                {
-               .num_frontends = 1,
-               .fe = {{
-                       .frontend_attach  = ce6230_zl10353_frontend_attach,
-                       .tuner_attach     = ce6230_mxl5003s_tuner_attach,
                        .stream = {
                                .type = USB_BULK,
                                .count = 6,
                                .endpoint = 0x82,
                                .u = {
                                        .bulk = {
-                                               .buffersize = (16*512),
+                                               .buffersize = (16 * 512),
                                        }
                                }
                        },
-               }},
                }
        },
-
-       .power_ctrl = ce6230_power_ctrl,
-
-       .i2c_algo = &ce6230_i2c_algo,
-
-       .num_device_descs = 2,
-       .devices = {
-               {
-                       .name = "Intel CE9500 reference design",
-                       .cold_ids = {NULL},
-                       .warm_ids = {&ce6230_table[0], NULL},
-               },
-               {
-                       .name = "AVerMedia A310 USB 2.0 DVB-T tuner",
-                       .cold_ids = {NULL},
-                       .warm_ids = {&ce6230_table[1], NULL},
-               },
-       }
 };
 
-static struct usb_driver ce6230_driver = {
-       .name       = "dvb_usb_ce6230",
-       .probe      = ce6230_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table   = ce6230_table,
+static const struct usb_device_id ce6230_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_INTEL, USB_PID_INTEL_CE9500,
+               &ce6230_props, "Intel CE9500 reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_AVERMEDIA, USB_PID_AVERMEDIA_A310,
+               &ce6230_props, "AVerMedia A310 USB 2.0 DVB-T tuner", NULL) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, ce6230_id_table);
+
+static struct usb_driver ce6230_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = ce6230_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
-module_usb_driver(ce6230_driver);
+module_usb_driver(ce6230_usb_driver);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("Driver for Intel CE6230 DVB-T USB2.0");
+MODULE_DESCRIPTION("Intel CE6230 driver");
 MODULE_LICENSE("GPL");
similarity index 58%
rename from drivers/media/dvb/dvb-usb/ce6230.h
rename to drivers/media/usb/dvb-usb-v2/ce6230.h
index 97c42482ccb3de40e9f11e19289111227e501581..299e57e3390b8714549b867bf67df3adc02f6b24 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * DVB USB Linux driver for Intel CE6230 DVB-T USB2.0 receiver
+ * Intel CE6230 DVB USB driver
  *
  * Copyright (C) 2009 Antti Palosaari <crope@iki.fi>
  *
  *
  */
 
-#ifndef _DVB_USB_CE6230_H_
-#define _DVB_USB_CE6230_H_
+#ifndef CE6230_H
+#define CE6230_H
 
-#define DVB_USB_LOG_PREFIX "ce6230"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_ce6230_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_ce6230_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_ce6230_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_ce6230_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_ce6230_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_ce6230_debug, 0x20, args)
-
-#define ce6230_debug_dump(r, t, v, i, b, l, func) { \
-       int loop_; \
-       func("%02x %02x %02x %02x %02x %02x %02x %02x", \
-               t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
-       if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
-               func(" >>> "); \
-       else \
-               func(" <<< "); \
-       for (loop_ = 0; loop_ < l; loop_++) \
-               func("%02x ", b[loop_]); \
-       func("\n");\
-}
+#include "dvb_usb.h"
+#include "zl10353.h"
+#include "mxl5005s.h"
 
 #define CE6230_USB_TIMEOUT 1000
 
-struct req_t {
+struct usb_req {
        u8  cmd;       /* [1] */
        u16 value;     /* [2|3] */
        u16 index;     /* [4|5] */
diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.c b/drivers/media/usb/dvb-usb-v2/cypress_firmware.c
new file mode 100644 (file)
index 0000000..211df54
--- /dev/null
@@ -0,0 +1,134 @@
+/*  cypress_firmware.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for downloading the firmware to Cypress FX 1
+ * and 2 based devices.
+ *
+ */
+
+#include "dvb_usb.h"
+#include "cypress_firmware.h"
+
+struct usb_cypress_controller {
+       u8 id;
+       const char *name;       /* name of the usb controller */
+       u16 cs_reg;             /* needs to be restarted,
+                                * when the firmware has been downloaded */
+};
+
+static const struct usb_cypress_controller cypress[] = {
+       { .id = CYPRESS_AN2135, .name = "Cypress AN2135", .cs_reg = 0x7f92 },
+       { .id = CYPRESS_AN2235, .name = "Cypress AN2235", .cs_reg = 0x7f92 },
+       { .id = CYPRESS_FX2,    .name = "Cypress FX2",    .cs_reg = 0xe600 },
+};
+
+/*
+ * load a firmware packet to the device
+ */
+static int usb_cypress_writemem(struct usb_device *udev, u16 addr, u8 *data,
+               u8 len)
+{
+       dvb_usb_dbg_usb_control_msg(udev,
+                       0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len);
+
+       return usb_control_msg(udev, usb_sndctrlpipe(udev, 0),
+                       0xa0, USB_TYPE_VENDOR, addr, 0x00, data, len, 5000);
+}
+
+int usbv2_cypress_load_firmware(struct usb_device *udev,
+               const struct firmware *fw, int type)
+{
+       struct hexline *hx;
+       int ret, pos = 0;
+
+       hx = kmalloc(sizeof(struct hexline), GFP_KERNEL);
+       if (!hx) {
+               dev_err(&udev->dev, "%s: kmalloc() failed\n", KBUILD_MODNAME);
+               return -ENOMEM;
+       }
+
+       /* stop the CPU */
+       hx->data[0] = 1;
+       ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
+       if (ret != 1) {
+               dev_err(&udev->dev, "%s: CPU stop failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               ret = -EIO;
+               goto err_kfree;
+       }
+
+       /* write firmware to memory */
+       for (;;) {
+               ret = dvb_usbv2_get_hexline(fw, hx, &pos);
+               if (ret < 0)
+                       goto err_kfree;
+               else if (ret == 0)
+                       break;
+
+               ret = usb_cypress_writemem(udev, hx->addr, hx->data, hx->len);
+               if (ret < 0) {
+                       goto err_kfree;
+               } else if (ret != hx->len) {
+                       dev_err(&udev->dev, "%s: error while transferring " \
+                                       "firmware (transferred size=%d, " \
+                                       "block size=%d)\n",
+                                       KBUILD_MODNAME, ret, hx->len);
+                       ret = -EIO;
+                       goto err_kfree;
+               }
+       }
+
+       /* start the CPU */
+       hx->data[0] = 0;
+       ret = usb_cypress_writemem(udev, cypress[type].cs_reg, hx->data, 1);
+       if (ret != 1) {
+               dev_err(&udev->dev, "%s: CPU start failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               ret = -EIO;
+               goto err_kfree;
+       }
+
+       ret = 0;
+err_kfree:
+       kfree(hx);
+       return ret;
+}
+EXPORT_SYMBOL(usbv2_cypress_load_firmware);
+
+int dvb_usbv2_get_hexline(const struct firmware *fw, struct hexline *hx,
+               int *pos)
+{
+       u8 *b = (u8 *) &fw->data[*pos];
+       int data_offs = 4;
+
+       if (*pos >= fw->size)
+               return 0;
+
+       memset(hx, 0, sizeof(struct hexline));
+       hx->len = b[0];
+
+       if ((*pos + hx->len + 4) >= fw->size)
+               return -EINVAL;
+
+       hx->addr = b[1] | (b[2] << 8);
+       hx->type = b[3];
+
+       if (hx->type == 0x04) {
+               /* b[4] and b[5] are the Extended linear address record data
+                * field */
+               hx->addr |= (b[4] << 24) | (b[5] << 16);
+       }
+
+       memcpy(hx->data, &b[data_offs], hx->len);
+       hx->chk = b[hx->len + data_offs];
+       *pos += hx->len + 5;
+
+       return *pos;
+}
+EXPORT_SYMBOL(dvb_usbv2_get_hexline);
+
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("Cypress firmware download");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/dvb-usb-v2/cypress_firmware.h b/drivers/media/usb/dvb-usb-v2/cypress_firmware.h
new file mode 100644 (file)
index 0000000..80085fd
--- /dev/null
@@ -0,0 +1,31 @@
+/* cypress_firmware.h is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file contains functions for downloading the firmware to Cypress FX 1
+ * and 2 based devices.
+ *
+ */
+
+#ifndef CYPRESS_FIRMWARE_H
+#define CYPRESS_FIRMWARE_H
+
+#define CYPRESS_AN2135  0
+#define CYPRESS_AN2235  1
+#define CYPRESS_FX2     2
+
+/* commonly used firmware download types and function */
+struct hexline {
+       u8 len;
+       u32 addr;
+       u8 type;
+       u8 data[255];
+       u8 chk;
+};
+extern int usbv2_cypress_load_firmware(struct usb_device *,
+               const struct firmware *, int);
+extern int dvb_usbv2_get_hexline(const struct firmware *,
+               struct hexline *, int *);
+
+#endif
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb.h b/drivers/media/usb/dvb-usb-v2/dvb_usb.h
new file mode 100644 (file)
index 0000000..bae16a1
--- /dev/null
@@ -0,0 +1,403 @@
+/*
+ * DVB USB framework
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de>
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DVB_USB_H
+#define DVB_USB_H
+
+#include <linux/usb/input.h>
+#include <linux/firmware.h>
+#include <media/rc-core.h>
+
+#include "dvb_frontend.h"
+#include "dvb_demux.h"
+#include "dvb_net.h"
+#include "dmxdev.h"
+#include "dvb-usb-ids.h"
+
+/*
+ * device file: /dev/dvb/adapter[0-1]/frontend[0-2]
+ *
+ * |-- device
+ * |   |-- adapter0
+ * |   |   |-- frontend0
+ * |   |   |-- frontend1
+ * |   |   `-- frontend2
+ * |   `-- adapter1
+ * |       |-- frontend0
+ * |       |-- frontend1
+ * |       `-- frontend2
+ *
+ *
+ * Commonly used variable names:
+ * d = pointer to device (struct dvb_usb_device *)
+ * adap = pointer to adapter (struct dvb_usb_adapter *)
+ * fe = pointer to frontend (struct dvb_frontend *)
+ *
+ * Use macros defined in that file to resolve needed pointers.
+ */
+
+/* helper macros for every DVB USB driver use */
+#define adap_to_d(adap) (container_of(adap, struct dvb_usb_device, \
+               adapter[adap->id]))
+#define adap_to_priv(adap) (adap_to_d(adap)->priv)
+#define fe_to_adap(fe) ((struct dvb_usb_adapter *) ((fe)->dvb->priv))
+#define fe_to_d(fe) (adap_to_d(fe_to_adap(fe)))
+#define fe_to_priv(fe) (fe_to_d(fe)->priv)
+#define d_to_priv(d) (d->priv)
+
+#define dvb_usb_dbg_usb_control_msg(udev, r, t, v, i, b, l) { \
+       char *direction; \
+       if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
+               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); \
+}
+
+#define DVB_USB_STREAM_BULK(endpoint_, count_, size_) { \
+       .type = USB_BULK, \
+       .count = count_, \
+       .endpoint = endpoint_, \
+       .u = { \
+               .bulk = { \
+                       .buffersize = size_, \
+               } \
+       } \
+}
+
+#define DVB_USB_STREAM_ISOC(endpoint_, count_, frames_, size_, interval_) { \
+       .type = USB_ISOC, \
+       .count = count_, \
+       .endpoint = endpoint_, \
+       .u = { \
+               .isoc = { \
+                       .framesperurb = frames_, \
+                       .framesize = size_,\
+                       .interval = interval_, \
+               } \
+       } \
+}
+
+#define DVB_USB_DEVICE(vend, prod, props_, name_, rc) \
+       .match_flags = USB_DEVICE_ID_MATCH_DEVICE, \
+       .idVendor = (vend), \
+       .idProduct = (prod), \
+       .driver_info = (kernel_ulong_t) &((const struct dvb_usb_driver_info) { \
+               .props = (props_), \
+               .name = (name_), \
+               .rc_map = (rc), \
+       })
+
+struct dvb_usb_device;
+struct dvb_usb_adapter;
+
+/**
+ * structure for carrying all needed data from the device driver to the general
+ * dvb usb routines
+ * @name: device name
+ * @rc_map: name of rc codes table
+ * @props: structure containing all device properties
+ */
+struct dvb_usb_driver_info {
+       const char *name;
+       const char *rc_map;
+       const struct dvb_usb_device_properties *props;
+};
+
+/**
+ * structure for remote controller configuration
+ * @map_name: name of rc codes table
+ * @allowed_protos: protocol(s) supported by the driver
+ * @change_protocol: callback to change protocol
+ * @query: called to query an event from the device
+ * @interval: time in ms between two queries
+ * @driver_type: used to point if a device supports raw mode
+ * @bulk_mode: device supports bulk mode for rc (disable polling mode)
+ */
+struct dvb_usb_rc {
+       const char *map_name;
+       u64 allowed_protos;
+       int (*change_protocol)(struct rc_dev *dev, u64 rc_type);
+       int (*query) (struct dvb_usb_device *d);
+       unsigned int interval;
+       const enum rc_driver_type driver_type;
+       bool bulk_mode;
+};
+
+/**
+ * usb streaming configration for adapter
+ * @type: urb type
+ * @count: count of used urbs
+ * @endpoint: stream usb endpoint number
+ */
+struct usb_data_stream_properties {
+#define USB_BULK  1
+#define USB_ISOC  2
+       u8 type;
+       u8 count;
+       u8 endpoint;
+
+       union {
+               struct {
+                       unsigned int buffersize; /* per URB */
+               } bulk;
+               struct {
+                       int framesperurb;
+                       int framesize;
+                       int interval;
+               } isoc;
+       } u;
+};
+
+/**
+ * properties of dvb usb device adapter
+ * @caps: adapter capabilities
+ * @pid_filter_count: pid count of adapter pid-filter
+ * @pid_filter_ctrl: called to enable/disable pid-filter
+ * @pid_filter: called to set/unset pid for filtering
+ * @stream: adapter usb stream configuration
+ */
+#define MAX_NO_OF_FE_PER_ADAP 3
+struct dvb_usb_adapter_properties {
+#define DVB_USB_ADAP_HAS_PID_FILTER               0x01
+#define DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF 0x02
+#define DVB_USB_ADAP_NEED_PID_FILTERING           0x04
+       u8 caps;
+
+       u8 pid_filter_count;
+       int (*pid_filter_ctrl) (struct dvb_usb_adapter *, int);
+       int (*pid_filter) (struct dvb_usb_adapter *, int, u16, int);
+
+       struct usb_data_stream_properties stream;
+};
+
+/**
+ * struct dvb_usb_device_properties - properties of a dvb-usb-device
+ * @driver_name: name of the owning driver module
+ * @owner: owner of the dvb_adapter
+ * @adapter_nr: values from the DVB_DEFINE_MOD_OPT_ADAPTER_NR() macro
+ * @bInterfaceNumber: usb interface number driver binds
+ * @size_of_priv: bytes allocated for the driver private data
+ * @generic_bulk_ctrl_endpoint: bulk control endpoint number for sent
+ * @generic_bulk_ctrl_endpoint_response: bulk control endpoint number for
+ *  receive
+ * @generic_bulk_ctrl_delay: delay between bulk control sent and receive message
+ * @identify_state: called to determine the firmware state (cold or warm) and
+ *  return possible firmware file name to be loaded
+ * @firmware: name of the firmware file to be loaded
+ * @download_firmware: called to download the firmware
+ * @i2c_algo: i2c_algorithm if the device has i2c-adapter
+ * @num_adapters: dvb usb device adapter count
+ * @get_adapter_count: called to resolve adapter count
+ * @adapter: array of all adapter properties of device
+ * @power_ctrl: called to enable/disable power of the device
+ * @read_config: called to resolve device configuration
+ * @read_mac_address: called to resolve adapter mac-address
+ * @frontend_attach: called to attach the possible frontends
+ * @tuner_attach: called to attach the possible tuners
+ * @frontend_ctrl: called to power on/off active frontend
+ * @streaming_ctrl: called to start/stop the usb streaming of adapter
+ * @init: called after adapters are created in order to finalize device
+ *  configuration
+ * @exit: called when driver is unloaded
+ * @get_rc_config: called to resolve used remote controller configuration
+ * @get_stream_config: called to resolve input and output stream configuration
+ *  of the adapter just before streaming is started. input stream is transport
+ *  stream from the demodulator and output stream is usb stream to host.
+ */
+#define MAX_NO_OF_ADAPTER_PER_DEVICE 2
+struct dvb_usb_device_properties {
+       const char *driver_name;
+       struct module *owner;
+       short *adapter_nr;
+
+       u8 bInterfaceNumber;
+       unsigned int size_of_priv;
+       u8 generic_bulk_ctrl_endpoint;
+       u8 generic_bulk_ctrl_endpoint_response;
+       unsigned int generic_bulk_ctrl_delay;
+
+#define WARM                  0
+#define COLD                  1
+       int (*identify_state) (struct dvb_usb_device *, const char **);
+       const char *firmware;
+#define RECONNECTS_USB        1
+       int (*download_firmware) (struct dvb_usb_device *,
+                       const struct firmware *);
+
+       struct i2c_algorithm *i2c_algo;
+
+       unsigned int num_adapters;
+       int (*get_adapter_count) (struct dvb_usb_device *);
+       struct dvb_usb_adapter_properties adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
+       int (*power_ctrl) (struct dvb_usb_device *, int);
+       int (*read_config) (struct dvb_usb_device *d);
+       int (*read_mac_address) (struct dvb_usb_adapter *, u8 []);
+       int (*frontend_attach) (struct dvb_usb_adapter *);
+       int (*tuner_attach) (struct dvb_usb_adapter *);
+       int (*frontend_ctrl) (struct dvb_frontend *, int);
+       int (*streaming_ctrl) (struct dvb_frontend *, int);
+       int (*init) (struct dvb_usb_device *);
+       void (*exit) (struct dvb_usb_device *);
+       int (*get_rc_config) (struct dvb_usb_device *, struct dvb_usb_rc *);
+#define DVB_USB_FE_TS_TYPE_188        0
+#define DVB_USB_FE_TS_TYPE_204        1
+#define DVB_USB_FE_TS_TYPE_RAW        2
+       int (*get_stream_config) (struct dvb_frontend *,  u8 *,
+                       struct usb_data_stream_properties *);
+};
+
+/**
+ * generic object of an usb stream
+ * @buf_num: number of buffer allocated
+ * @buf_size: size of each buffer in buf_list
+ * @buf_list: array containing all allocate buffers for streaming
+ * @dma_addr: list of dma_addr_t for each buffer in buf_list
+ *
+ * @urbs_initialized: number of URBs initialized
+ * @urbs_submitted: number of URBs submitted
+ */
+#define MAX_NO_URBS_FOR_DATA_STREAM 10
+struct usb_data_stream {
+       struct usb_device *udev;
+       struct usb_data_stream_properties props;
+
+#define USB_STATE_INIT    0x00
+#define USB_STATE_URB_BUF 0x01
+       u8 state;
+
+       void (*complete) (struct usb_data_stream *, u8 *, size_t);
+
+       struct urb    *urb_list[MAX_NO_URBS_FOR_DATA_STREAM];
+       int            buf_num;
+       unsigned long  buf_size;
+       u8            *buf_list[MAX_NO_URBS_FOR_DATA_STREAM];
+       dma_addr_t     dma_addr[MAX_NO_URBS_FOR_DATA_STREAM];
+
+       int urbs_initialized;
+       int urbs_submitted;
+
+       void *user_priv;
+};
+
+/**
+ * dvb adapter object on dvb usb device
+ * @props: pointer to adapter properties
+ * @stream: adapter the usb data stream
+ * @id: index of this adapter (starting with 0)
+ * @ts_type: transport stream, input stream, type
+ * @suspend_resume_active: set when there is ongoing suspend / resume
+ * @pid_filtering: is hardware pid_filtering used or not
+ * @feed_count: current feed count
+ * @max_feed_count: maimum feed count device can handle
+ * @dvb_adap: adapter dvb_adapter
+ * @dmxdev: adapter dmxdev
+ * @demux: adapter software demuxer
+ * @dvb_net: adapter dvb_net interfaces
+ * @sync_mutex: mutex used to sync control and streaming of the adapter
+ * @fe: adapter frontends
+ * @fe_init: rerouted frontend-init function
+ * @fe_sleep: rerouted frontend-sleep function
+ */
+struct dvb_usb_adapter {
+       const struct dvb_usb_adapter_properties *props;
+       struct usb_data_stream stream;
+       u8 id;
+       u8 ts_type;
+       bool suspend_resume_active;
+       bool pid_filtering;
+       u8 feed_count;
+       u8 max_feed_count;
+       s8 active_fe;
+
+       /* dvb */
+       struct dvb_adapter   dvb_adap;
+       struct dmxdev        dmxdev;
+       struct dvb_demux     demux;
+       struct dvb_net       dvb_net;
+       struct mutex         sync_mutex;
+
+       struct dvb_frontend *fe[MAX_NO_OF_FE_PER_ADAP];
+       int (*fe_init[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *);
+       int (*fe_sleep[MAX_NO_OF_FE_PER_ADAP]) (struct dvb_frontend *);
+};
+
+/**
+ * dvb usb device object
+ * @props: device properties
+ * @name: device name
+ * @rc_map: name of rc codes table
+ * @udev: pointer to the device's struct usb_device
+ * @intf: pointer to the device's usb interface
+ * @rc: remote controller configuration
+ * @probe_work: work to defer .probe()
+ * @powered: indicated whether the device is power or not
+ * @usb_mutex: mutex for usb control messages
+ * @i2c_mutex: mutex for i2c-transfers
+ * @i2c_adap: device's i2c-adapter
+ * @rc_dev: rc device for the remote control
+ * @rc_query_work: work for polling remote
+ * @priv: private data of the actual driver (allocate by dvb usb, size defined
+ *  in size_of_priv of dvb_usb_properties).
+ */
+struct dvb_usb_device {
+       const struct dvb_usb_device_properties *props;
+       const char *name;
+       const char *rc_map;
+
+       struct usb_device *udev;
+       struct usb_interface *intf;
+       struct dvb_usb_rc rc;
+       struct work_struct probe_work;
+       pid_t work_pid;
+       int powered;
+
+       /* locking */
+       struct mutex usb_mutex;
+
+       /* i2c */
+       struct mutex i2c_mutex;
+       struct i2c_adapter i2c_adap;
+
+       struct dvb_usb_adapter adapter[MAX_NO_OF_ADAPTER_PER_DEVICE];
+
+       /* remote control */
+       struct rc_dev *rc_dev;
+       char rc_phys[64];
+       struct delayed_work rc_query_work;
+
+       void *priv;
+};
+
+extern int dvb_usbv2_probe(struct usb_interface *,
+               const struct usb_device_id *);
+extern void dvb_usbv2_disconnect(struct usb_interface *);
+extern int dvb_usbv2_suspend(struct usb_interface *, pm_message_t);
+extern int dvb_usbv2_resume(struct usb_interface *);
+extern int dvb_usbv2_reset_resume(struct usb_interface *);
+
+/* the generic read/write method for device control */
+extern int dvb_usbv2_generic_rw(struct dvb_usb_device *, u8 *, u16, u8 *, u16);
+extern int dvb_usbv2_generic_write(struct dvb_usb_device *, u8 *, u16);
+
+#endif
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h b/drivers/media/usb/dvb-usb-v2/dvb_usb_common.h
new file mode 100644 (file)
index 0000000..45f0709
--- /dev/null
@@ -0,0 +1,35 @@
+/*
+ * DVB USB framework
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de>
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#ifndef DVB_USB_COMMON_H
+#define DVB_USB_COMMON_H
+
+#include "dvb_usb.h"
+
+/* commonly used  methods */
+extern int usb_urb_initv2(struct usb_data_stream *stream,
+               const struct usb_data_stream_properties *props);
+extern int usb_urb_exitv2(struct usb_data_stream *stream);
+extern int usb_urb_submitv2(struct usb_data_stream *stream,
+               struct usb_data_stream_properties *props);
+extern int usb_urb_killv2(struct usb_data_stream *stream);
+
+#endif
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_core.c
new file mode 100644 (file)
index 0000000..9859d2a
--- /dev/null
@@ -0,0 +1,1049 @@
+/*
+ * DVB USB framework
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de>
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dvb_usb_common.h"
+
+int dvb_usbv2_disable_rc_polling;
+module_param_named(disable_rc_polling, dvb_usbv2_disable_rc_polling, int, 0644);
+MODULE_PARM_DESC(disable_rc_polling,
+               "disable remote control polling (default: 0)");
+static int dvb_usb_force_pid_filter_usage;
+module_param_named(force_pid_filter_usage, dvb_usb_force_pid_filter_usage,
+               int, 0444);
+MODULE_PARM_DESC(force_pid_filter_usage, "force all DVB USB devices to use a " \
+               "PID filter, if any (default: 0)");
+
+static int dvb_usbv2_download_firmware(struct dvb_usb_device *d, const char *name)
+{
+       int ret;
+       const struct firmware *fw;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       if (!d->props->download_firmware) {
+               ret = -EINVAL;
+               goto err;
+       }
+
+       ret = request_firmware(&fw, name, &d->udev->dev);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: Did not find the firmware file "\
+                               "'%s'. Please see linux/Documentation/dvb/ " \
+                               "for more details on firmware-problems. " \
+                               "Status %d\n", KBUILD_MODNAME, name, ret);
+               goto err;
+       }
+
+       dev_info(&d->udev->dev, "%s: downloading firmware from file '%s'\n",
+                       KBUILD_MODNAME, name);
+
+       ret = d->props->download_firmware(d, fw);
+       release_firmware(fw);
+       if (ret < 0)
+               goto err;
+
+       return ret;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usbv2_i2c_init(struct dvb_usb_device *d)
+{
+       int ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       if (!d->props->i2c_algo)
+               return 0;
+
+       strlcpy(d->i2c_adap.name, d->name, sizeof(d->i2c_adap.name));
+       d->i2c_adap.algo = d->props->i2c_algo;
+       d->i2c_adap.dev.parent = &d->udev->dev;
+       i2c_set_adapdata(&d->i2c_adap, d);
+
+       ret = i2c_add_adapter(&d->i2c_adap);
+       if (ret < 0) {
+               d->i2c_adap.algo = NULL;
+               dev_err(&d->udev->dev, "%s: i2c_add_adapter() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               goto err;
+       }
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usbv2_i2c_exit(struct dvb_usb_device *d)
+{
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       if (d->i2c_adap.algo)
+               i2c_del_adapter(&d->i2c_adap);
+
+       return 0;
+}
+
+static void dvb_usb_read_remote_control(struct work_struct *work)
+{
+       struct dvb_usb_device *d = container_of(work,
+                       struct dvb_usb_device, rc_query_work.work);
+       int ret;
+
+       /*
+        * When the parameter has been set to 1 via sysfs while the
+        * driver was running, or when bulk mode is enabled after IR init.
+        */
+       if (dvb_usbv2_disable_rc_polling || d->rc.bulk_mode)
+               return;
+
+       ret = d->rc.query(d);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: rc.query() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               return; /* stop polling */
+       }
+
+       schedule_delayed_work(&d->rc_query_work,
+                       msecs_to_jiffies(d->rc.interval));
+}
+
+static int dvb_usbv2_remote_init(struct dvb_usb_device *d)
+{
+       int ret;
+       struct rc_dev *dev;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       if (dvb_usbv2_disable_rc_polling || !d->props->get_rc_config)
+               return 0;
+
+       d->rc.map_name = d->rc_map;
+       ret = d->props->get_rc_config(d, &d->rc);
+       if (ret < 0)
+               goto err;
+
+       /* disable rc when there is no keymap defined */
+       if (!d->rc.map_name)
+               return 0;
+
+       dev = rc_allocate_device();
+       if (!dev) {
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       dev->dev.parent = &d->udev->dev;
+       dev->input_name = d->name;
+       usb_make_path(d->udev, d->rc_phys, sizeof(d->rc_phys));
+       strlcat(d->rc_phys, "/ir0", sizeof(d->rc_phys));
+       dev->input_phys = d->rc_phys;
+       usb_to_input_id(d->udev, &dev->input_id);
+       /* TODO: likely RC-core should took const char * */
+       dev->driver_name = (char *) d->props->driver_name;
+       dev->map_name = d->rc.map_name;
+       dev->driver_type = d->rc.driver_type;
+       dev->allowed_protos = d->rc.allowed_protos;
+       dev->change_protocol = d->rc.change_protocol;
+       dev->priv = d;
+
+       ret = rc_register_device(dev);
+       if (ret < 0) {
+               rc_free_device(dev);
+               goto err;
+       }
+
+       d->rc_dev = dev;
+
+       /* start polling if needed */
+       if (d->rc.query && !d->rc.bulk_mode) {
+               /* initialize a work queue for handling polling */
+               INIT_DELAYED_WORK(&d->rc_query_work,
+                               dvb_usb_read_remote_control);
+               dev_info(&d->udev->dev, "%s: schedule remote query interval " \
+                               "to %d msecs\n", KBUILD_MODNAME,
+                               d->rc.interval);
+               schedule_delayed_work(&d->rc_query_work,
+                               msecs_to_jiffies(d->rc.interval));
+       }
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usbv2_remote_exit(struct dvb_usb_device *d)
+{
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       if (d->rc_dev) {
+               cancel_delayed_work_sync(&d->rc_query_work);
+               rc_unregister_device(d->rc_dev);
+               d->rc_dev = NULL;
+       }
+
+       return 0;
+}
+
+static void dvb_usb_data_complete(struct usb_data_stream *stream, u8 *buf,
+               size_t len)
+{
+       struct dvb_usb_adapter *adap = stream->user_priv;
+       dvb_dmx_swfilter(&adap->demux, buf, len);
+}
+
+static void dvb_usb_data_complete_204(struct usb_data_stream *stream, u8 *buf,
+               size_t len)
+{
+       struct dvb_usb_adapter *adap = stream->user_priv;
+       dvb_dmx_swfilter_204(&adap->demux, buf, len);
+}
+
+static void dvb_usb_data_complete_raw(struct usb_data_stream *stream, u8 *buf,
+               size_t len)
+{
+       struct dvb_usb_adapter *adap = stream->user_priv;
+       dvb_dmx_swfilter_raw(&adap->demux, buf, len);
+}
+
+int dvb_usbv2_adapter_stream_init(struct dvb_usb_adapter *adap)
+{
+       dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
+                       adap->id);
+
+       adap->stream.udev = adap_to_d(adap)->udev;
+       adap->stream.user_priv = adap;
+       adap->stream.complete = dvb_usb_data_complete;
+
+       return usb_urb_initv2(&adap->stream, &adap->props->stream);
+}
+
+int dvb_usbv2_adapter_stream_exit(struct dvb_usb_adapter *adap)
+{
+       dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
+                       adap->id);
+
+       return usb_urb_exitv2(&adap->stream);
+}
+
+static inline int dvb_usb_ctrl_feed(struct dvb_demux_feed *dvbdmxfeed,
+               int count)
+{
+       struct dvb_usb_adapter *adap = dvbdmxfeed->demux->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       int ret;
+       dev_dbg(&d->udev->dev, "%s: adap=%d active_fe=%d feed_type=%d " \
+                       "setting pid [%s]: %04x (%04d) at index %d '%s'\n",
+                       __func__, adap->id, adap->active_fe, dvbdmxfeed->type,
+                       adap->pid_filtering ? "yes" : "no", dvbdmxfeed->pid,
+                       dvbdmxfeed->pid, dvbdmxfeed->index,
+                       (count == 1) ? "on" : "off");
+
+       if (adap->active_fe == -1)
+               return -EINVAL;
+
+       adap->feed_count += count;
+
+       /* stop feeding if it is last pid */
+       if (adap->feed_count == 0) {
+               dev_dbg(&d->udev->dev, "%s: stop feeding\n", __func__);
+
+               if (d->props->streaming_ctrl) {
+                       ret = d->props->streaming_ctrl(
+                                       adap->fe[adap->active_fe], 0);
+                       if (ret < 0) {
+                               dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
+                                               "failed=%d\n", KBUILD_MODNAME,
+                                               ret);
+                               usb_urb_killv2(&adap->stream);
+                               goto err_mutex_unlock;
+                       }
+               }
+               usb_urb_killv2(&adap->stream);
+               mutex_unlock(&adap->sync_mutex);
+       }
+
+       /* activate the pid on the device pid filter */
+       if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+                       adap->pid_filtering &&
+                       adap->props->pid_filter)
+               ret = adap->props->pid_filter(adap, dvbdmxfeed->index,
+                               dvbdmxfeed->pid, (count == 1) ? 1 : 0);
+                       if (ret < 0)
+                               dev_err(&d->udev->dev, "%s: pid_filter() " \
+                                               "failed=%d\n", KBUILD_MODNAME,
+                                               ret);
+
+       /* start feeding if it is first pid */
+       if (adap->feed_count == 1 && count == 1) {
+               struct usb_data_stream_properties stream_props;
+               mutex_lock(&adap->sync_mutex);
+               dev_dbg(&d->udev->dev, "%s: start feeding\n", __func__);
+
+               /* resolve input and output streaming paramters */
+               if (d->props->get_stream_config) {
+                       memcpy(&stream_props, &adap->props->stream,
+                               sizeof(struct usb_data_stream_properties));
+                       ret = d->props->get_stream_config(
+                                       adap->fe[adap->active_fe],
+                                       &adap->ts_type, &stream_props);
+                       if (ret < 0)
+                               goto err_mutex_unlock;
+               } else {
+                       stream_props = adap->props->stream;
+               }
+
+               switch (adap->ts_type) {
+               case DVB_USB_FE_TS_TYPE_204:
+                       adap->stream.complete = dvb_usb_data_complete_204;
+                       break;
+               case DVB_USB_FE_TS_TYPE_RAW:
+                       adap->stream.complete = dvb_usb_data_complete_raw;
+                       break;
+               case DVB_USB_FE_TS_TYPE_188:
+               default:
+                       adap->stream.complete = dvb_usb_data_complete;
+                       break;
+               }
+
+               usb_urb_submitv2(&adap->stream, &stream_props);
+
+               if (adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER &&
+                               adap->props->caps &
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF &&
+                               adap->props->pid_filter_ctrl) {
+                       ret = adap->props->pid_filter_ctrl(adap,
+                                       adap->pid_filtering);
+                       if (ret < 0) {
+                               dev_err(&d->udev->dev, "%s: " \
+                                               "pid_filter_ctrl() failed=%d\n",
+                                               KBUILD_MODNAME, ret);
+                               goto err_mutex_unlock;
+                       }
+               }
+
+               if (d->props->streaming_ctrl) {
+                       ret = d->props->streaming_ctrl(
+                                       adap->fe[adap->active_fe], 1);
+                       if (ret < 0) {
+                               dev_err(&d->udev->dev, "%s: streaming_ctrl() " \
+                                               "failed=%d\n", KBUILD_MODNAME,
+                                               ret);
+                               goto err_mutex_unlock;
+                       }
+               }
+       }
+
+       return 0;
+err_mutex_unlock:
+       mutex_unlock(&adap->sync_mutex);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usb_start_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       return dvb_usb_ctrl_feed(dvbdmxfeed, 1);
+}
+
+static int dvb_usb_stop_feed(struct dvb_demux_feed *dvbdmxfeed)
+{
+       return dvb_usb_ctrl_feed(dvbdmxfeed, -1);
+}
+
+int dvb_usbv2_adapter_dvb_init(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);
+
+       ret = dvb_register_adapter(&adap->dvb_adap, d->name, d->props->owner,
+                       &d->udev->dev, d->props->adapter_nr);
+       if (ret < 0) {
+               dev_dbg(&d->udev->dev, "%s: dvb_register_adapter() failed=%d\n",
+                               __func__, ret);
+               goto err_dvb_register_adapter;
+       }
+
+       adap->dvb_adap.priv = adap;
+
+       if (d->props->read_mac_address) {
+               ret = d->props->read_mac_address(adap,
+                               adap->dvb_adap.proposed_mac);
+               if (ret < 0)
+                       goto err_dvb_dmx_init;
+
+               dev_info(&d->udev->dev, "%s: MAC address: %pM\n",
+                               KBUILD_MODNAME, adap->dvb_adap.proposed_mac);
+       }
+
+       adap->demux.dmx.capabilities = DMX_TS_FILTERING | DMX_SECTION_FILTERING;
+       adap->demux.priv             = adap;
+       adap->demux.filternum        = 0;
+       adap->demux.filternum        = adap->max_feed_count;
+       adap->demux.feednum          = adap->demux.filternum;
+       adap->demux.start_feed       = dvb_usb_start_feed;
+       adap->demux.stop_feed        = dvb_usb_stop_feed;
+       adap->demux.write_to_decoder = NULL;
+       ret = dvb_dmx_init(&adap->demux);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: dvb_dmx_init() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               goto err_dvb_dmx_init;
+       }
+
+       adap->dmxdev.filternum       = adap->demux.filternum;
+       adap->dmxdev.demux           = &adap->demux.dmx;
+       adap->dmxdev.capabilities    = 0;
+       ret = dvb_dmxdev_init(&adap->dmxdev, &adap->dvb_adap);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: dvb_dmxdev_init() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               goto err_dvb_dmxdev_init;
+       }
+
+       ret = dvb_net_init(&adap->dvb_adap, &adap->dvb_net, &adap->demux.dmx);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: dvb_net_init() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+               goto err_dvb_net_init;
+       }
+
+       mutex_init(&adap->sync_mutex);
+
+       return 0;
+err_dvb_net_init:
+       dvb_dmxdev_release(&adap->dmxdev);
+err_dvb_dmxdev_init:
+       dvb_dmx_release(&adap->demux);
+err_dvb_dmx_init:
+       dvb_unregister_adapter(&adap->dvb_adap);
+err_dvb_register_adapter:
+       adap->dvb_adap.priv = NULL;
+       return ret;
+}
+
+int dvb_usbv2_adapter_dvb_exit(struct dvb_usb_adapter *adap)
+{
+       dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
+                       adap->id);
+
+       if (adap->dvb_adap.priv) {
+               dvb_net_release(&adap->dvb_net);
+               adap->demux.dmx.close(&adap->demux.dmx);
+               dvb_dmxdev_release(&adap->dmxdev);
+               dvb_dmx_release(&adap->demux);
+               dvb_unregister_adapter(&adap->dvb_adap);
+       }
+
+       return 0;
+}
+
+int dvb_usbv2_device_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       int ret;
+
+       if (onoff)
+               d->powered++;
+       else
+               d->powered--;
+
+       if (d->powered == 0 || (onoff && d->powered == 1)) {
+               /* when switching from 1 to 0 or from 0 to 1 */
+               dev_dbg(&d->udev->dev, "%s: power=%d\n", __func__, onoff);
+               if (d->props->power_ctrl) {
+                       ret = d->props->power_ctrl(d, onoff);
+                       if (ret < 0)
+                               goto err;
+               }
+       }
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usb_fe_init(struct dvb_frontend *fe)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
+                       fe->id);
+
+       if (!adap->suspend_resume_active) {
+               adap->active_fe = fe->id;
+               mutex_lock(&adap->sync_mutex);
+       }
+
+       ret = dvb_usbv2_device_power_ctrl(d, 1);
+       if (ret < 0)
+               goto err;
+
+       if (d->props->frontend_ctrl) {
+               ret = d->props->frontend_ctrl(fe, 1);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (adap->fe_init[fe->id]) {
+               ret = adap->fe_init[fe->id](fe);
+               if (ret < 0)
+                       goto err;
+       }
+err:
+       if (!adap->suspend_resume_active)
+               mutex_unlock(&adap->sync_mutex);
+
+       dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usb_fe_sleep(struct dvb_frontend *fe)
+{
+       int ret;
+       struct dvb_usb_adapter *adap = fe->dvb->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s: adap=%d fe=%d\n", __func__, adap->id,
+                       fe->id);
+
+       if (!adap->suspend_resume_active)
+               mutex_lock(&adap->sync_mutex);
+
+       if (adap->fe_sleep[fe->id]) {
+               ret = adap->fe_sleep[fe->id](fe);
+               if (ret < 0)
+                       goto err;
+       }
+
+       if (d->props->frontend_ctrl) {
+               ret = d->props->frontend_ctrl(fe, 0);
+               if (ret < 0)
+                       goto err;
+       }
+
+       ret = dvb_usbv2_device_power_ctrl(d, 0);
+       if (ret < 0)
+               goto err;
+err:
+       if (!adap->suspend_resume_active) {
+               adap->active_fe = -1;
+               mutex_unlock(&adap->sync_mutex);
+       }
+
+       dev_dbg(&d->udev->dev, "%s: ret=%d\n", __func__, ret);
+       return ret;
+}
+
+int dvb_usbv2_adapter_frontend_init(struct dvb_usb_adapter *adap)
+{
+       int ret, i, count_registered = 0;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s: adap=%d\n", __func__, adap->id);
+
+       memset(adap->fe, 0, sizeof(adap->fe));
+       adap->active_fe = -1;
+
+       if (d->props->frontend_attach) {
+               ret = d->props->frontend_attach(adap);
+               if (ret < 0) {
+                       dev_dbg(&d->udev->dev, "%s: frontend_attach() " \
+                                       "failed=%d\n", __func__, ret);
+                       goto err_dvb_frontend_detach;
+               }
+       } else {
+               dev_dbg(&d->udev->dev, "%s: frontend_attach() do not exists\n",
+                               __func__);
+               ret = 0;
+               goto err;
+       }
+
+       for (i = 0; i < MAX_NO_OF_FE_PER_ADAP && adap->fe[i]; i++) {
+               adap->fe[i]->id = i;
+               /* re-assign sleep and wakeup functions */
+               adap->fe_init[i] = adap->fe[i]->ops.init;
+               adap->fe[i]->ops.init = dvb_usb_fe_init;
+               adap->fe_sleep[i] = adap->fe[i]->ops.sleep;
+               adap->fe[i]->ops.sleep = dvb_usb_fe_sleep;
+
+               ret = dvb_register_frontend(&adap->dvb_adap, adap->fe[i]);
+               if (ret < 0) {
+                       dev_err(&d->udev->dev, "%s: frontend%d registration " \
+                                       "failed\n", KBUILD_MODNAME, i);
+                       goto err_dvb_unregister_frontend;
+               }
+
+               count_registered++;
+       }
+
+       if (d->props->tuner_attach) {
+               ret = d->props->tuner_attach(adap);
+               if (ret < 0) {
+                       dev_dbg(&d->udev->dev, "%s: tuner_attach() failed=%d\n",
+                                       __func__, ret);
+                       goto err_dvb_unregister_frontend;
+               }
+       }
+
+       return 0;
+
+err_dvb_unregister_frontend:
+       for (i = count_registered - 1; i >= 0; i--)
+               dvb_unregister_frontend(adap->fe[i]);
+
+err_dvb_frontend_detach:
+       for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) {
+               if (adap->fe[i]) {
+                       dvb_frontend_detach(adap->fe[i]);
+                       adap->fe[i] = NULL;
+               }
+       }
+
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+int dvb_usbv2_adapter_frontend_exit(struct dvb_usb_adapter *adap)
+{
+       int i;
+       dev_dbg(&adap_to_d(adap)->udev->dev, "%s: adap=%d\n", __func__,
+                       adap->id);
+
+       for (i = MAX_NO_OF_FE_PER_ADAP - 1; i >= 0; i--) {
+               if (adap->fe[i]) {
+                       dvb_unregister_frontend(adap->fe[i]);
+                       dvb_frontend_detach(adap->fe[i]);
+               }
+       }
+
+       return 0;
+}
+
+static int dvb_usbv2_adapter_init(struct dvb_usb_device *d)
+{
+       struct dvb_usb_adapter *adap;
+       int ret, i, adapter_count;
+
+       /* resolve adapter count */
+       adapter_count = d->props->num_adapters;
+       if (d->props->get_adapter_count) {
+               ret = d->props->get_adapter_count(d);
+               if (ret < 0)
+                       goto err;
+
+               adapter_count = ret;
+       }
+
+       for (i = 0; i < adapter_count; i++) {
+               adap = &d->adapter[i];
+               adap->id = i;
+               adap->props = &d->props->adapter[i];
+
+               /* speed - when running at FULL speed we need a HW PID filter */
+               if (d->udev->speed == USB_SPEED_FULL &&
+                               !(adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER)) {
+                       dev_err(&d->udev->dev, "%s: this USB2.0 device " \
+                                       "cannot be run on a USB1.1 port (it " \
+                                       "lacks a hardware PID filter)\n",
+                                       KBUILD_MODNAME);
+                       ret = -ENODEV;
+                       goto err;
+               } else if ((d->udev->speed == USB_SPEED_FULL &&
+                               adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) ||
+                               (adap->props->caps & DVB_USB_ADAP_NEED_PID_FILTERING)) {
+                       dev_info(&d->udev->dev, "%s: will use the device's " \
+                                       "hardware PID filter " \
+                                       "(table count: %d)\n", KBUILD_MODNAME,
+                                       adap->props->pid_filter_count);
+                       adap->pid_filtering  = 1;
+                       adap->max_feed_count = adap->props->pid_filter_count;
+               } else {
+                       dev_info(&d->udev->dev, "%s: will pass the complete " \
+                                       "MPEG2 transport stream to the " \
+                                       "software demuxer\n", KBUILD_MODNAME);
+                       adap->pid_filtering  = 0;
+                       adap->max_feed_count = 255;
+               }
+
+               if (!adap->pid_filtering && dvb_usb_force_pid_filter_usage &&
+                               adap->props->caps & DVB_USB_ADAP_HAS_PID_FILTER) {
+                       dev_info(&d->udev->dev, "%s: PID filter enabled by " \
+                                       "module option\n", KBUILD_MODNAME);
+                       adap->pid_filtering  = 1;
+                       adap->max_feed_count = adap->props->pid_filter_count;
+               }
+
+               ret = dvb_usbv2_adapter_stream_init(adap);
+               if (ret)
+                       goto err;
+
+               ret = dvb_usbv2_adapter_dvb_init(adap);
+               if (ret)
+                       goto err;
+
+               ret = dvb_usbv2_adapter_frontend_init(adap);
+               if (ret)
+                       goto err;
+
+               /* use exclusive FE lock if there is multiple shared FEs */
+               if (adap->fe[1])
+                       adap->dvb_adap.mfe_shared = 1;
+       }
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int dvb_usbv2_adapter_exit(struct dvb_usb_device *d)
+{
+       int i;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) {
+               if (d->adapter[i].props) {
+                       dvb_usbv2_adapter_frontend_exit(&d->adapter[i]);
+                       dvb_usbv2_adapter_dvb_exit(&d->adapter[i]);
+                       dvb_usbv2_adapter_stream_exit(&d->adapter[i]);
+               }
+       }
+
+       return 0;
+}
+
+/* general initialization functions */
+static int dvb_usbv2_exit(struct dvb_usb_device *d)
+{
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       dvb_usbv2_remote_exit(d);
+       dvb_usbv2_adapter_exit(d);
+       dvb_usbv2_i2c_exit(d);
+       kfree(d->priv);
+       kfree(d);
+
+       return 0;
+}
+
+static int dvb_usbv2_init(struct dvb_usb_device *d)
+{
+       int ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       dvb_usbv2_device_power_ctrl(d, 1);
+
+       if (d->props->read_config) {
+               ret = d->props->read_config(d);
+               if (ret < 0)
+                       goto err;
+       }
+
+       ret = dvb_usbv2_i2c_init(d);
+       if (ret < 0)
+               goto err;
+
+       ret = dvb_usbv2_adapter_init(d);
+       if (ret < 0)
+               goto err;
+
+       if (d->props->init) {
+               ret = d->props->init(d);
+               if (ret < 0)
+                       goto err;
+       }
+
+       ret = dvb_usbv2_remote_init(d);
+       if (ret < 0)
+               goto err;
+
+       dvb_usbv2_device_power_ctrl(d, 0);
+
+       return 0;
+err:
+       dvb_usbv2_device_power_ctrl(d, 0);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+/*
+ * udev, which is used for the firmware downloading, requires we cannot
+ * block during module_init(). module_init() calls USB probe() which
+ * is this routine. Due to that we delay actual operation using workqueue
+ * and return always success here.
+ */
+static void dvb_usbv2_init_work(struct work_struct *work)
+{
+       int ret;
+       struct dvb_usb_device *d =
+                       container_of(work, struct dvb_usb_device, probe_work);
+
+       d->work_pid = current->pid;
+       dev_dbg(&d->udev->dev, "%s: work_pid=%d\n", __func__, d->work_pid);
+
+       if (d->props->size_of_priv) {
+               d->priv = kzalloc(d->props->size_of_priv, GFP_KERNEL);
+               if (!d->priv) {
+                       dev_err(&d->udev->dev, "%s: kzalloc() failed\n",
+                                       KBUILD_MODNAME);
+                       ret = -ENOMEM;
+                       goto err_usb_driver_release_interface;
+               }
+       }
+
+       if (d->props->identify_state) {
+               const char *name = NULL;
+               ret = d->props->identify_state(d, &name);
+               if (ret == 0) {
+                       ;
+               } else if (ret == COLD) {
+                       dev_info(&d->udev->dev, "%s: found a '%s' in cold " \
+                                       "state\n", KBUILD_MODNAME, d->name);
+
+                       if (!name)
+                               name = d->props->firmware;
+
+                       ret = dvb_usbv2_download_firmware(d, name);
+                       if (ret == 0) {
+                               /* device is warm, continue initialization */
+                               ;
+                       } else if (ret == RECONNECTS_USB) {
+                               /*
+                                * USB core will call disconnect() and then
+                                * probe() as device reconnects itself from the
+                                * USB bus. disconnect() will release all driver
+                                * resources and probe() is called for 'new'
+                                * device. As 'new' device is warm we should
+                                * never go here again.
+                                */
+                               return;
+                       } else {
+                               /*
+                                * Unexpected error. We must unregister driver
+                                * manually from the device, because device is
+                                * already register by returning from probe()
+                                * with success. usb_driver_release_interface()
+                                * finally calls disconnect() in order to free
+                                * resources.
+                                */
+                               goto err_usb_driver_release_interface;
+                       }
+               } else {
+                       goto err_usb_driver_release_interface;
+               }
+       }
+
+       dev_info(&d->udev->dev, "%s: found a '%s' in warm state\n",
+                       KBUILD_MODNAME, d->name);
+
+       ret = dvb_usbv2_init(d);
+       if (ret < 0)
+               goto err_usb_driver_release_interface;
+
+       dev_info(&d->udev->dev, "%s: '%s' successfully initialized and " \
+                       "connected\n", KBUILD_MODNAME, d->name);
+
+       return;
+err_usb_driver_release_interface:
+       dev_info(&d->udev->dev, "%s: '%s' error while loading driver (%d)\n",
+                       KBUILD_MODNAME, d->name, ret);
+       usb_driver_release_interface(to_usb_driver(d->intf->dev.driver),
+                       d->intf);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return;
+}
+
+int dvb_usbv2_probe(struct usb_interface *intf,
+               const struct usb_device_id *id)
+{
+       int ret;
+       struct dvb_usb_device *d;
+       struct usb_device *udev = interface_to_usbdev(intf);
+       struct dvb_usb_driver_info *driver_info =
+                       (struct dvb_usb_driver_info *) id->driver_info;
+
+       dev_dbg(&udev->dev, "%s: bInterfaceNumber=%d\n", __func__,
+                       intf->cur_altsetting->desc.bInterfaceNumber);
+
+       if (!id->driver_info) {
+               dev_err(&udev->dev, "%s: driver_info failed\n", KBUILD_MODNAME);
+               ret = -ENODEV;
+               goto err;
+       }
+
+       d = kzalloc(sizeof(struct dvb_usb_device), GFP_KERNEL);
+       if (!d) {
+               dev_err(&udev->dev, "%s: kzalloc() failed\n", KBUILD_MODNAME);
+               ret = -ENOMEM;
+               goto err;
+       }
+
+       d->name = driver_info->name;
+       d->rc_map = driver_info->rc_map;
+       d->udev = udev;
+       d->intf = intf;
+       d->props = driver_info->props;
+
+       if (d->intf->cur_altsetting->desc.bInterfaceNumber !=
+                       d->props->bInterfaceNumber) {
+               ret = -ENODEV;
+               goto err_kfree;
+       }
+
+       mutex_init(&d->usb_mutex);
+       mutex_init(&d->i2c_mutex);
+       INIT_WORK(&d->probe_work, dvb_usbv2_init_work);
+       usb_set_intfdata(intf, d);
+       ret = schedule_work(&d->probe_work);
+       if (ret < 0) {
+               dev_err(&d->udev->dev, "%s: schedule_work() failed\n",
+                               KBUILD_MODNAME);
+               goto err_kfree;
+       }
+
+       return 0;
+err_kfree:
+       kfree(d);
+err:
+       dev_dbg(&udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+EXPORT_SYMBOL(dvb_usbv2_probe);
+
+void dvb_usbv2_disconnect(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       const char *name = d->name;
+       struct device dev = d->udev->dev;
+       dev_dbg(&d->udev->dev, "%s: pid=%d work_pid=%d\n", __func__,
+                       current->pid, d->work_pid);
+
+       /* ensure initialization work is finished until release resources */
+       if (d->work_pid != current->pid)
+               cancel_work_sync(&d->probe_work);
+
+       if (d->props->exit)
+               d->props->exit(d);
+
+       dvb_usbv2_exit(d);
+
+       dev_info(&dev, "%s: '%s' successfully deinitialized and disconnected\n",
+                       KBUILD_MODNAME, name);
+}
+EXPORT_SYMBOL(dvb_usbv2_disconnect);
+
+int dvb_usbv2_suspend(struct usb_interface *intf, pm_message_t msg)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       int ret = 0, i, active_fe;
+       struct dvb_frontend *fe;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* stop remote controller poll */
+       if (d->rc.query && !d->rc.bulk_mode)
+               cancel_delayed_work_sync(&d->rc_query_work);
+
+       for (i = MAX_NO_OF_ADAPTER_PER_DEVICE - 1; i >= 0; i--) {
+               active_fe = d->adapter[i].active_fe;
+               if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
+                       fe = d->adapter[i].fe[active_fe];
+                       d->adapter[i].suspend_resume_active = true;
+
+                       if (d->props->streaming_ctrl)
+                               d->props->streaming_ctrl(fe, 0);
+
+                       /* stop usb streaming */
+                       usb_urb_killv2(&d->adapter[i].stream);
+
+                       ret = dvb_frontend_suspend(fe);
+               }
+       }
+
+       return ret;
+}
+EXPORT_SYMBOL(dvb_usbv2_suspend);
+
+static int dvb_usbv2_resume_common(struct dvb_usb_device *d)
+{
+       int ret = 0, i, active_fe;
+       struct dvb_frontend *fe;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       for (i = 0; i < MAX_NO_OF_ADAPTER_PER_DEVICE; i++) {
+               active_fe = d->adapter[i].active_fe;
+               if (d->adapter[i].dvb_adap.priv && active_fe != -1) {
+                       fe = d->adapter[i].fe[active_fe];
+
+                       ret = dvb_frontend_resume(fe);
+
+                       /* resume usb streaming */
+                       usb_urb_submitv2(&d->adapter[i].stream, NULL);
+
+                       if (d->props->streaming_ctrl)
+                               d->props->streaming_ctrl(fe, 1);
+
+                       d->adapter[i].suspend_resume_active = false;
+               }
+       }
+
+       /* start remote controller poll */
+       if (d->rc.query && !d->rc.bulk_mode)
+               schedule_delayed_work(&d->rc_query_work,
+                               msecs_to_jiffies(d->rc.interval));
+
+       return ret;
+}
+
+int dvb_usbv2_resume(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       return dvb_usbv2_resume_common(d);
+}
+EXPORT_SYMBOL(dvb_usbv2_resume);
+
+int dvb_usbv2_reset_resume(struct usb_interface *intf)
+{
+       struct dvb_usb_device *d = usb_get_intfdata(intf);
+       int ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       dvb_usbv2_device_power_ctrl(d, 1);
+
+       if (d->props->init)
+               d->props->init(d);
+
+       ret = dvb_usbv2_resume_common(d);
+
+       dvb_usbv2_device_power_ctrl(d, 0);
+
+       return ret;
+}
+EXPORT_SYMBOL(dvb_usbv2_reset_resume);
+
+MODULE_VERSION("2.0");
+MODULE_AUTHOR("Patrick Boettcher <patrick.boettcher@desy.de>");
+MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
+MODULE_DESCRIPTION("DVB USB common");
+MODULE_LICENSE("GPL");
diff --git a/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c b/drivers/media/usb/dvb-usb-v2/dvb_usb_urb.c
new file mode 100644 (file)
index 0000000..0431bee
--- /dev/null
@@ -0,0 +1,77 @@
+/*
+ * DVB USB framework
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher <patrick.boettcher@desy.de>
+ * Copyright (C) 2012 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.
+ *
+ *    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.,
+ *    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ */
+
+#include "dvb_usb_common.h"
+
+int dvb_usbv2_generic_rw(struct dvb_usb_device *d, u8 *wbuf, u16 wlen, u8 *rbuf,
+               u16 rlen)
+{
+       int ret, actual_length;
+
+       if (!d || !wbuf || !wlen || !d->props->generic_bulk_ctrl_endpoint ||
+                       !d->props->generic_bulk_ctrl_endpoint_response) {
+               dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, -EINVAL);
+               return -EINVAL;
+       }
+
+       ret = mutex_lock_interruptible(&d->usb_mutex);
+       if (ret < 0)
+               return ret;
+
+       dev_dbg(&d->udev->dev, "%s: >>> %*ph\n", __func__, wlen, wbuf);
+
+       ret = usb_bulk_msg(d->udev, usb_sndbulkpipe(d->udev,
+                       d->props->generic_bulk_ctrl_endpoint), wbuf, wlen,
+                       &actual_length, 2000);
+       if (ret < 0)
+               dev_err(&d->udev->dev, "%s: usb_bulk_msg() failed=%d\n",
+                               KBUILD_MODNAME, ret);
+       else
+               ret = actual_length != wlen ? -EIO : 0;
+
+       /* an answer is expected, and no error before */
+       if (!ret && rbuf && rlen) {
+               if (d->props->generic_bulk_ctrl_delay)
+                       usleep_range(d->props->generic_bulk_ctrl_delay,
+                                       d->props->generic_bulk_ctrl_delay
+                                       + 20000);
+
+               ret = usb_bulk_msg(d->udev, usb_rcvbulkpipe(d->udev,
+                               d->props->generic_bulk_ctrl_endpoint_response),
+                               rbuf, rlen, &actual_length, 2000);
+               if (ret)
+                       dev_err(&d->udev->dev, "%s: 2nd usb_bulk_msg() " \
+                                       "failed=%d\n", KBUILD_MODNAME, ret);
+
+               dev_dbg(&d->udev->dev, "%s: <<< %*ph\n", __func__,
+                               actual_length, rbuf);
+       }
+
+       mutex_unlock(&d->usb_mutex);
+       return ret;
+}
+EXPORT_SYMBOL(dvb_usbv2_generic_rw);
+
+int dvb_usbv2_generic_write(struct dvb_usb_device *d, u8 *buf, u16 len)
+{
+       return dvb_usbv2_generic_rw(d, buf, len, NULL, 0);
+}
+EXPORT_SYMBOL(dvb_usbv2_generic_write);
similarity index 57%
rename from drivers/media/dvb/dvb-usb/ec168.c
rename to drivers/media/usb/dvb-usb-v2/ec168.c
index b4989ba8897d5fd5dbea9e55c3786b4a07fd2446..5c68f3918bc81279717131e15a5084e25e10d1d8 100644 (file)
 #include "ec100.h"
 #include "mxl5005s.h"
 
-/* debug */
-static int dvb_usb_ec168_debug;
-module_param_named(debug, dvb_usb_ec168_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
-static struct ec100_config ec168_ec100_config;
-
-static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
+static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)
 {
        int ret;
        unsigned int pipe;
        u8 request, requesttype;
        u8 *buf;
 
-
-
        switch (req->cmd) {
        case DOWNLOAD_FIRMWARE:
        case GPIO:
@@ -69,8 +61,9 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
                request = DEMOD_RW;
                break;
        default:
-               err("unknown command:%02x", req->cmd);
-               ret = -EPERM;
+               dev_err(&d->udev->dev, "%s: unknown command=%02x\n",
+                               KBUILD_MODNAME, req->cmd);
+               ret = -EINVAL;
                goto error;
        }
 
@@ -83,19 +76,19 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
        if (requesttype == (USB_TYPE_VENDOR | USB_DIR_OUT)) {
                /* write */
                memcpy(buf, req->data, req->size);
-               pipe = usb_sndctrlpipe(udev, 0);
+               pipe = usb_sndctrlpipe(d->udev, 0);
        } else {
                /* read */
-               pipe = usb_rcvctrlpipe(udev, 0);
+               pipe = usb_rcvctrlpipe(d->udev, 0);
        }
 
        msleep(1); /* avoid I2C errors */
 
-       ret = usb_control_msg(udev, pipe, request, requesttype, req->value,
+       ret = usb_control_msg(d->udev, pipe, request, requesttype, req->value,
                req->index, buf, req->size, EC168_USB_TIMEOUT);
 
-       ec168_debug_dump(request, requesttype, req->value, req->index, buf,
-               req->size, deb_xfer);
+       dvb_usb_dbg_usb_control_msg(d->udev, request, requesttype, req->value,
+                       req->index, buf, req->size);
 
        if (ret < 0)
                goto err_dealloc;
@@ -112,16 +105,13 @@ static int ec168_rw_udev(struct usb_device *udev, struct ec168_req *req)
 err_dealloc:
        kfree(buf);
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-static int ec168_ctrl_msg(struct dvb_usb_device *d, struct ec168_req *req)
-{
-       return ec168_rw_udev(d->udev, req);
-}
-
 /* I2C */
+static struct ec100_config ec168_ec100_config;
+
 static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
        int num)
 {
@@ -147,8 +137,10 @@ static int ec168_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
                                ret = ec168_ctrl_msg(d, &req);
                                i += 2;
                        } else {
-                               err("I2C read not implemented");
-                               ret = -ENOSYS;
+                               dev_err(&d->udev->dev, "%s: I2C read not " \
+                                               "implemented\n",
+                                               KBUILD_MODNAME);
+                               ret = -EOPNOTSUPP;
                                i += 2;
                        }
                } else {
@@ -181,7 +173,6 @@ error:
        return i;
 }
 
-
 static u32 ec168_i2c_func(struct i2c_adapter *adapter)
 {
        return I2C_FUNC_I2C;
@@ -193,88 +184,63 @@ static struct i2c_algorithm ec168_i2c_algo = {
 };
 
 /* Callbacks for DVB USB */
-static struct ec100_config ec168_ec100_config = {
-       .demod_address = 0xff, /* not real address, demod is integrated */
-};
-
-static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
+static int ec168_identify_state(struct dvb_usb_device *d, const char **name)
 {
-       deb_info("%s:\n", __func__);
-       adap->fe_adap[0].fe = dvb_attach(ec100_attach, &ec168_ec100_config,
-               &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL)
-               return -ENODEV;
+       int ret;
+       u8 reply;
+       struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-       return 0;
-}
+       ret = ec168_ctrl_msg(d, &req);
+       if (ret)
+               goto error;
 
-static struct mxl5005s_config ec168_mxl5003s_config = {
-       .i2c_address     = 0xc6,
-       .if_freq         = IF_FREQ_4570000HZ,
-       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
-       .agc_mode        = MXL_SINGLE_AGC,
-       .tracking_filter = MXL_TF_OFF,
-       .rssi_enable     = MXL_RSSI_ENABLE,
-       .cap_select      = MXL_CAP_SEL_ENABLE,
-       .div_out         = MXL_DIV_OUT_4,
-       .clock_out       = MXL_CLOCK_OUT_DISABLE,
-       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
-       .top             = MXL5005S_TOP_25P2,
-       .mod_mode        = MXL_DIGITAL_MODE,
-       .if_mode         = MXL_ZERO_IF,
-       .AgcMasterByte   = 0x00,
-};
+       dev_dbg(&d->udev->dev, "%s: reply=%02x\n", __func__, reply);
 
-static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
-{
-       deb_info("%s:\n", __func__);
-       return dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe, &adap->dev->i2c_adap,
-               &ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
-}
+       if (reply == 0x01)
+               ret = WARM;
+       else
+               ret = COLD;
 
-static int ec168_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};
-       deb_info("%s: onoff:%d\n", __func__, onoff);
-       if (onoff)
-               req.index = 0x0102;
-       return ec168_ctrl_msg(adap->dev, &req);
+       return ret;
+error:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
 }
 
-static int ec168_download_firmware(struct usb_device *udev,
-       const struct firmware *fw)
+static int ec168_download_firmware(struct dvb_usb_device *d,
+               const struct firmware *fw)
 {
-       int i, len, packets, remainder, ret;
-       u16 addr = 0x0000; /* firmware start address */
+       int ret, len, remaining;
        struct ec168_req req = {DOWNLOAD_FIRMWARE, 0, 0, 0, NULL};
-       deb_info("%s:\n", __func__);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-       #define FW_PACKET_MAX_DATA  2048
-       packets = fw->size / FW_PACKET_MAX_DATA;
-       remainder = fw->size % FW_PACKET_MAX_DATA;
-       len = FW_PACKET_MAX_DATA;
-       for (i = 0; i <= packets; i++) {
-               if (i == packets)  /* set size of the last packet */
-                       len = remainder;
+       #define LEN_MAX 2048 /* max packet size */
+       for (remaining = fw->size; remaining > 0; remaining -= LEN_MAX) {
+               len = remaining;
+               if (len > LEN_MAX)
+                       len = LEN_MAX;
 
                req.size = len;
-               req.data = (u8 *)(fw->data + i * FW_PACKET_MAX_DATA);
-               req.index = addr;
-               addr += FW_PACKET_MAX_DATA;
+               req.data = (u8 *) &fw->data[fw->size - remaining];
+               req.index = fw->size - remaining;
 
-               ret = ec168_rw_udev(udev, &req);
+               ret = ec168_ctrl_msg(d, &req);
                if (ret) {
-                       err("firmware download failed:%d packet:%d", ret, i);
+                       dev_err(&d->udev->dev,
+                                       "%s: firmware download failed=%d\n",
+                                       KBUILD_MODNAME, ret);
                        goto error;
                }
        }
+
        req.size = 0;
 
        /* set "warm"? */
        req.cmd = SET_CONFIG;
        req.value = 0;
        req.index = 0x0001;
-       ret = ec168_rw_udev(udev, &req);
+       ret = ec168_ctrl_msg(d, &req);
        if (ret)
                goto error;
 
@@ -282,7 +248,7 @@ static int ec168_download_firmware(struct usb_device *udev,
        req.cmd = GPIO;
        req.value = 0;
        req.index = 0x0206;
-       ret = ec168_rw_udev(udev, &req);
+       ret = ec168_ctrl_msg(d, &req);
        if (ret)
                goto error;
 
@@ -290,146 +256,130 @@ static int ec168_download_firmware(struct usb_device *udev,
        req.cmd = WRITE_I2C;
        req.value = 0;
        req.index = 0x00c6;
-       ret = ec168_rw_udev(udev, &req);
+       ret = ec168_ctrl_msg(d, &req);
        if (ret)
                goto error;
 
        return ret;
 error:
-       deb_info("%s: failed:%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-static int ec168_identify_state(struct usb_device *udev,
-       struct dvb_usb_device_properties *props,
-       struct dvb_usb_device_description **desc, int *cold)
-{
-       int ret;
-       u8 reply;
-       struct ec168_req req = {GET_CONFIG, 0, 1, sizeof(reply), &reply};
-       deb_info("%s:\n", __func__);
-
-       ret = ec168_rw_udev(udev, &req);
-       if (ret)
-               goto error;
+static struct ec100_config ec168_ec100_config = {
+       .demod_address = 0xff, /* not real address, demod is integrated */
+};
 
-       deb_info("%s: reply:%02x\n", __func__, reply);
+static int ec168_ec100_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-       if (reply == 0x01)
-               *cold = 0;
-       else
-               *cold = 1;
+       adap->fe[0] = dvb_attach(ec100_attach, &ec168_ec100_config,
+                       &d->i2c_adap);
+       if (adap->fe[0] == NULL)
+               return -ENODEV;
 
-       return ret;
-error:
-       deb_info("%s: failed:%d\n", __func__, ret);
-       return ret;
+       return 0;
 }
 
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties ec168_properties;
+static struct mxl5005s_config ec168_mxl5003s_config = {
+       .i2c_address     = 0xc6,
+       .if_freq         = IF_FREQ_4570000HZ,
+       .xtal_freq       = CRYSTAL_FREQ_16000000HZ,
+       .agc_mode        = MXL_SINGLE_AGC,
+       .tracking_filter = MXL_TF_OFF,
+       .rssi_enable     = MXL_RSSI_ENABLE,
+       .cap_select      = MXL_CAP_SEL_ENABLE,
+       .div_out         = MXL_DIV_OUT_4,
+       .clock_out       = MXL_CLOCK_OUT_DISABLE,
+       .output_load     = MXL5005S_IF_OUTPUT_LOAD_200_OHM,
+       .top             = MXL5005S_TOP_25P2,
+       .mod_mode        = MXL_DIGITAL_MODE,
+       .if_mode         = MXL_ZERO_IF,
+       .AgcMasterByte   = 0x00,
+};
 
-static int ec168_probe(struct usb_interface *intf,
-       const struct usb_device_id *id)
+static int ec168_mxl5003s_tuner_attach(struct dvb_usb_adapter *adap)
 {
-       int ret;
-       deb_info("%s: interface:%d\n", __func__,
-               intf->cur_altsetting->desc.bInterfaceNumber);
-
-       ret = dvb_usb_device_init(intf, &ec168_properties, THIS_MODULE, NULL,
-               adapter_nr);
-       if (ret)
-               goto error;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-       return ret;
-error:
-       deb_info("%s: failed:%d\n", __func__, ret);
-       return ret;
+       return dvb_attach(mxl5005s_attach, adap->fe[0], &d->i2c_adap,
+                       &ec168_mxl5003s_config) == NULL ? -ENODEV : 0;
 }
 
-#define E3C_EC168_1689                          0
-#define E3C_EC168_FFFA                          1
-#define E3C_EC168_FFFB                          2
-#define E3C_EC168_1001                          3
-#define E3C_EC168_1002                          4
-
-static struct usb_device_id ec168_id[] = {
-       [E3C_EC168_1689] =
-               {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168)},
-       [E3C_EC168_FFFA] =
-               {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2)},
-       [E3C_EC168_FFFB] =
-               {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3)},
-       [E3C_EC168_1001] =
-               {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4)},
-       [E3C_EC168_1002] =
-               {USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5)},
-       {} /* terminating entry */
-};
+static int ec168_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+       struct dvb_usb_device *d = fe_to_d(fe);
+       struct ec168_req req = {STREAMING_CTRL, 0x7f01, 0x0202, 0, NULL};
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
 
-MODULE_DEVICE_TABLE(usb, ec168_id);
+       if (onoff)
+               req.index = 0x0102;
+       return ec168_ctrl_msg(d, &req);
+}
 
-static struct dvb_usb_device_properties ec168_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
+/* DVB USB Driver stuff */
+/* bInterfaceNumber 0 is HID
+ * bInterfaceNumber 1 is DVB-T */
+static struct dvb_usb_device_properties ec168_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .bInterfaceNumber = 1,
 
-       .usb_ctrl = DEVICE_SPECIFIC,
+       .identify_state = ec168_identify_state,
+       .firmware = EC168_FIRMWARE,
        .download_firmware = ec168_download_firmware,
-       .firmware = "dvb-usb-ec168.fw",
-       .no_reconnect = 1,
 
-       .size_of_priv = 0,
+       .i2c_algo = &ec168_i2c_algo,
+       .frontend_attach = ec168_ec100_frontend_attach,
+       .tuner_attach = ec168_mxl5003s_tuner_attach,
+       .streaming_ctrl = ec168_streaming_ctrl,
 
        .num_adapters = 1,
        .adapter = {
                {
-               .num_frontends = 1,
-               .fe = {{
-                       .streaming_ctrl   = ec168_streaming_ctrl,
-                       .frontend_attach  = ec168_ec100_frontend_attach,
-                       .tuner_attach     = ec168_mxl5003s_tuner_attach,
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 6,
-                               .endpoint = 0x82,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = (32*512),
-                                       }
-                               }
-                       },
-               }},
+                       .stream = DVB_USB_STREAM_BULK(0x82, 6, 32 * 512),
                }
        },
+};
 
-       .identify_state = ec168_identify_state,
-
-       .i2c_algo = &ec168_i2c_algo,
+static const struct dvb_usb_driver_info ec168_driver_info = {
+       .name = "E3C EC168 reference design",
+       .props = &ec168_props,
+};
 
-       .num_device_descs = 1,
-       .devices = {
-               {
-                       .name = "E3C EC168 DVB-T USB2.0 reference design",
-                       .cold_ids = {
-                               &ec168_id[E3C_EC168_1689],
-                               &ec168_id[E3C_EC168_FFFA],
-                               &ec168_id[E3C_EC168_FFFB],
-                               &ec168_id[E3C_EC168_1001],
-                               &ec168_id[E3C_EC168_1002],
-                               NULL},
-                       .warm_ids = {NULL},
-               },
-       }
+static const struct usb_device_id ec168_id[] = {
+       { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168),
+               .driver_info = (kernel_ulong_t) &ec168_driver_info },
+       { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_2),
+               .driver_info = (kernel_ulong_t) &ec168_driver_info },
+       { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_3),
+               .driver_info = (kernel_ulong_t) &ec168_driver_info },
+       { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_4),
+               .driver_info = (kernel_ulong_t) &ec168_driver_info },
+       { USB_DEVICE(USB_VID_E3C, USB_PID_E3C_EC168_5),
+               .driver_info = (kernel_ulong_t) &ec168_driver_info },
+       {}
 };
+MODULE_DEVICE_TABLE(usb, ec168_id);
 
 static struct usb_driver ec168_driver = {
-       .name       = "dvb_usb_ec168",
-       .probe      = ec168_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table   = ec168_id,
+       .name = KBUILD_MODNAME,
+       .id_table = ec168_id,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
 module_usb_driver(ec168_driver);
 
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
-MODULE_DESCRIPTION("E3C EC168 DVB-T USB2.0 driver");
+MODULE_DESCRIPTION("E3C EC168 driver");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(EC168_FIRMWARE);
similarity index 62%
rename from drivers/media/dvb/dvb-usb/ec168.h
rename to drivers/media/usb/dvb-usb-v2/ec168.h
index e7e0b831314eeec4c42334f074ce87311d846eab..615a6569421f55298a07b4770711f0ef9e895113 100644 (file)
 #ifndef EC168_H
 #define EC168_H
 
-#define DVB_USB_LOG_PREFIX "ec168"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_ec168_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_ec168_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_ec168_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_ec168_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_ec168_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_ec168_debug, 0x20, args)
-
-#define ec168_debug_dump(r, t, v, i, b, l, func) { \
-       int loop_; \
-       func("%02x %02x %02x %02x %02x %02x %02x %02x", \
-               t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
-       if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
-               func(" >>> "); \
-       else \
-               func(" <<< "); \
-       for (loop_ = 0; loop_ < l; loop_++) \
-               func("%02x ", b[loop_]); \
-       func("\n");\
-}
+#include "dvb_usb.h"
 
 #define EC168_USB_TIMEOUT 1000
+#define EC168_FIRMWARE "dvb-usb-ec168.fw"
 
 struct ec168_req {
        u8  cmd;       /* [1] */
similarity index 54%
rename from drivers/media/dvb/dvb-usb/gl861.c
rename to drivers/media/usb/dvb-usb-v2/gl861.c
index c1f5582e1cdfd3923d7fd816c22d0ce252d3c17e..b1b09c547861c26c3672a7290a45486ce52c9e30 100644 (file)
 #include "zl10353.h"
 #include "qt1010.h"
 
-/* debug */
-static int dvb_usb_gl861_debug;
-module_param_named(debug, dvb_usb_gl861_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=rc (or-able))."
-       DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
@@ -43,7 +38,8 @@ static int gl861_i2c_msg(struct dvb_usb_device *d, u8 addr,
                value = value + wbuf[1];
                break;
        default:
-               warn("wlen = %x, aborting.", wlen);
+               dev_err(&d->udev->dev, "%s: wlen=%d, aborting\n",
+                               KBUILD_MODNAME, wlen);
                return -EINVAL;
        }
 
@@ -103,9 +99,9 @@ static struct zl10353_config gl861_zl10353_config = {
 static int gl861_frontend_attach(struct dvb_usb_adapter *adap)
 {
 
-       adap->fe_adap[0].fe = dvb_attach(zl10353_attach, &gl861_zl10353_config,
-               &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL)
+       adap->fe[0] = dvb_attach(zl10353_attach, &gl861_zl10353_config,
+               &adap_to_d(adap)->i2c_adap);
+       if (adap->fe[0] == NULL)
                return -EIO;
 
        return 0;
@@ -118,98 +114,62 @@ static struct qt1010_config gl861_qt1010_config = {
 static int gl861_tuner_attach(struct dvb_usb_adapter *adap)
 {
        return dvb_attach(qt1010_attach,
-                         adap->fe_adap[0].fe, &adap->dev->i2c_adap,
+                         adap->fe[0], &adap_to_d(adap)->i2c_adap,
                          &gl861_qt1010_config) == NULL ? -ENODEV : 0;
 }
 
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties gl861_properties;
-
-static int gl861_probe(struct usb_interface *intf,
-                      const struct usb_device_id *id)
+static int gl861_init(struct dvb_usb_device *d)
 {
-       struct dvb_usb_device *d;
-       struct usb_host_interface *alt;
-       int ret;
-
-       if (intf->num_altsetting < 2)
-               return -ENODEV;
-
-       ret = dvb_usb_device_init(intf, &gl861_properties, THIS_MODULE, &d,
-                                 adapter_nr);
-       if (ret == 0) {
-               alt = usb_altnum_to_altsetting(intf, 0);
-
-               if (alt == NULL) {
-                       deb_rc("not alt found!\n");
-                       return -ENODEV;
-               }
-
-               ret = usb_set_interface(d->udev, alt->desc.bInterfaceNumber,
-                                       alt->desc.bAlternateSetting);
-       }
-
-       return ret;
+       /*
+        * There is 2 interfaces. Interface 0 is for TV and interface 1 is
+        * for HID remote controller. Interface 0 has 2 alternate settings.
+        * For some reason we need to set interface explicitly, defaulted
+        * as alternate setting 1?
+        */
+       return usb_set_interface(d->udev, 0, 0);
 }
 
-static struct usb_device_id gl861_table [] = {
-               { USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801) },
-               { USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU) },
-               { }             /* Terminating entry */
-};
-MODULE_DEVICE_TABLE(usb, gl861_table);
-
-static struct dvb_usb_device_properties gl861_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-       .usb_ctrl = DEVICE_SPECIFIC,
+/* DVB USB Driver stuff */
+static struct dvb_usb_device_properties gl861_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
 
-       .size_of_priv     = 0,
+       .i2c_algo = &gl861_i2c_algo,
+       .frontend_attach = gl861_frontend_attach,
+       .tuner_attach = gl861_tuner_attach,
+       .init = gl861_init,
 
        .num_adapters = 1,
-       .adapter = {{
-               .num_frontends = 1,
-               .fe = {{
-
-               .frontend_attach  = gl861_frontend_attach,
-               .tuner_attach     = gl861_tuner_attach,
-
-               .stream = {
-                       .type = USB_BULK,
-                       .count = 7,
-                       .endpoint = 0x81,
-                       .u = {
-                               .bulk = {
-                                       .buffersize = 512,
-                               }
-                       }
-               },
-               }},
-       } },
-       .i2c_algo         = &gl861_i2c_algo,
-
-       .num_device_descs = 2,
-       .devices = {
+       .adapter = {
                {
-                       .name = "MSI Mega Sky 55801 DVB-T USB2.0",
-                       .cold_ids = { NULL },
-                       .warm_ids = { &gl861_table[0], NULL },
-               },
-               {
-                       .name = "A-LINK DTU DVB-T USB2.0",
-                       .cold_ids = { NULL },
-                       .warm_ids = { &gl861_table[1], NULL },
-               },
+                       .stream = DVB_USB_STREAM_BULK(0x81, 7, 512),
+               }
        }
 };
 
-static struct usb_driver gl861_driver = {
-       .name           = "dvb_usb_gl861",
-       .probe          = gl861_probe,
-       .disconnect     = dvb_usb_device_exit,
-       .id_table       = gl861_table,
+static const struct usb_device_id gl861_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_MSI, USB_PID_MSI_MEGASKY580_55801,
+               &gl861_props, "MSI Mega Sky 55801 DVB-T USB2.0", NULL) },
+       { DVB_USB_DEVICE(USB_VID_ALINK, USB_VID_ALINK_DTU,
+               &gl861_props, "A-LINK DTU DVB-T USB2.0", NULL) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, gl861_id_table);
+
+static struct usb_driver gl861_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = gl861_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
-module_usb_driver(gl861_driver);
+module_usb_driver(gl861_usb_driver);
 
 MODULE_AUTHOR("Carl Lundqvist <comabug@gmail.com>");
 MODULE_DESCRIPTION("Driver MSI Mega Sky 580 DVB-T USB2.0 / GL861");
similarity index 59%
rename from drivers/media/dvb/dvb-usb/gl861.h
rename to drivers/media/usb/dvb-usb-v2/gl861.h
index c54855e2c233f8ae007e30a31f2f57ecf5c6e32c..b0b80d87bb7e36f98a6e413d6f7c0e6cc63b77e0 100644 (file)
@@ -1,10 +1,7 @@
 #ifndef _DVB_USB_GL861_H_
 #define _DVB_USB_GL861_H_
 
-#define DVB_USB_LOG_PREFIX "gl861"
-#include "dvb-usb.h"
-
-#define deb_rc(args...)   dprintk(dvb_usb_gl861_debug, 0x01, args)
+#include "dvb_usb.h"
 
 #define GL861_WRITE            0x40
 #define GL861_READ             0xc0
diff --git a/drivers/media/usb/dvb-usb-v2/it913x.c b/drivers/media/usb/dvb-usb-v2/it913x.c
new file mode 100644 (file)
index 0000000..695f910
--- /dev/null
@@ -0,0 +1,799 @@
+/*
+ * DVB USB compliant linux driver for ITE IT9135 and IT9137
+ *
+ * Copyright (C) 2011 Malcolm Priestley (tvboxspy@gmail.com)
+ * IT9135 (C) ITE Tech Inc.
+ * IT9137 (C) ITE Tech Inc.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ * see Documentation/dvb/it9137.txt for firmware information
+ *
+ */
+#define DVB_USB_LOG_PREFIX "it913x"
+
+#include <linux/usb.h>
+#include <linux/usb/input.h>
+#include <media/rc-core.h>
+
+#include "dvb_usb.h"
+#include "it913x-fe.h"
+
+/* debug */
+static int dvb_usb_it913x_debug;
+#define it_debug(var, level, args...) \
+       do { if ((var & level)) pr_debug(DVB_USB_LOG_PREFIX": " args); \
+} while (0)
+#define deb_info(level, args...) it_debug(dvb_usb_it913x_debug, level, args)
+#define info(args...) pr_info(DVB_USB_LOG_PREFIX": " args)
+
+module_param_named(debug, dvb_usb_it913x_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
+
+static int dvb_usb_it913x_firmware;
+module_param_named(firmware, dvb_usb_it913x_firmware, int, 0644);
+MODULE_PARM_DESC(firmware, "set firmware 0=auto"\
+       "1=IT9137 2=IT9135 V1 3=IT9135 V2");
+#define FW_IT9137 "dvb-usb-it9137-01.fw"
+#define FW_IT9135_V1 "dvb-usb-it9135-01.fw"
+#define FW_IT9135_V2 "dvb-usb-it9135-02.fw"
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+struct it913x_state {
+       struct ite_config it913x_config;
+       u8 pid_filter_onoff;
+       bool proprietary_ir;
+       int cmd_counter;
+};
+
+static u16 check_sum(u8 *p, u8 len)
+{
+       u16 sum = 0;
+       u8 i = 1;
+       while (i < len)
+               sum += (i++ & 1) ? (*p++) << 8 : *p++;
+       return ~sum;
+}
+
+static int it913x_io(struct dvb_usb_device *d, u8 mode, u8 pro,
+                       u8 cmd, u32 reg, u8 addr, u8 *data, u8 len)
+{
+       struct it913x_state *st = d->priv;
+       int ret = 0, i, buf_size = 1;
+       u8 *buff;
+       u8 rlen;
+       u16 chk_sum;
+
+       buff = kzalloc(256, GFP_KERNEL);
+       if (!buff) {
+               info("USB Buffer Failed");
+               return -ENOMEM;
+       }
+
+       buff[buf_size++] = pro;
+       buff[buf_size++] = cmd;
+       buff[buf_size++] = st->cmd_counter;
+
+       switch (mode) {
+       case READ_LONG:
+       case WRITE_LONG:
+               buff[buf_size++] = len;
+               buff[buf_size++] = 2;
+               buff[buf_size++] = (reg >> 24);
+               buff[buf_size++] = (reg >> 16) & 0xff;
+               buff[buf_size++] = (reg >> 8) & 0xff;
+               buff[buf_size++] = reg & 0xff;
+       break;
+       case READ_SHORT:
+               buff[buf_size++] = addr;
+               break;
+       case WRITE_SHORT:
+               buff[buf_size++] = len;
+               buff[buf_size++] = addr;
+               buff[buf_size++] = (reg >> 8) & 0xff;
+               buff[buf_size++] = reg & 0xff;
+       break;
+       case READ_DATA:
+       case WRITE_DATA:
+               break;
+       case WRITE_CMD:
+               mode = 7;
+               break;
+       default:
+               kfree(buff);
+               return -EINVAL;
+       }
+
+       if (mode & 1) {
+               for (i = 0; i < len ; i++)
+                       buff[buf_size++] = data[i];
+       }
+       chk_sum = check_sum(&buff[1], buf_size);
+
+       buff[buf_size++] = chk_sum >> 8;
+       buff[0] = buf_size;
+       buff[buf_size++] = (chk_sum & 0xff);
+
+       ret = dvb_usbv2_generic_rw(d, buff, buf_size, buff, (mode & 1) ?
+                       5 : len + 5);
+       if (ret < 0)
+               goto error;
+
+       rlen = (mode & 0x1) ? 0x1 : len;
+
+       if (mode & 1)
+               ret = buff[2];
+       else
+               memcpy(data, &buff[3], rlen);
+
+       st->cmd_counter++;
+
+error: kfree(buff);
+
+       return ret;
+}
+
+static int it913x_wr_reg(struct dvb_usb_device *d, u8 pro, u32 reg , u8 data)
+{
+       int ret;
+       u8 b[1];
+       b[0] = data;
+       ret = it913x_io(d, WRITE_LONG, pro,
+                       CMD_DEMOD_WRITE, reg, 0, b, sizeof(b));
+
+       return ret;
+}
+
+static int it913x_read_reg(struct dvb_usb_device *d, u32 reg)
+{
+       int ret;
+       u8 data[1];
+
+       ret = it913x_io(d, READ_LONG, DEV_0,
+                       CMD_DEMOD_READ, reg, 0, &data[0], sizeof(data));
+
+       return (ret < 0) ? ret : data[0];
+}
+
+static int it913x_query(struct dvb_usb_device *d, u8 pro)
+{
+       struct it913x_state *st = d->priv;
+       int ret, i;
+       u8 data[4];
+       u8 ver;
+
+       for (i = 0; i < 5; i++) {
+               ret = it913x_io(d, READ_LONG, pro, CMD_DEMOD_READ,
+                       0x1222, 0, &data[0], 3);
+               ver = data[0];
+               if (ver > 0 && ver < 3)
+                       break;
+               msleep(100);
+       }
+
+       if (ver < 1 || ver > 2) {
+               info("Failed to identify chip version applying 1");
+               st->it913x_config.chip_ver = 0x1;
+               st->it913x_config.chip_type = 0x9135;
+               return 0;
+       }
+
+       st->it913x_config.chip_ver = ver;
+       st->it913x_config.chip_type = (u16)(data[2] << 8) + data[1];
+
+       info("Chip Version=%02x Chip Type=%04x", st->it913x_config.chip_ver,
+               st->it913x_config.chip_type);
+
+       ret = it913x_io(d, READ_SHORT, pro,
+                       CMD_QUERYINFO, 0, 0x1, &data[0], 4);
+
+       st->it913x_config.firmware = (data[0] << 24) | (data[1] << 16) |
+                       (data[2] << 8) | data[3];
+
+       return ret;
+}
+
+static int it913x_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct it913x_state *st = adap_to_priv(adap);
+       int ret;
+       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+       mutex_lock(&d->i2c_mutex);
+
+       deb_info(1, "PID_C  (%02x)", onoff);
+
+       ret = it913x_wr_reg(d, pro, PID_EN, st->pid_filter_onoff);
+
+       mutex_unlock(&d->i2c_mutex);
+       return ret;
+}
+
+static int it913x_pid_filter(struct dvb_usb_adapter *adap,
+               int index, u16 pid, int onoff)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct it913x_state *st = adap_to_priv(adap);
+       int ret;
+       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+       mutex_lock(&d->i2c_mutex);
+
+       deb_info(1, "PID_F  (%02x)", onoff);
+
+       ret = it913x_wr_reg(d, pro, PID_LSB, (u8)(pid & 0xff));
+
+       ret |= it913x_wr_reg(d, pro, PID_MSB, (u8)(pid >> 8));
+
+       ret |= it913x_wr_reg(d, pro, PID_INX_EN, (u8)onoff);
+
+       ret |= it913x_wr_reg(d, pro, PID_INX, (u8)(index & 0x1f));
+
+       if (d->udev->speed == USB_SPEED_HIGH && pid == 0x2000) {
+                       ret |= it913x_wr_reg(d , pro, PID_EN, !onoff);
+                       st->pid_filter_onoff = !onoff;
+       } else
+               st->pid_filter_onoff =
+                       adap->pid_filtering;
+
+       mutex_unlock(&d->i2c_mutex);
+       return 0;
+}
+
+
+static int it913x_return_status(struct dvb_usb_device *d)
+{
+       struct it913x_state *st = d->priv;
+       int ret = it913x_query(d, DEV_0);
+       if (st->it913x_config.firmware > 0)
+               info("Firmware Version %d", st->it913x_config.firmware);
+
+       return ret;
+}
+
+static int it913x_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
+                                int num)
+{
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
+       static u8 data[256];
+       int ret;
+       u32 reg;
+       u8 pro;
+
+       mutex_lock(&d->i2c_mutex);
+
+       deb_info(2, "num of messages %d address %02x", num, msg[0].addr);
+
+       pro = (msg[0].addr & 0x2) ?  DEV_0_DMOD : 0x0;
+       pro |= (msg[0].addr & 0x20) ? DEV_1 : DEV_0;
+       memcpy(data, msg[0].buf, msg[0].len);
+       reg = (data[0] << 24) + (data[1] << 16) +
+                       (data[2] << 8) + data[3];
+       if (num == 2) {
+               ret = it913x_io(d, READ_LONG, pro,
+                       CMD_DEMOD_READ, reg, 0, data, msg[1].len);
+               memcpy(msg[1].buf, data, msg[1].len);
+       } else
+               ret = it913x_io(d, WRITE_LONG, pro, CMD_DEMOD_WRITE,
+                       reg, 0, &data[4], msg[0].len - 4);
+
+       mutex_unlock(&d->i2c_mutex);
+
+       return ret;
+}
+
+static u32 it913x_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+static struct i2c_algorithm it913x_i2c_algo = {
+       .master_xfer   = it913x_i2c_xfer,
+       .functionality = it913x_i2c_func,
+};
+
+/* Callbacks for DVB USB */
+#define IT913X_POLL 250
+static int it913x_rc_query(struct dvb_usb_device *d)
+{
+       u8 ibuf[4];
+       int ret;
+       u32 key;
+       /* Avoid conflict with frontends*/
+       mutex_lock(&d->i2c_mutex);
+
+       ret = it913x_io(d, READ_LONG, PRO_LINK, CMD_IR_GET,
+               0, 0, &ibuf[0], sizeof(ibuf));
+
+       if ((ibuf[2] + ibuf[3]) == 0xff) {
+               key = ibuf[2];
+               key += ibuf[0] << 16;
+               key += ibuf[1] << 8;
+               deb_info(1, "NEC Extended Key =%08x", key);
+               if (d->rc_dev != NULL)
+                       rc_keydown(d->rc_dev, key, 0);
+       }
+
+       mutex_unlock(&d->i2c_mutex);
+
+       return ret;
+}
+
+/* Firmware sets raw */
+static const char fw_it9135_v1[] = FW_IT9135_V1;
+static const char fw_it9135_v2[] = FW_IT9135_V2;
+static const char fw_it9137[] = FW_IT9137;
+
+static void ite_get_firmware_name(struct dvb_usb_device *d,
+       const char **name)
+{
+       struct it913x_state *st = d->priv;
+       int sw;
+       /* auto switch */
+       if (le16_to_cpu(d->udev->descriptor.idVendor) == USB_VID_KWORLD_2)
+               sw = IT9137_FW;
+       else if (st->it913x_config.chip_ver == 1)
+               sw = IT9135_V1_FW;
+       else
+               sw = IT9135_V2_FW;
+
+       /* force switch */
+       if (dvb_usb_it913x_firmware != IT9135_AUTO)
+               sw = dvb_usb_it913x_firmware;
+
+       switch (sw) {
+       case IT9135_V1_FW:
+               st->it913x_config.firmware_ver = 1;
+               st->it913x_config.adc_x2 = 1;
+               st->it913x_config.read_slevel = false;
+               *name = fw_it9135_v1;
+               break;
+       case IT9135_V2_FW:
+               st->it913x_config.firmware_ver = 1;
+               st->it913x_config.adc_x2 = 1;
+               st->it913x_config.read_slevel = false;
+               *name = fw_it9135_v2;
+               switch (st->it913x_config.tuner_id_0) {
+               case IT9135_61:
+               case IT9135_62:
+                       break;
+               default:
+                       info("Unknown tuner ID applying default 0x60");
+               case IT9135_60:
+                       st->it913x_config.tuner_id_0 = IT9135_60;
+               }
+               break;
+       case IT9137_FW:
+       default:
+               st->it913x_config.firmware_ver = 0;
+               st->it913x_config.adc_x2 = 0;
+               st->it913x_config.read_slevel = true;
+               *name = fw_it9137;
+       }
+
+       return;
+}
+
+#define TS_MPEG_PKT_SIZE       188
+#define EP_LOW                 21
+#define TS_BUFFER_SIZE_PID     (EP_LOW*TS_MPEG_PKT_SIZE)
+#define EP_HIGH                        348
+#define TS_BUFFER_SIZE_MAX     (EP_HIGH*TS_MPEG_PKT_SIZE)
+
+static int it913x_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
+               struct usb_data_stream_properties *stream)
+{
+       struct dvb_usb_adapter *adap = fe_to_adap(fe);
+       if (adap->pid_filtering)
+               stream->u.bulk.buffersize = TS_BUFFER_SIZE_PID;
+       else
+               stream->u.bulk.buffersize = TS_BUFFER_SIZE_MAX;
+
+       return 0;
+}
+
+static int it913x_select_config(struct dvb_usb_device *d)
+{
+       struct it913x_state *st = d->priv;
+       int ret, reg;
+
+       ret = it913x_return_status(d);
+       if (ret < 0)
+               return ret;
+
+       if (st->it913x_config.chip_ver == 0x02
+                       && st->it913x_config.chip_type == 0x9135)
+               reg = it913x_read_reg(d, 0x461d);
+       else
+               reg = it913x_read_reg(d, 0x461b);
+
+       if (reg < 0)
+               return reg;
+
+       if (reg == 0) {
+               st->it913x_config.dual_mode = 0;
+               st->it913x_config.tuner_id_0 = IT9135_38;
+               st->proprietary_ir = true;
+       } else {
+               /* TS mode */
+               reg =  it913x_read_reg(d, 0x49c5);
+               if (reg < 0)
+                       return reg;
+               st->it913x_config.dual_mode = reg;
+
+               /* IR mode type */
+               reg = it913x_read_reg(d, 0x49ac);
+               if (reg < 0)
+                       return reg;
+               if (reg == 5) {
+                       info("Remote propriety (raw) mode");
+                       st->proprietary_ir = true;
+               } else if (reg == 1) {
+                       info("Remote HID mode NOT SUPPORTED");
+                       st->proprietary_ir = false;
+               }
+
+               /* Tuner_id */
+               reg = it913x_read_reg(d, 0x49d0);
+               if (reg < 0)
+                       return reg;
+               st->it913x_config.tuner_id_0 = reg;
+       }
+
+       info("Dual mode=%x Tuner Type=%x", st->it913x_config.dual_mode,
+               st->it913x_config.tuner_id_0);
+
+       return ret;
+}
+
+static int it913x_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+       struct dvb_usb_adapter *adap = fe_to_adap(fe);
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct it913x_state *st = fe_to_priv(fe);
+       int ret = 0;
+       u8 pro = (adap->id == 0) ? DEV_0_DMOD : DEV_1_DMOD;
+
+       deb_info(1, "STM  (%02x)", onoff);
+
+       if (!onoff) {
+               mutex_lock(&d->i2c_mutex);
+
+               ret = it913x_wr_reg(d, pro, PID_RST, 0x1);
+
+               mutex_unlock(&d->i2c_mutex);
+               st->pid_filter_onoff =
+                       adap->pid_filtering;
+
+       }
+
+       return ret;
+}
+
+static int it913x_identify_state(struct dvb_usb_device *d, const char **name)
+{
+       struct it913x_state *st = d->priv;
+       int ret;
+       u8 reg;
+
+       /* Read and select config */
+       ret = it913x_select_config(d);
+       if (ret < 0)
+               return ret;
+
+       ite_get_firmware_name(d, name);
+
+       if (st->it913x_config.firmware > 0)
+               return WARM;
+
+       if (st->it913x_config.dual_mode) {
+               st->it913x_config.tuner_id_1 = it913x_read_reg(d, 0x49e0);
+               ret = it913x_wr_reg(d, DEV_0, GPIOH1_EN, 0x1);
+               ret |= it913x_wr_reg(d, DEV_0, GPIOH1_ON, 0x1);
+               ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x1);
+               msleep(50);
+               ret |= it913x_wr_reg(d, DEV_0, GPIOH1_O, 0x0);
+               msleep(50);
+               reg = it913x_read_reg(d, GPIOH1_O);
+               if (reg == 0) {
+                       ret |= it913x_wr_reg(d, DEV_0,  GPIOH1_O, 0x1);
+                       ret |= it913x_return_status(d);
+                       if (ret != 0)
+                               ret = it913x_wr_reg(d, DEV_0,
+                                       GPIOH1_O, 0x0);
+               }
+       }
+
+       reg = it913x_read_reg(d, IO_MUX_POWER_CLK);
+
+       if (st->it913x_config.dual_mode) {
+               ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, CHIP2_I2C_ADDR);
+               if (st->it913x_config.firmware_ver == 1)
+                       ret |= it913x_wr_reg(d, DEV_0,  0xcfff, 0x1);
+               else
+                       ret |= it913x_wr_reg(d, DEV_0,  CLK_O_EN, 0x1);
+       } else {
+               ret |= it913x_wr_reg(d, DEV_0, 0x4bfb, 0x0);
+               if (st->it913x_config.firmware_ver == 1)
+                       ret |= it913x_wr_reg(d, DEV_0,  0xcfff, 0x0);
+               else
+                       ret |= it913x_wr_reg(d, DEV_0,  CLK_O_EN, 0x0);
+       }
+
+       ret |= it913x_wr_reg(d, DEV_0,  I2C_CLK, I2C_CLK_100);
+
+       return (ret < 0) ? ret : COLD;
+}
+
+static int it913x_download_firmware(struct dvb_usb_device *d,
+                                       const struct firmware *fw)
+{
+       struct it913x_state *st = d->priv;
+       int ret = 0, i = 0, pos = 0;
+       u8 packet_size, min_pkt;
+       u8 *fw_data;
+
+       ret = it913x_wr_reg(d, DEV_0,  I2C_CLK, I2C_CLK_100);
+
+       info("FRM Starting Firmware Download");
+
+       /* Multi firmware loader */
+       /* This uses scatter write firmware headers */
+       /* The firmware must start with 03 XX 00 */
+       /* and be the extact firmware length */
+
+       if (st->it913x_config.chip_ver == 2)
+               min_pkt = 0x11;
+       else
+               min_pkt = 0x19;
+
+       while (i <= fw->size) {
+               if (((fw->data[i] == 0x3) && (fw->data[i + 2] == 0x0))
+                       || (i == fw->size)) {
+                       packet_size = i - pos;
+                       if ((packet_size > min_pkt) || (i == fw->size)) {
+                               fw_data = (u8 *)(fw->data + pos);
+                               pos += packet_size;
+                               if (packet_size > 0) {
+                                       ret = it913x_io(d, WRITE_DATA,
+                                               DEV_0, CMD_SCATTER_WRITE, 0,
+                                               0, fw_data, packet_size);
+                                       if (ret < 0)
+                                               break;
+                               }
+                               udelay(1000);
+                       }
+               }
+               i++;
+       }
+
+       if (ret < 0)
+               info("FRM Firmware Download Failed (%d)" , ret);
+       else
+               info("FRM Firmware Download Completed - Resetting Device");
+
+       msleep(30);
+
+       ret = it913x_io(d, WRITE_CMD, DEV_0, CMD_BOOT, 0, 0, NULL, 0);
+       if (ret < 0)
+               info("FRM Device not responding to reboot");
+
+       ret = it913x_return_status(d);
+       if (st->it913x_config.firmware == 0) {
+               info("FRM Failed to reboot device");
+               return -ENODEV;
+       }
+
+       msleep(30);
+
+       ret = it913x_wr_reg(d, DEV_0,  I2C_CLK, I2C_CLK_400);
+
+       msleep(30);
+
+       /* Tuner function */
+       if (st->it913x_config.dual_mode)
+               ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0xa0);
+       else
+               ret |= it913x_wr_reg(d, DEV_0_DMOD , 0xec4c, 0x68);
+
+       if ((st->it913x_config.chip_ver == 1) &&
+               (st->it913x_config.chip_type == 0x9135)) {
+               ret |= it913x_wr_reg(d, DEV_0,  PADODPU, 0x0);
+               ret |= it913x_wr_reg(d, DEV_0,  AGC_O_D, 0x0);
+               if (st->it913x_config.dual_mode) {
+                       ret |= it913x_wr_reg(d, DEV_1,  PADODPU, 0x0);
+                       ret |= it913x_wr_reg(d, DEV_1,  AGC_O_D, 0x0);
+               }
+       }
+
+       return (ret < 0) ? -ENODEV : 0;
+}
+
+static int it913x_name(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       const char *desc = d->name;
+       char *fe_name[] = {"_1", "_2", "_3", "_4"};
+       char *name = adap->fe[0]->ops.info.name;
+
+       strlcpy(name, desc, 128);
+       strlcat(name, fe_name[adap->id], 128);
+
+       return 0;
+}
+
+static int it913x_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct it913x_state *st = d->priv;
+       int ret = 0;
+       u8 adap_addr = I2C_BASE_ADDR + (adap->id << 5);
+       u16 ep_size = adap->stream.buf_size / 4;
+       u8 pkt_size = 0x80;
+
+       if (d->udev->speed != USB_SPEED_HIGH)
+               pkt_size = 0x10;
+
+       st->it913x_config.adf = it913x_read_reg(d, IO_MUX_POWER_CLK);
+
+       adap->fe[0] = dvb_attach(it913x_fe_attach,
+               &d->i2c_adap, adap_addr, &st->it913x_config);
+
+       if (adap->id == 0 && adap->fe[0]) {
+               it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x1);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x1);
+               it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x0f);
+               it913x_wr_reg(d, DEV_0, EP0_TX_NAK, 0x1b);
+               it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x2f);
+               it913x_wr_reg(d, DEV_0, EP4_TX_LEN_LSB,
+                                       ep_size & 0xff);
+               it913x_wr_reg(d, DEV_0, EP4_TX_LEN_MSB, ep_size >> 8);
+               ret = it913x_wr_reg(d, DEV_0, EP4_MAX_PKT, pkt_size);
+       } else if (adap->id == 1 && adap->fe[0]) {
+               it913x_wr_reg(d, DEV_0, EP0_TX_EN, 0x6f);
+               it913x_wr_reg(d, DEV_0, EP5_TX_LEN_LSB,
+                                       ep_size & 0xff);
+               it913x_wr_reg(d, DEV_0, EP5_TX_LEN_MSB, ep_size >> 8);
+               it913x_wr_reg(d, DEV_0, EP5_MAX_PKT, pkt_size);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_EN, 0x1);
+               it913x_wr_reg(d, DEV_1_DMOD, MP2IF_SERIAL, 0x1);
+               it913x_wr_reg(d, DEV_1, TOP_HOSTB_SER_MODE, 0x1);
+               it913x_wr_reg(d, DEV_0_DMOD, TSIS_ENABLE, 0x1);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2_SW_RST, 0x0);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_SW_RST, 0x0);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2IF2_HALF_PSB, 0x0);
+               it913x_wr_reg(d, DEV_0_DMOD, MP2IF_STOP_EN, 0x1);
+               it913x_wr_reg(d, DEV_1_DMOD, MPEG_FULL_SPEED, 0x0);
+               ret = it913x_wr_reg(d, DEV_1_DMOD, MP2IF_STOP_EN, 0x0);
+       } else
+               return -ENODEV;
+
+       ret |= it913x_name(adap);
+
+       return ret;
+}
+
+/* DVB USB Driver */
+static int it913x_get_rc_config(struct dvb_usb_device *d, struct dvb_usb_rc *rc)
+{
+       struct it913x_state *st = d->priv;
+
+       if (st->proprietary_ir == false) {
+               rc->map_name = NULL;
+               return 0;
+       }
+
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query = it913x_rc_query;
+       rc->interval = 250;
+
+       return 0;
+}
+
+static int it913x_get_adapter_count(struct dvb_usb_device *d)
+{
+       struct it913x_state *st = d->priv;
+       if (st->it913x_config.dual_mode)
+               return 2;
+       return 1;
+}
+
+static struct dvb_usb_device_properties it913x_properties = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .bInterfaceNumber = 0,
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct it913x_state),
+
+       .identify_state = it913x_identify_state,
+       .i2c_algo = &it913x_i2c_algo,
+
+       .download_firmware = it913x_download_firmware,
+
+       .frontend_attach  = it913x_frontend_attach,
+       .get_rc_config = it913x_get_rc_config,
+       .get_stream_config = it913x_get_stream_config,
+       .get_adapter_count = it913x_get_adapter_count,
+       .streaming_ctrl   = it913x_streaming_ctrl,
+
+
+       .adapter = {
+               {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                       .pid_filter_count = 32,
+                       .pid_filter = it913x_pid_filter,
+                       .pid_filter_ctrl  = it913x_pid_filter_ctrl,
+                       .stream =
+                       DVB_USB_STREAM_BULK(0x84, 10, TS_BUFFER_SIZE_MAX),
+               },
+               {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                       .pid_filter_count = 32,
+                       .pid_filter = it913x_pid_filter,
+                       .pid_filter_ctrl  = it913x_pid_filter_ctrl,
+                       .stream =
+                       DVB_USB_STREAM_BULK(0x85, 10, TS_BUFFER_SIZE_MAX),
+               }
+       }
+};
+
+static const struct usb_device_id it913x_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_KWORLD_UB499_2T_T09,
+               &it913x_properties, "Kworld UB499-2T T09(IT9137)",
+                       RC_MAP_IT913X_V1) },
+       { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135,
+               &it913x_properties, "ITE 9135 Generic",
+                       RC_MAP_IT913X_V1) },
+       { DVB_USB_DEVICE(USB_VID_KWORLD_2, USB_PID_SVEON_STV22_IT9137,
+               &it913x_properties, "Sveon STV22 Dual DVB-T HDTV(IT9137)",
+                       RC_MAP_IT913X_V1) },
+       { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9005,
+               &it913x_properties, "ITE 9135(9005) Generic",
+                       RC_MAP_IT913X_V2) },
+       { DVB_USB_DEVICE(USB_VID_ITETECH, USB_PID_ITETECH_IT9135_9006,
+               &it913x_properties, "ITE 9135(9006) Generic",
+                       RC_MAP_IT913X_V1) },
+       {}              /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, it913x_id_table);
+
+static struct usb_driver it913x_driver = {
+       .name           = KBUILD_MODNAME,
+       .probe          = dvb_usbv2_probe,
+       .disconnect     = dvb_usbv2_disconnect,
+       .suspend        = dvb_usbv2_suspend,
+       .resume         = dvb_usbv2_resume,
+       .id_table       = it913x_id_table,
+};
+
+module_usb_driver(it913x_driver);
+
+MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
+MODULE_DESCRIPTION("it913x USB 2 Driver");
+MODULE_VERSION("1.32");
+MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(FW_IT9135_V1);
+MODULE_FIRMWARE(FW_IT9135_V2);
+MODULE_FIRMWARE(FW_IT9137);
+
similarity index 69%
rename from drivers/media/dvb/dvb-usb/lmedm04.c
rename to drivers/media/usb/dvb-usb-v2/lmedm04.c
index 25d1031460f8071deaa2bd0e9a5e14879824fb37..c41d9d9ec7b54df963ede5ad9deb6d9534e50620 100644 (file)
@@ -19,6 +19,8 @@
  *
  * MVB0194 (LME2510C+SHARP0194)
  *
+ * LME2510C + M88RS2000
+ *
  * For firmware see Documentation/dvb/lmedm04.txt
  *
  * I2C addresses:
  *     LME2510: SHARP:BS2F7HZ0194(MV0194) cannot cold reset and share system
  * with other tuners. After a cold reset streaming will not start.
  *
+ * M88RS2000 suffers from loss of lock.
  */
 #define DVB_USB_LOG_PREFIX "LME2510(C)"
 #include <linux/usb.h>
 #include <linux/usb/input.h>
 #include <media/rc-core.h>
 
-#include "dvb-usb.h"
+#include "dvb_usb.h"
 #include "lmedm04.h"
 #include "tda826x.h"
 #include "tda10086.h"
 #include "m88rs2000.h"
 
 
+#define LME2510_C_S7395        "dvb-usb-lme2510c-s7395.fw";
+#define LME2510_C_LG   "dvb-usb-lme2510c-lg.fw";
+#define LME2510_C_S0194        "dvb-usb-lme2510c-s0194.fw";
+#define LME2510_C_RS2000 "dvb-usb-lme2510c-rs2000.fw";
+#define LME2510_LG     "dvb-usb-lme2510-lg.fw";
+#define LME2510_S0194  "dvb-usb-lme2510-s0194.fw";
 
 /* debug */
 static int dvb_usb_lme2510_debug;
-#define l_dprintk(var, level, args...) do { \
+#define lme_debug(var, level, args...) do { \
        if ((var >= level)) \
-               printk(KERN_DEBUG DVB_USB_LOG_PREFIX ": " args); \
+               pr_debug(DVB_USB_LOG_PREFIX": " args); \
 } while (0)
-
-#define deb_info(level, args...) l_dprintk(dvb_usb_lme2510_debug, level, args)
+#define deb_info(level, args...) lme_debug(dvb_usb_lme2510_debug, level, args)
 #define debug_data_snipet(level, name, p) \
         deb_info(level, name" (%02x%02x%02x%02x%02x%02x%02x%02x)", \
                *p, *(p+1), *(p+2), *(p+3), *(p+4), \
                        *(p+5), *(p+6), *(p+7));
-
+#define info(args...) pr_info(DVB_USB_LOG_PREFIX": "args)
 
 module_param_named(debug, dvb_usb_lme2510_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able))."
-                       DVB_USB_DEBUG_STATUS);
+MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
 
 static int dvb_usb_lme2510_firmware;
 module_param_named(firmware, dvb_usb_lme2510_firmware, int, 0644);
@@ -136,7 +143,8 @@ struct lme2510_state {
        void *buffer;
        struct urb *lme_urb;
        void *usb_buffer;
-
+       int (*fe_set_voltage)(struct dvb_frontend *, fe_sec_voltage_t);
+       u8 dvb_usb_lme2510_firmware;
 };
 
 static int lme2510_bulk_write(struct usb_device *dev,
@@ -246,7 +254,7 @@ static int lme2510_enable_pid(struct dvb_usb_device *d, u8 index, u16 pid_out)
 static void lme2510_int_response(struct urb *lme_urb)
 {
        struct dvb_usb_adapter *adap = lme_urb->context;
-       struct lme2510_state *st = adap->dev->priv;
+       struct lme2510_state *st = adap_to_priv(adap);
        static u8 *ibuf, *rbuf;
        int i = 0, offset;
        u32 key;
@@ -283,8 +291,9 @@ static void lme2510_int_response(struct urb *lme_urb)
                                        ? (ibuf[3] ^ 0xff) << 8 : 0;
                                key += (ibuf[2] ^ 0xff) << 16;
                                deb_info(1, "INT Key =%08x", key);
-                               if (adap->dev->rc_dev != NULL)
-                                       rc_keydown(adap->dev->rc_dev, key, 0);
+                               if (adap_to_d(adap)->rc_dev != NULL)
+                                       rc_keydown(adap_to_d(adap)->rc_dev,
+                                               key, 0);
                        }
                        break;
                case 0xbb:
@@ -313,12 +322,12 @@ static void lme2510_int_response(struct urb *lme_urb)
                                }
                                break;
                        case TUNER_RS2000:
-                               if (ibuf[2] > 0)
+                               if (ibuf[1] == 0x3 &&  ibuf[6] == 0xff)
                                        st->signal_lock = 0xff;
                                else
-                                       st->signal_lock = 0xf0;
-                               st->signal_level = ibuf[4];
-                               st->signal_sn = ibuf[5];
+                                       st->signal_lock = 0x00;
+                               st->signal_level = ibuf[5];
+                               st->signal_sn = ibuf[4];
                                st->time_key = ibuf[7];
                        default:
                                break;
@@ -338,22 +347,23 @@ static void lme2510_int_response(struct urb *lme_urb)
 
 static int lme2510_int_read(struct dvb_usb_adapter *adap)
 {
-       struct lme2510_state *lme_int = adap->dev->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *lme_int = adap_to_priv(adap);
 
        lme_int->lme_urb = usb_alloc_urb(0, GFP_ATOMIC);
 
        if (lme_int->lme_urb == NULL)
                        return -ENOMEM;
 
-       lme_int->buffer = usb_alloc_coherent(adap->dev->udev, 128, GFP_ATOMIC,
+       lme_int->buffer = usb_alloc_coherent(d->udev, 128, GFP_ATOMIC,
                                        &lme_int->lme_urb->transfer_dma);
 
        if (lme_int->buffer == NULL)
                        return -ENOMEM;
 
        usb_fill_int_urb(lme_int->lme_urb,
-                               adap->dev->udev,
-                               usb_rcvintpipe(adap->dev->udev, 0xa),
+                               d->udev,
+                               usb_rcvintpipe(d->udev, 0xa),
                                lme_int->buffer,
                                128,
                                lme2510_int_response,
@@ -370,17 +380,18 @@ static int lme2510_int_read(struct dvb_usb_adapter *adap)
 
 static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 {
-       struct lme2510_state *st = adap->dev->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *st = adap_to_priv(adap);
        static u8 clear_pid_reg[] = LME_ALL_PIDS;
        static u8 rbuf[1];
        int ret = 0;
 
        deb_info(1, "PID Clearing Filter");
 
-       mutex_lock(&adap->dev->i2c_mutex);
+       mutex_lock(&d->i2c_mutex);
 
        if (!onoff) {
-               ret |= lme2510_usb_talk(adap->dev, clear_pid_reg,
+               ret |= lme2510_usb_talk(d, clear_pid_reg,
                        sizeof(clear_pid_reg), rbuf, sizeof(rbuf));
                st->pid_off = true;
        } else
@@ -388,7 +399,7 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 
        st->pid_size = 0;
 
-       mutex_unlock(&adap->dev->i2c_mutex);
+       mutex_unlock(&d->i2c_mutex);
 
        return 0;
 }
@@ -396,15 +407,16 @@ static int lme2510_pid_filter_ctrl(struct dvb_usb_adapter *adap, int onoff)
 static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
        int onoff)
 {
+       struct dvb_usb_device *d = adap_to_d(adap);
        int ret = 0;
 
        deb_info(3, "%s PID=%04x Index=%04x onoff=%02x", __func__,
                pid, index, onoff);
 
        if (onoff) {
-               mutex_lock(&adap->dev->i2c_mutex);
-               ret |= lme2510_enable_pid(adap->dev, index, pid);
-               mutex_unlock(&adap->dev->i2c_mutex);
+               mutex_lock(&d->i2c_mutex);
+               ret |= lme2510_enable_pid(d, index, pid);
+               mutex_unlock(&d->i2c_mutex);
        }
 
 
@@ -412,7 +424,7 @@ static int lme2510_pid_filter(struct dvb_usb_adapter *adap, int index, u16 pid,
 }
 
 
-static int lme2510_return_status(struct usb_device *dev)
+static int lme2510_return_status(struct dvb_usb_device *d)
 {
        int ret = 0;
        u8 *data;
@@ -421,7 +433,7 @@ static int lme2510_return_status(struct usb_device *dev)
        if (!data)
                return -ENOMEM;
 
-       ret |= usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
+       ret |= usb_control_msg(d->udev, usb_rcvctrlpipe(d->udev, 0),
                        0x06, 0x80, 0x0302, 0x00, data, 0x0006, 200);
        info("Firmware Status: %x (%x)", ret , data[2]);
 
@@ -613,10 +625,6 @@ static int lme2510_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
        if (gate == 0)
                gate = 5;
 
-       if (num > 2)
-               warn("more than 2 i2c messages"
-                       "at a time is not handled yet.  TODO.");
-
        for (i = 0; i < num; i++) {
                read_o = 1 & (msg[i].flags & I2C_M_RD);
                read = i+1 < num && (msg[i+1].flags & I2C_M_RD);
@@ -676,22 +684,11 @@ static struct i2c_algorithm lme2510_i2c_algo = {
        .functionality = lme2510_i2c_func,
 };
 
-/* Callbacks for DVB USB */
-static int lme2510_identify_state(struct usb_device *udev,
-               struct dvb_usb_device_properties *props,
-               struct dvb_usb_device_description **desc,
-               int *cold)
+static int lme2510_streaming_ctrl(struct dvb_frontend *fe, int onoff)
 {
-       if (pid_filter != 2)
-               props->adapter[0].fe[0].caps &=
-                       ~DVB_USB_ADAP_NEED_PID_FILTERING;
-       *cold = 0;
-       return 0;
-}
-
-static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
-{
-       struct lme2510_state *st = adap->dev->priv;
+       struct dvb_usb_adapter *adap = fe_to_adap(fe);
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *st = adap_to_priv(adap);
        static u8 clear_reg_3[] = LME_ALL_PIDS;
        static u8 rbuf[1];
        int ret = 0, rlen = sizeof(rbuf);
@@ -704,14 +701,14 @@ static int lme2510_streaming_ctrl(struct dvb_usb_adapter *adap, int onoff)
        else {
                deb_info(1, "STM Steam Off");
                /* mutex is here only to avoid collision with I2C */
-               mutex_lock(&adap->dev->i2c_mutex);
+               mutex_lock(&d->i2c_mutex);
 
-               ret = lme2510_usb_talk(adap->dev, clear_reg_3,
+               ret = lme2510_usb_talk(d, clear_reg_3,
                                sizeof(clear_reg_3), rbuf, rlen);
                st->stream_on = 0;
                st->i2c_talk_onoff = 1;
 
-               mutex_unlock(&adap->dev->i2c_mutex);
+               mutex_unlock(&d->i2c_mutex);
        }
 
        return (ret < 0) ? -ENODEV : 0;
@@ -725,7 +722,7 @@ static u8 check_sum(u8 *p, u8 len)
        return sum;
 }
 
-static int lme2510_download_firmware(struct usb_device *dev,
+static int lme2510_download_firmware(struct dvb_usb_device *d,
                                        const struct firmware *fw)
 {
        int ret = 0;
@@ -737,9 +734,10 @@ static int lme2510_download_firmware(struct usb_device *dev,
        packet_size = 0x31;
        len_in = 1;
 
-       data = kzalloc(512, GFP_KERNEL);
+       data = kzalloc(128, GFP_KERNEL);
        if (!data) {
-               info("FRM Could not start Firmware Download (Buffer allocation failed)");
+               info("FRM Could not start Firmware Download"\
+                       "(Buffer allocation failed)");
                return -ENOMEM;
        }
 
@@ -763,21 +761,15 @@ static int lme2510_download_firmware(struct usb_device *dev,
                        data[wlen-1] = check_sum(fw_data, dlen+1);
                        deb_info(1, "Data S=%02x:E=%02x CS= %02x", data[3],
                                data[dlen+2], data[dlen+3]);
-                       ret |= lme2510_bulk_write(dev, data,  wlen, 1);
-                       ret |= lme2510_bulk_read(dev, data, len_in , 1);
+                       lme2510_usb_talk(d, data, wlen, data, len_in);
                        ret |= (data[0] == 0x88) ? 0 : -1;
                }
        }
 
-       usb_control_msg(dev, usb_rcvctrlpipe(dev, 0),
-                       0x06, 0x80, 0x0200, 0x00, data, 0x0109, 1000);
-
-
        data[0] = 0x8a;
        len_in = 1;
        msleep(2000);
-       ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Resetting*/
-       ret |= lme2510_bulk_read(dev, data, len_in, 1);
+       lme2510_usb_talk(d, data, len_in, data, len_in);
        msleep(400);
 
        if (ret < 0)
@@ -786,44 +778,42 @@ static int lme2510_download_firmware(struct usb_device *dev,
                info("FRM Firmware Download Completed - Resetting Device");
 
        kfree(data);
-       return (ret < 0) ? -ENODEV : 0;
+       return RECONNECTS_USB;
 }
 
-static void lme_coldreset(struct usb_device *dev)
+static void lme_coldreset(struct dvb_usb_device *d)
 {
-       int ret = 0, len_in;
-       u8 data[512] = {0};
-
+       u8 data[1] = {0};
        data[0] = 0x0a;
-       len_in = 1;
        info("FRM Firmware Cold Reset");
-       ret |= lme2510_bulk_write(dev, data , len_in, 1); /*Cold Resetting*/
-       ret |= lme2510_bulk_read(dev, data, len_in, 1);
+
+       lme2510_usb_talk(d, data, sizeof(data), data, sizeof(data));
 
        return;
 }
 
-static int lme_firmware_switch(struct usb_device *udev, int cold)
+static const char fw_c_s7395[] = LME2510_C_S7395;
+static const char fw_c_lg[] = LME2510_C_LG;
+static const char fw_c_s0194[] = LME2510_C_S0194;
+static const char fw_c_rs2000[] = LME2510_C_RS2000;
+static const char fw_lg[] = LME2510_LG;
+static const char fw_s0194[] = LME2510_S0194;
+
+const char *lme_firmware_switch(struct dvb_usb_device *d, int cold)
 {
+       struct lme2510_state *st = d->priv;
+       struct usb_device *udev = d->udev;
        const struct firmware *fw = NULL;
-       const char fw_c_s7395[] = "dvb-usb-lme2510c-s7395.fw";
-       const char fw_c_lg[] = "dvb-usb-lme2510c-lg.fw";
-       const char fw_c_s0194[] = "dvb-usb-lme2510c-s0194.fw";
-       const char fw_c_rs2000[] = "dvb-usb-lme2510c-rs2000.fw";
-       const char fw_lg[] = "dvb-usb-lme2510-lg.fw";
-       const char fw_s0194[] = "dvb-usb-lme2510-s0194.fw";
        const char *fw_lme;
-       int ret = 0, cold_fw;
+       int ret = 0;
 
        cold = (cold > 0) ? (cold & 1) : 0;
 
-       cold_fw = !cold;
-
        switch (le16_to_cpu(udev->descriptor.idProduct)) {
        case 0x1122:
-               switch (dvb_usb_lme2510_firmware) {
+               switch (st->dvb_usb_lme2510_firmware) {
                default:
-                       dvb_usb_lme2510_firmware = TUNER_S0194;
+                       st->dvb_usb_lme2510_firmware = TUNER_S0194;
                case TUNER_S0194:
                        fw_lme = fw_s0194;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
@@ -831,23 +821,20 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
                                cold = 0;
                                break;
                        }
-                       dvb_usb_lme2510_firmware = TUNER_LG;
+                       st->dvb_usb_lme2510_firmware = TUNER_LG;
                case TUNER_LG:
                        fw_lme = fw_lg;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
                        if (ret == 0)
                                break;
-                       info("FRM No Firmware Found - please install");
-                       dvb_usb_lme2510_firmware = TUNER_DEFAULT;
-                       cold = 0;
-                       cold_fw = 0;
+                       st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
                        break;
                }
                break;
        case 0x1120:
-               switch (dvb_usb_lme2510_firmware) {
+               switch (st->dvb_usb_lme2510_firmware) {
                default:
-                       dvb_usb_lme2510_firmware = TUNER_S7395;
+                       st->dvb_usb_lme2510_firmware = TUNER_S7395;
                case TUNER_S7395:
                        fw_lme = fw_c_s7395;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
@@ -855,49 +842,41 @@ static int lme_firmware_switch(struct usb_device *udev, int cold)
                                cold = 0;
                                break;
                        }
-                       dvb_usb_lme2510_firmware = TUNER_LG;
+                       st->dvb_usb_lme2510_firmware = TUNER_LG;
                case TUNER_LG:
                        fw_lme = fw_c_lg;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
                        if (ret == 0)
                                break;
-                       dvb_usb_lme2510_firmware = TUNER_S0194;
+                       st->dvb_usb_lme2510_firmware = TUNER_S0194;
                case TUNER_S0194:
                        fw_lme = fw_c_s0194;
                        ret = request_firmware(&fw, fw_lme, &udev->dev);
                        if (ret == 0)
                                break;
-                       info("FRM No Firmware Found - please install");
-                       dvb_usb_lme2510_firmware = TUNER_DEFAULT;
+                       st->dvb_usb_lme2510_firmware = TUNER_DEFAULT;
                        cold = 0;
-                       cold_fw = 0;
                        break;
                }
                break;
        case 0x22f0:
                fw_lme = fw_c_rs2000;
-               ret = request_firmware(&fw, fw_lme, &udev->dev);
-               dvb_usb_lme2510_firmware = TUNER_RS2000;
+               st->dvb_usb_lme2510_firmware = TUNER_RS2000;
                break;
        default:
                fw_lme = fw_c_s7395;
        }
 
-
-       if (cold_fw) {
-               info("FRM Loading %s file", fw_lme);
-               ret = lme2510_download_firmware(udev, fw);
-       }
-
        release_firmware(fw);
 
        if (cold) {
+               dvb_usb_lme2510_firmware = st->dvb_usb_lme2510_firmware;
                info("FRM Changing to %s firmware", fw_lme);
-               lme_coldreset(udev);
-               return -ENODEV;
+               lme_coldreset(d);
+               return NULL;
        }
 
-       return ret;
+       return fw_lme;
 }
 
 static int lme2510_kill_urb(struct usb_data_stream *stream)
@@ -949,8 +928,8 @@ static struct stv0299_config sharp_z0194_config = {
 static int dm04_rs2000_set_ts_param(struct dvb_frontend *fe,
        int caller)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct dvb_usb_device *d = adap->dev;
+       struct dvb_usb_adapter *adap = fe_to_adap(fe);
+       struct dvb_usb_device *d = adap_to_d(adap);
        struct lme2510_state *st = d->priv;
 
        mutex_lock(&d->i2c_mutex);
@@ -972,29 +951,35 @@ static struct m88rs2000_config m88rs2000_config = {
 static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
                                        fe_sec_voltage_t voltage)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       static u8 voltage_low[] = LME_VOLTAGE_L;
+       struct dvb_usb_device *d = fe_to_d(fe);
+       struct lme2510_state *st = fe_to_priv(fe);
+       static u8 voltage_low[] = LME_VOLTAGE_L;
        static u8 voltage_high[] = LME_VOLTAGE_H;
        static u8 rbuf[1];
        int ret = 0, len = 3, rlen = 1;
 
-       mutex_lock(&adap->dev->i2c_mutex);
+       mutex_lock(&d->i2c_mutex);
 
        switch (voltage) {
        case SEC_VOLTAGE_18:
-               ret |= lme2510_usb_talk(adap->dev,
+               ret |= lme2510_usb_talk(d,
                        voltage_high, len, rbuf, rlen);
                break;
 
        case SEC_VOLTAGE_OFF:
        case SEC_VOLTAGE_13:
        default:
-               ret |= lme2510_usb_talk(adap->dev,
+               ret |= lme2510_usb_talk(d,
                                voltage_low, len, rbuf, rlen);
                break;
        }
 
-       mutex_unlock(&adap->dev->i2c_mutex);
+       mutex_unlock(&d->i2c_mutex);
+
+       if (st->tuner_config == TUNER_RS2000)
+               if (st->fe_set_voltage)
+                       st->fe_set_voltage(fe, voltage);
+
 
        return (ret < 0) ? -ENODEV : 0;
 }
@@ -1002,29 +987,44 @@ static int dm04_lme2510_set_voltage(struct dvb_frontend *fe,
 static int dm04_rs2000_read_signal_strength(struct dvb_frontend *fe,
        u16 *strength)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct lme2510_state *st = adap->dev->priv;
+       struct lme2510_state *st = fe_to_priv(fe);
+
+       *strength = (u16)((u32)st->signal_level * 0xffff / 0xff);
 
-       *strength = (u16)((u32)st->signal_level * 0xffff / 0x7f);
        return 0;
 }
 
 static int dm04_rs2000_read_snr(struct dvb_frontend *fe, u16 *snr)
 {
-       struct dvb_usb_adapter *adap = fe->dvb->priv;
-       struct lme2510_state *st = adap->dev->priv;
+       struct lme2510_state *st = fe_to_priv(fe);
+
+       *snr = (u16)((u32)st->signal_sn * 0xffff / 0x7f);
+
+       return 0;
+}
+
+static int dm04_read_ber(struct dvb_frontend *fe, u32 *ber)
+{
+       *ber = 0;
+
+       return 0;
+}
+
+static int dm04_read_ucblocks(struct dvb_frontend *fe, u32 *ucblocks)
+{
+       *ucblocks = 0;
 
-       *snr = (u16)((u32)st->signal_sn * 0xffff / 0xff);
        return 0;
 }
 
 static int lme_name(struct dvb_usb_adapter *adap)
 {
-       struct lme2510_state *st = adap->dev->priv;
-       const char *desc = adap->dev->desc->name;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *st = adap_to_priv(adap);
+       const char *desc = d->name;
        char *fe_name[] = {"", " LG TDQY-P001F", " SHARP:BS2F7HZ7395",
                                " SHARP:BS2F7HZ0194", " RS2000"};
-       char *name = adap->fe_adap[0].fe->ops.info.name;
+       char *name = adap->fe[0]->ops.info.name;
 
        strlcpy(name, desc, 128);
        strlcat(name, fe_name[st->tuner_config], 128);
@@ -1034,120 +1034,128 @@ static int lme_name(struct dvb_usb_adapter *adap)
 
 static int dm04_lme2510_frontend_attach(struct dvb_usb_adapter *adap)
 {
-       struct lme2510_state *st = adap->dev->priv;
-
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *st = d->priv;
        int ret = 0;
 
        st->i2c_talk_onoff = 1;
-       switch (le16_to_cpu(adap->dev->udev->descriptor.idProduct)) {
+       switch (le16_to_cpu(d->udev->descriptor.idProduct)) {
        case 0x1122:
        case 0x1120:
                st->i2c_gate = 4;
-               adap->fe_adap[0].fe = dvb_attach(tda10086_attach,
-                       &tda10086_config, &adap->dev->i2c_adap);
-               if (adap->fe_adap[0].fe) {
+               adap->fe[0] = dvb_attach(tda10086_attach,
+                       &tda10086_config, &d->i2c_adap);
+               if (adap->fe[0]) {
                        info("TUN Found Frontend TDA10086");
                        st->i2c_tuner_gate_w = 4;
                        st->i2c_tuner_gate_r = 4;
                        st->i2c_tuner_addr = 0xc0;
                        st->tuner_config = TUNER_LG;
-                       if (dvb_usb_lme2510_firmware != TUNER_LG) {
-                               dvb_usb_lme2510_firmware = TUNER_LG;
-                               ret = lme_firmware_switch(adap->dev->udev, 1);
+                       if (st->dvb_usb_lme2510_firmware != TUNER_LG) {
+                               st->dvb_usb_lme2510_firmware = TUNER_LG;
+                               ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
                        }
                        break;
                }
 
                st->i2c_gate = 4;
-               adap->fe_adap[0].fe = dvb_attach(stv0299_attach,
-                               &sharp_z0194_config, &adap->dev->i2c_adap);
-               if (adap->fe_adap[0].fe) {
+               adap->fe[0] = dvb_attach(stv0299_attach,
+                               &sharp_z0194_config, &d->i2c_adap);
+               if (adap->fe[0]) {
                        info("FE Found Stv0299");
                        st->i2c_tuner_gate_w = 4;
                        st->i2c_tuner_gate_r = 5;
                        st->i2c_tuner_addr = 0xc0;
                        st->tuner_config = TUNER_S0194;
-                       if (dvb_usb_lme2510_firmware != TUNER_S0194) {
-                               dvb_usb_lme2510_firmware = TUNER_S0194;
-                               ret = lme_firmware_switch(adap->dev->udev, 1);
+                       if (st->dvb_usb_lme2510_firmware != TUNER_S0194) {
+                               st->dvb_usb_lme2510_firmware = TUNER_S0194;
+                               ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
                        }
                        break;
                }
 
                st->i2c_gate = 5;
-               adap->fe_adap[0].fe = dvb_attach(stv0288_attach, &lme_config,
-                       &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(stv0288_attach, &lme_config,
+                       &d->i2c_adap);
 
-               if (adap->fe_adap[0].fe) {
+               if (adap->fe[0]) {
                        info("FE Found Stv0288");
                        st->i2c_tuner_gate_w = 4;
                        st->i2c_tuner_gate_r = 5;
                        st->i2c_tuner_addr = 0xc0;
                        st->tuner_config = TUNER_S7395;
-                       if (dvb_usb_lme2510_firmware != TUNER_S7395) {
-                               dvb_usb_lme2510_firmware = TUNER_S7395;
-                               ret = lme_firmware_switch(adap->dev->udev, 1);
+                       if (st->dvb_usb_lme2510_firmware != TUNER_S7395) {
+                               st->dvb_usb_lme2510_firmware = TUNER_S7395;
+                               ret = lme_firmware_switch(d, 1) ? 0 : -ENODEV;
                        }
                        break;
                }
        case 0x22f0:
                st->i2c_gate = 5;
-               adap->fe_adap[0].fe = dvb_attach(m88rs2000_attach,
-                       &m88rs2000_config, &adap->dev->i2c_adap);
+               adap->fe[0] = dvb_attach(m88rs2000_attach,
+                       &m88rs2000_config, &d->i2c_adap);
 
-               if (adap->fe_adap[0].fe) {
+               if (adap->fe[0]) {
                        info("FE Found M88RS2000");
                        st->i2c_tuner_gate_w = 5;
                        st->i2c_tuner_gate_r = 5;
                        st->i2c_tuner_addr = 0xc0;
                        st->tuner_config = TUNER_RS2000;
-                       adap->fe_adap[0].fe->ops.read_signal_strength =
+                       st->fe_set_voltage =
+                               adap->fe[0]->ops.set_voltage;
+
+                       adap->fe[0]->ops.read_signal_strength =
                                dm04_rs2000_read_signal_strength;
-                       adap->fe_adap[0].fe->ops.read_snr =
+                       adap->fe[0]->ops.read_snr =
                                dm04_rs2000_read_snr;
+                       adap->fe[0]->ops.read_ber =
+                               dm04_read_ber;
+                       adap->fe[0]->ops.read_ucblocks =
+                               dm04_read_ucblocks;
                }
                break;
        }
 
-       if (adap->fe_adap[0].fe == NULL) {
-                       info("DM04/QQBOX Not Powered up or not Supported");
-                       return -ENODEV;
+       if (adap->fe[0] == NULL) {
+               info("DM04/QQBOX Not Powered up or not Supported");
+               return -ENODEV;
        }
 
        if (ret) {
-               if (adap->fe_adap[0].fe) {
-                       dvb_frontend_detach(adap->fe_adap[0].fe);
-                       adap->fe_adap[0].fe = NULL;
+               if (adap->fe[0]) {
+                       dvb_frontend_detach(adap->fe[0]);
+                       adap->fe[0] = NULL;
                }
-               adap->dev->props.rc.core.rc_codes = NULL;
+               d->rc_map = NULL;
                return -ENODEV;
        }
 
-       adap->fe_adap[0].fe->ops.set_voltage = dm04_lme2510_set_voltage;
+       adap->fe[0]->ops.set_voltage = dm04_lme2510_set_voltage;
        ret = lme_name(adap);
        return ret;
 }
 
 static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
 {
-       struct lme2510_state *st = adap->dev->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct lme2510_state *st = adap_to_priv(adap);
        char *tun_msg[] = {"", "TDA8263", "IX2505V", "DVB_PLL_OPERA", "RS2000"};
        int ret = 0;
 
        switch (st->tuner_config) {
        case TUNER_LG:
-               if (dvb_attach(tda826x_attach, adap->fe_adap[0].fe, 0xc0,
-                       &adap->dev->i2c_adap, 1))
+               if (dvb_attach(tda826x_attach, adap->fe[0], 0xc0,
+                       &d->i2c_adap, 1))
                        ret = st->tuner_config;
                break;
        case TUNER_S7395:
-               if (dvb_attach(ix2505v_attach , adap->fe_adap[0].fe, &lme_tuner,
-                       &adap->dev->i2c_adap))
+               if (dvb_attach(ix2505v_attach , adap->fe[0], &lme_tuner,
+                       &d->i2c_adap))
                        ret = st->tuner_config;
                break;
        case TUNER_S0194:
-               if (dvb_attach(dvb_pll_attach , adap->fe_adap[0].fe, 0xc0,
-                       &adap->dev->i2c_adap, DVB_PLL_OPERA1))
+               if (dvb_attach(dvb_pll_attach , adap->fe[0], 0xc0,
+                       &d->i2c_adap, DVB_PLL_OPERA1))
                        ret = st->tuner_config;
                break;
        case TUNER_RS2000:
@@ -1161,7 +1169,7 @@ static int dm04_lme2510_tuner(struct dvb_usb_adapter *adap)
                info("TUN Found %s tuner", tun_msg[ret]);
        else {
                info("TUN No tuner found --- resetting device");
-               lme_coldreset(adap->dev->udev);
+               lme_coldreset(d);
                return -ENODEV;
        }
 
@@ -1197,158 +1205,57 @@ static int lme2510_powerup(struct dvb_usb_device *d, int onoff)
        return ret;
 }
 
-/* DVB USB Driver stuff */
-static struct dvb_usb_device_properties lme2510_properties;
-static struct dvb_usb_device_properties lme2510c_properties;
-
-static int lme2510_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
+static int lme2510_get_adapter_count(struct dvb_usb_device *d)
 {
-       struct usb_device *udev = interface_to_usbdev(intf);
+       return 1;
+}
 
-       usb_reset_configuration(udev);
+static int lme2510_identify_state(struct dvb_usb_device *d, const char **name)
+{
+       struct lme2510_state *st = d->priv;
 
-       usb_set_interface(udev, intf->cur_altsetting->desc.bInterfaceNumber, 1);
+       usb_reset_configuration(d->udev);
 
-       if (udev->speed != USB_SPEED_HIGH) {
-               usb_reset_device(udev);
-               info("DEV Failed to connect in HIGH SPEED mode");
-               return -ENODEV;
-       }
+       usb_set_interface(d->udev,
+               d->intf->cur_altsetting->desc.bInterfaceNumber, 1);
 
-       if (lme2510_return_status(udev) == 0x44) {
-               lme_firmware_switch(udev, 0);
-               return -ENODEV;
-       }
+       st->dvb_usb_lme2510_firmware = dvb_usb_lme2510_firmware;
 
-       if (0 == dvb_usb_device_init(intf, &lme2510_properties,
-                                    THIS_MODULE, NULL, adapter_nr)) {
-               info("DEV registering device driver");
-               return 0;
-       }
-       if (0 == dvb_usb_device_init(intf, &lme2510c_properties,
-                                    THIS_MODULE, NULL, adapter_nr)) {
-               info("DEV registering device driver");
-               return 0;
+       if (lme2510_return_status(d) == 0x44) {
+               *name = lme_firmware_switch(d, 0);
+               return COLD;
        }
 
-       info("DEV lme2510 Error");
-       return -ENODEV;
-
+       return 0;
 }
 
-static struct usb_device_id lme2510_table[] = {
-       { USB_DEVICE(0x3344, 0x1122) },  /* LME2510 */
-       { USB_DEVICE(0x3344, 0x1120) },  /* LME2510C */
-       { USB_DEVICE(0x3344, 0x22f0) },  /* LME2510C RS2000 */
-       {}              /* Terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, lme2510_table);
-
-static struct dvb_usb_device_properties lme2510_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-       .size_of_priv = sizeof(struct lme2510_state),
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
-                               DVB_USB_ADAP_NEED_PID_FILTERING|
-                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-                       .streaming_ctrl   = lme2510_streaming_ctrl,
-                       .pid_filter_count = 32,
-                       .pid_filter = lme2510_pid_filter,
-                       .pid_filter_ctrl  = lme2510_pid_filter_ctrl,
-                       .frontend_attach  = dm04_lme2510_frontend_attach,
-                       .tuner_attach = dm04_lme2510_tuner,
-                       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 10,
-                               .endpoint = 0x06,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = 4096,
-
-                                       }
-                               }
-                       }
-               }},
-               }
-       },
-       .rc.core = {
-               .protocol       = RC_TYPE_NEC,
-               .module_name    = "LME2510 Remote Control",
-               .allowed_protos = RC_TYPE_NEC,
-               .rc_codes       = RC_MAP_LME2510,
-       },
-       .power_ctrl       = lme2510_powerup,
-       .identify_state   = lme2510_identify_state,
-       .i2c_algo         = &lme2510_i2c_algo,
-       .generic_bulk_ctrl_endpoint = 0,
-       .num_device_descs = 1,
-       .devices = {
-               {   "DM04_LME2510_DVB-S",
-                       { &lme2510_table[0], NULL },
-                       },
+static int lme2510_get_stream_config(struct dvb_frontend *fe, u8 *ts_type,
+               struct usb_data_stream_properties *stream)
+{
+       struct dvb_usb_adapter *adap = fe_to_adap(fe);
+       struct dvb_usb_device *d = adap_to_d(adap);
 
+       if (adap == NULL)
+               return 0;
+       /* Turn PID filter on the fly by module option */
+       if (pid_filter == 2) {
+               adap->pid_filtering  = 1;
+               adap->max_feed_count = 15;
        }
-};
 
-static struct dvb_usb_device_properties lme2510c_properties = {
-       .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-       .size_of_priv = sizeof(struct lme2510_state),
-       .num_adapters = 1,
-       .adapter = {
-               {
-               .num_frontends = 1,
-               .fe = {{
-                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
-                               DVB_USB_ADAP_NEED_PID_FILTERING|
-                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
-                       .streaming_ctrl   = lme2510_streaming_ctrl,
-                       .pid_filter_count = 32,
-                       .pid_filter = lme2510_pid_filter,
-                       .pid_filter_ctrl  = lme2510_pid_filter_ctrl,
-                       .frontend_attach  = dm04_lme2510_frontend_attach,
-                       .tuner_attach = dm04_lme2510_tuner,
-                       /* parameter for the MPEG2-data transfer */
-                       .stream = {
-                               .type = USB_BULK,
-                               .count = 10,
-                               .endpoint = 0x8,
-                               .u = {
-                                       .bulk = {
-                                               .buffersize = 4096,
+       if (!(le16_to_cpu(d->udev->descriptor.idProduct)
+               == 0x1122))
+               stream->endpoint = 0x8;
 
-                                       }
-                               }
-                       }
-               }},
-               }
-       },
-       .rc.core = {
-               .protocol       = RC_TYPE_NEC,
-               .module_name    = "LME2510 Remote Control",
-               .allowed_protos = RC_TYPE_NEC,
-               .rc_codes       = RC_MAP_LME2510,
-       },
-       .power_ctrl       = lme2510_powerup,
-       .identify_state   = lme2510_identify_state,
-       .i2c_algo         = &lme2510_i2c_algo,
-       .generic_bulk_ctrl_endpoint = 0,
-       .num_device_descs = 2,
-       .devices = {
-               {   "DM04_LME2510C_DVB-S",
-                       { &lme2510_table[1], NULL },
-                       },
-               {   "DM04_LME2510C_DVB-S RS2000",
-                       { &lme2510_table[2], NULL },
-                       },
-       }
-};
+       return 0;
+}
+
+static int lme2510_get_rc_config(struct dvb_usb_device *d,
+       struct dvb_usb_rc *rc)
+{
+       rc->allowed_protos = RC_TYPE_NEC;
+       return 0;
+}
 
 static void *lme2510_exit_int(struct dvb_usb_device *d)
 {
@@ -1357,8 +1264,7 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
        void *buffer = NULL;
 
        if (adap != NULL) {
-               lme2510_kill_urb(&adap->fe_adap[0].stream);
-               adap->feedcount = 0;
+               lme2510_kill_urb(&adap->stream);
        }
 
        if (st->usb_buffer != NULL) {
@@ -1379,29 +1285,85 @@ static void *lme2510_exit_int(struct dvb_usb_device *d)
        return buffer;
 }
 
-static void lme2510_exit(struct usb_interface *intf)
+static void lme2510_exit(struct dvb_usb_device *d)
 {
-       struct dvb_usb_device *d = usb_get_intfdata(intf);
        void *usb_buffer;
 
        if (d != NULL) {
                usb_buffer = lme2510_exit_int(d);
-               dvb_usb_device_exit(intf);
                if (usb_buffer != NULL)
                        kfree(usb_buffer);
        }
 }
 
+static struct dvb_usb_device_properties lme2510_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .bInterfaceNumber = 0,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct lme2510_state),
+
+       .download_firmware = lme2510_download_firmware,
+
+       .power_ctrl       = lme2510_powerup,
+       .identify_state   = lme2510_identify_state,
+       .i2c_algo         = &lme2510_i2c_algo,
+
+       .frontend_attach  = dm04_lme2510_frontend_attach,
+       .tuner_attach = dm04_lme2510_tuner,
+       .get_stream_config = lme2510_get_stream_config,
+       .get_adapter_count = lme2510_get_adapter_count,
+       .streaming_ctrl   = lme2510_streaming_ctrl,
+
+       .get_rc_config = lme2510_get_rc_config,
+
+       .exit = lme2510_exit,
+       .adapter = {
+               {
+                       .caps = DVB_USB_ADAP_HAS_PID_FILTER|
+                               DVB_USB_ADAP_PID_FILTER_CAN_BE_TURNED_OFF,
+                       .pid_filter_count = 15,
+                       .pid_filter = lme2510_pid_filter,
+                       .pid_filter_ctrl  = lme2510_pid_filter_ctrl,
+                       .stream =
+                       DVB_USB_STREAM_BULK(0x86, 10, 4096),
+               },
+               {
+               }
+       },
+};
+
+static const struct usb_device_id lme2510_id_table[] = {
+       {       DVB_USB_DEVICE(0x3344, 0x1122, &lme2510_props,
+               "DM04_LME2510_DVB-S", RC_MAP_LME2510)   },
+       {       DVB_USB_DEVICE(0x3344, 0x1120, &lme2510_props,
+               "DM04_LME2510C_DVB-S", RC_MAP_LME2510)  },
+       {       DVB_USB_DEVICE(0x3344, 0x22f0, &lme2510_props,
+               "DM04_LME2510C_DVB-S RS2000", RC_MAP_LME2510)   },
+       {}              /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, lme2510_id_table);
+
 static struct usb_driver lme2510_driver = {
-       .name           = "LME2510C_DVB-S",
-       .probe          = lme2510_probe,
-       .disconnect     = lme2510_exit,
-       .id_table       = lme2510_table,
+       .name           = KBUILD_MODNAME,
+       .probe          = dvb_usbv2_probe,
+       .disconnect     = dvb_usbv2_disconnect,
+       .id_table       = lme2510_id_table,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
 module_usb_driver(lme2510_driver);
 
 MODULE_AUTHOR("Malcolm Priestley <tvboxspy@gmail.com>");
 MODULE_DESCRIPTION("LME2510(C) DVB-S USB2.0");
-MODULE_VERSION("1.99");
+MODULE_VERSION("2.06");
 MODULE_LICENSE("GPL");
+MODULE_FIRMWARE(LME2510_C_S7395);
+MODULE_FIRMWARE(LME2510_C_LG);
+MODULE_FIRMWARE(LME2510_C_S0194);
+MODULE_FIRMWARE(LME2510_C_RS2000);
+MODULE_FIRMWARE(LME2510_LG);
+MODULE_FIRMWARE(LME2510_S0194);
+
similarity index 99%
rename from drivers/media/dvb/dvb-usb/mxl111sf-tuner.c
rename to drivers/media/usb/dvb-usb-v2/mxl111sf-tuner.c
index 74da5bb1ce99c5ab934e64d769adb38f32cd642d..ef4c65fcbb734ce6852dbd30856a5f3409849e86 100644 (file)
@@ -31,6 +31,8 @@ MODULE_PARM_DESC(debug, "set debugging level (1=info (or-able)).");
        if (mxl111sf_tuner_debug) \
                mxl_printk(KERN_DEBUG, fmt, ##arg)
 
+#define err pr_err
+
 /* ------------------------------------------------------------------------ */
 
 struct mxl111sf_tuner_state {
diff --git a/drivers/media/usb/dvb-usb-v2/mxl111sf.c b/drivers/media/usb/dvb-usb-v2/mxl111sf.c
new file mode 100644 (file)
index 0000000..efdcb15
--- /dev/null
@@ -0,0 +1,1431 @@
+/*
+ * Copyright (C) 2010 Michael Krufky (mkrufky@kernellabs.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, version 2.
+ *
+ * see Documentation/dvb/README.dvb-usb for more information
+ */
+
+#include <linux/vmalloc.h>
+#include <linux/i2c.h>
+
+#include "mxl111sf.h"
+#include "mxl111sf-reg.h"
+#include "mxl111sf-phy.h"
+#include "mxl111sf-i2c.h"
+#include "mxl111sf-gpio.h"
+
+#include "mxl111sf-demod.h"
+#include "mxl111sf-tuner.h"
+
+#include "lgdt3305.h"
+#include "lg2160.h"
+
+int dvb_usb_mxl111sf_debug;
+module_param_named(debug, dvb_usb_mxl111sf_debug, int, 0644);
+MODULE_PARM_DESC(debug, "set debugging level "
+                "(1=info, 2=xfer, 4=i2c, 8=reg, 16=adv (or-able)).");
+
+int dvb_usb_mxl111sf_isoc;
+module_param_named(isoc, dvb_usb_mxl111sf_isoc, int, 0644);
+MODULE_PARM_DESC(isoc, "enable usb isoc xfer (0=bulk, 1=isoc).");
+
+int dvb_usb_mxl111sf_spi;
+module_param_named(spi, dvb_usb_mxl111sf_spi, int, 0644);
+MODULE_PARM_DESC(spi, "use spi rather than tp for data xfer (0=tp, 1=spi).");
+
+#define ANT_PATH_AUTO 0
+#define ANT_PATH_EXTERNAL 1
+#define ANT_PATH_INTERNAL 2
+
+int dvb_usb_mxl111sf_rfswitch =
+#if 0
+               ANT_PATH_AUTO;
+#else
+               ANT_PATH_EXTERNAL;
+#endif
+
+module_param_named(rfswitch, dvb_usb_mxl111sf_rfswitch, int, 0644);
+MODULE_PARM_DESC(rfswitch, "force rf switch position (0=auto, 1=ext, 2=int).");
+
+DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
+
+#define deb_info pr_debug
+#define deb_reg pr_debug
+#define deb_adv pr_debug
+#define err pr_err
+#define info pr_info
+
+int mxl111sf_ctrl_msg(struct dvb_usb_device *d,
+                     u8 cmd, u8 *wbuf, int wlen, u8 *rbuf, int rlen)
+{
+       int wo = (rbuf == NULL || rlen == 0); /* write-only */
+       int ret;
+       u8 sndbuf[1+wlen];
+
+       deb_adv("%s(wlen = %d, rlen = %d)\n", __func__, wlen, rlen);
+
+       memset(sndbuf, 0, 1+wlen);
+
+       sndbuf[0] = cmd;
+       memcpy(&sndbuf[1], wbuf, wlen);
+
+       ret = (wo) ? dvb_usbv2_generic_write(d, sndbuf, 1+wlen) :
+               dvb_usbv2_generic_rw(d, sndbuf, 1+wlen, rbuf, rlen);
+       mxl_fail(ret);
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+#define MXL_CMD_REG_READ       0xaa
+#define MXL_CMD_REG_WRITE      0x55
+
+int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data)
+{
+       u8 buf[2];
+       int ret;
+
+       ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_READ, &addr, 1, buf, 2);
+       if (mxl_fail(ret)) {
+               mxl_debug("error reading reg: 0x%02x", addr);
+               goto fail;
+       }
+
+       if (buf[0] == addr)
+               *data = buf[1];
+       else {
+               err("invalid response reading reg: 0x%02x != 0x%02x, 0x%02x",
+                   addr, buf[0], buf[1]);
+               ret = -EINVAL;
+       }
+
+       deb_reg("R: (0x%02x, 0x%02x)\n", addr, *data);
+fail:
+       return ret;
+}
+
+int mxl111sf_write_reg(struct mxl111sf_state *state, u8 addr, u8 data)
+{
+       u8 buf[] = { addr, data };
+       int ret;
+
+       deb_reg("W: (0x%02x, 0x%02x)\n", addr, data);
+
+       ret = mxl111sf_ctrl_msg(state->d, MXL_CMD_REG_WRITE, buf, 2, NULL, 0);
+       if (mxl_fail(ret))
+               err("error writing reg: 0x%02x, val: 0x%02x", addr, data);
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_write_reg_mask(struct mxl111sf_state *state,
+                                  u8 addr, u8 mask, u8 data)
+{
+       int ret;
+       u8 val;
+
+       if (mask != 0xff) {
+               ret = mxl111sf_read_reg(state, addr, &val);
+#if 1
+               /* dont know why this usually errors out on the first try */
+               if (mxl_fail(ret))
+                       err("error writing addr: 0x%02x, mask: 0x%02x, "
+                           "data: 0x%02x, retrying...", addr, mask, data);
+
+               ret = mxl111sf_read_reg(state, addr, &val);
+#endif
+               if (mxl_fail(ret))
+                       goto fail;
+       }
+       val &= ~mask;
+       val |= data;
+
+       ret = mxl111sf_write_reg(state, addr, val);
+       mxl_fail(ret);
+fail:
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+int mxl111sf_ctrl_program_regs(struct mxl111sf_state *state,
+                              struct mxl111sf_reg_ctrl_info *ctrl_reg_info)
+{
+       int i, ret = 0;
+
+       for (i = 0;  ctrl_reg_info[i].addr |
+                    ctrl_reg_info[i].mask |
+                    ctrl_reg_info[i].data;  i++) {
+
+               ret = mxl111sf_write_reg_mask(state,
+                                             ctrl_reg_info[i].addr,
+                                             ctrl_reg_info[i].mask,
+                                             ctrl_reg_info[i].data);
+               if (mxl_fail(ret)) {
+                       err("failed on reg #%d (0x%02x)", i,
+                           ctrl_reg_info[i].addr);
+                       break;
+               }
+       }
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static int mxl1x1sf_get_chip_info(struct mxl111sf_state *state)
+{
+       int ret;
+       u8 id, ver;
+       char *mxl_chip, *mxl_rev;
+
+       if ((state->chip_id) && (state->chip_ver))
+               return 0;
+
+       ret = mxl111sf_read_reg(state, CHIP_ID_REG, &id);
+       if (mxl_fail(ret))
+               goto fail;
+       state->chip_id = id;
+
+       ret = mxl111sf_read_reg(state, TOP_CHIP_REV_ID_REG, &ver);
+       if (mxl_fail(ret))
+               goto fail;
+       state->chip_ver = ver;
+
+       switch (id) {
+       case 0x61:
+               mxl_chip = "MxL101SF";
+               break;
+       case 0x63:
+               mxl_chip = "MxL111SF";
+               break;
+       default:
+               mxl_chip = "UNKNOWN MxL1X1";
+               break;
+       }
+       switch (ver) {
+       case 0x36:
+               state->chip_rev = MXL111SF_V6;
+               mxl_rev = "v6";
+               break;
+       case 0x08:
+               state->chip_rev = MXL111SF_V8_100;
+               mxl_rev = "v8_100";
+               break;
+       case 0x18:
+               state->chip_rev = MXL111SF_V8_200;
+               mxl_rev = "v8_200";
+               break;
+       default:
+               state->chip_rev = 0;
+               mxl_rev = "UNKNOWN REVISION";
+               break;
+       }
+       info("%s detected, %s (0x%x)", mxl_chip, mxl_rev, ver);
+fail:
+       return ret;
+}
+
+#define get_chip_info(state)                                           \
+({                                                                     \
+       int ___ret;                                                     \
+       ___ret = mxl1x1sf_get_chip_info(state);                         \
+       if (mxl_fail(___ret)) {                                         \
+               mxl_debug("failed to get chip info"                     \
+                         " on first probe attempt");                   \
+               ___ret = mxl1x1sf_get_chip_info(state);                 \
+               if (mxl_fail(___ret))                                   \
+                       err("failed to get chip info during probe");    \
+               else                                                    \
+                       mxl_debug("probe needed a retry "               \
+                                 "in order to succeed.");              \
+       }                                                               \
+       ___ret;                                                         \
+})
+
+/* ------------------------------------------------------------------------ */
+#if 0
+static int mxl111sf_power_ctrl(struct dvb_usb_device *d, int onoff)
+{
+       /* power control depends on which adapter is being woken:
+        * save this for init, instead, via mxl111sf_adap_fe_init */
+       return 0;
+}
+#endif
+
+static int mxl111sf_adap_fe_init(struct dvb_frontend *fe)
+{
+       struct dvb_usb_device *d = fe_to_d(fe);
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
+       int err;
+
+       /* exit if we didnt initialize the driver yet */
+       if (!state->chip_id) {
+               mxl_debug("driver not yet initialized, exit.");
+               goto fail;
+       }
+
+       deb_info("%s()\n", __func__);
+
+       mutex_lock(&state->fe_lock);
+
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       err = mxl1x1sf_soft_reset(state);
+       mxl_fail(err);
+       err = mxl111sf_init_tuner_demod(state);
+       mxl_fail(err);
+       err = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+
+       mxl_fail(err);
+       mxl111sf_enable_usb_output(state);
+       mxl_fail(err);
+       mxl1x1sf_top_master_ctrl(state, 1);
+       mxl_fail(err);
+
+       if ((MXL111SF_GPIO_MOD_DVBT != adap_state->gpio_mode) &&
+           (state->chip_rev > MXL111SF_V6)) {
+               mxl111sf_config_pin_mux_modes(state,
+                                             PIN_MUX_TS_SPI_IN_MODE_1);
+               mxl_fail(err);
+       }
+       err = mxl111sf_init_port_expander(state);
+       if (!mxl_fail(err)) {
+               state->gpio_mode = adap_state->gpio_mode;
+               err = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+               mxl_fail(err);
+#if 0
+               err = fe->ops.init(fe);
+#endif
+               msleep(100); /* add short delay after enabling
+                             * the demod before touching it */
+       }
+
+       return (adap_state->fe_init) ? adap_state->fe_init(fe) : 0;
+fail:
+       return -ENODEV;
+}
+
+static int mxl111sf_adap_fe_sleep(struct dvb_frontend *fe)
+{
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
+       int err;
+
+       /* exit if we didnt initialize the driver yet */
+       if (!state->chip_id) {
+               mxl_debug("driver not yet initialized, exit.");
+               goto fail;
+       }
+
+       deb_info("%s()\n", __func__);
+
+       err = (adap_state->fe_sleep) ? adap_state->fe_sleep(fe) : 0;
+
+       mutex_unlock(&state->fe_lock);
+
+       return err;
+fail:
+       return -ENODEV;
+}
+
+
+static int mxl111sf_ep6_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe->id];
+       int ret = 0;
+
+       deb_info("%s(%d)\n", __func__, onoff);
+
+       if (onoff) {
+               ret = mxl111sf_enable_usb_output(state);
+               mxl_fail(ret);
+               ret = mxl111sf_config_mpeg_in(state, 1, 1,
+                                             adap_state->ep6_clockphase,
+                                             0, 0);
+               mxl_fail(ret);
+#if 0
+       } else {
+               ret = mxl111sf_disable_656_port(state);
+               mxl_fail(ret);
+#endif
+       }
+
+       return ret;
+}
+
+static int mxl111sf_ep5_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       int ret = 0;
+
+       deb_info("%s(%d)\n", __func__, onoff);
+
+       if (onoff) {
+               ret = mxl111sf_enable_usb_output(state);
+               mxl_fail(ret);
+
+               ret = mxl111sf_init_i2s_port(state, 200);
+               mxl_fail(ret);
+               ret = mxl111sf_config_i2s(state, 0, 15);
+               mxl_fail(ret);
+       } else {
+               ret = mxl111sf_disable_i2s_port(state);
+               mxl_fail(ret);
+       }
+       if (state->chip_rev > MXL111SF_V6)
+               ret = mxl111sf_config_spi(state, onoff);
+       mxl_fail(ret);
+
+       return ret;
+}
+
+static int mxl111sf_ep4_streaming_ctrl(struct dvb_frontend *fe, int onoff)
+{
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       int ret = 0;
+
+       deb_info("%s(%d)\n", __func__, onoff);
+
+       if (onoff) {
+               ret = mxl111sf_enable_usb_output(state);
+               mxl_fail(ret);
+       }
+
+       return ret;
+}
+
+/* ------------------------------------------------------------------------ */
+
+static struct lgdt3305_config hauppauge_lgdt3305_config = {
+       .i2c_addr           = 0xb2 >> 1,
+       .mpeg_mode          = LGDT3305_MPEG_SERIAL,
+       .tpclk_edge         = LGDT3305_TPCLK_RISING_EDGE,
+       .tpvalid_polarity   = LGDT3305_TP_VALID_HIGH,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .qam_if_khz         = 6000,
+       .vsb_if_khz         = 6000,
+};
+
+static int mxl111sf_lgdt3305_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct mxl111sf_state *state = d_to_priv(d);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_ATSC;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_TUNER_MODE;
+       adap_state->ep6_clockphase = 1;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_init_port_expander(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       adap->fe[fe_id] = dvb_attach(lgdt3305_attach,
+                                &hauppauge_lgdt3305_config,
+                                &d->i2c_adap);
+       if (adap->fe[fe_id]) {
+               state->num_frontends++;
+               adap_state->fe_init = adap->fe[fe_id]->ops.init;
+               adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
+               adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
+static struct lg2160_config hauppauge_lg2160_config = {
+       .lg_chip            = LG2160,
+       .i2c_addr           = 0x1c >> 1,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .if_khz             = 6000,
+};
+
+static int mxl111sf_lg2160_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct mxl111sf_state *state = d_to_priv(d);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_TUNER_MODE;
+       adap_state->ep6_clockphase = 1;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_init_port_expander(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       adap->fe[fe_id] = dvb_attach(lg2160_attach,
+                             &hauppauge_lg2160_config,
+                             &d->i2c_adap);
+       if (adap->fe[fe_id]) {
+               state->num_frontends++;
+               adap_state->fe_init = adap->fe[fe_id]->ops.init;
+               adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
+               adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
+static struct lg2160_config hauppauge_lg2161_1019_config = {
+       .lg_chip            = LG2161_1019,
+       .i2c_addr           = 0x1c >> 1,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .if_khz             = 6000,
+       .output_if          = 2, /* LG2161_OIF_SPI_MAS */
+};
+
+static struct lg2160_config hauppauge_lg2161_1040_config = {
+       .lg_chip            = LG2161_1040,
+       .i2c_addr           = 0x1c >> 1,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .if_khz             = 6000,
+       .output_if          = 4, /* LG2161_OIF_SPI_MAS */
+};
+
+static int mxl111sf_lg2161_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct mxl111sf_state *state = d_to_priv(d);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_TUNER_MODE;
+       adap_state->ep6_clockphase = 1;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_init_port_expander(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       adap->fe[fe_id] = dvb_attach(lg2160_attach,
+                             (MXL111SF_V8_200 == state->chip_rev) ?
+                             &hauppauge_lg2161_1040_config :
+                             &hauppauge_lg2161_1019_config,
+                             &d->i2c_adap);
+       if (adap->fe[fe_id]) {
+               state->num_frontends++;
+               adap_state->fe_init = adap->fe[fe_id]->ops.init;
+               adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
+               adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
+static struct lg2160_config hauppauge_lg2161_1019_ep6_config = {
+       .lg_chip            = LG2161_1019,
+       .i2c_addr           = 0x1c >> 1,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .if_khz             = 6000,
+       .output_if          = 1, /* LG2161_OIF_SERIAL_TS */
+};
+
+static struct lg2160_config hauppauge_lg2161_1040_ep6_config = {
+       .lg_chip            = LG2161_1040,
+       .i2c_addr           = 0x1c >> 1,
+       .deny_i2c_rptr      = 1,
+       .spectral_inversion = 0,
+       .if_khz             = 6000,
+       .output_if          = 7, /* LG2161_OIF_SERIAL_TS */
+};
+
+static int mxl111sf_lg2161_ep6_frontend_attach(struct dvb_usb_adapter *adap, u8 fe_id)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct mxl111sf_state *state = d_to_priv(d);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 2 : 1;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_MH;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_TUNER_MODE;
+       adap_state->ep6_clockphase = 0;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_init_port_expander(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_gpio_mode_switch(state, state->gpio_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       adap->fe[fe_id] = dvb_attach(lg2160_attach,
+                             (MXL111SF_V8_200 == state->chip_rev) ?
+                             &hauppauge_lg2161_1040_ep6_config :
+                             &hauppauge_lg2161_1019_ep6_config,
+                             &d->i2c_adap);
+       if (adap->fe[fe_id]) {
+               state->num_frontends++;
+               adap_state->fe_init = adap->fe[fe_id]->ops.init;
+               adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
+               adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
+static struct mxl111sf_demod_config mxl_demod_config = {
+       .read_reg        = mxl111sf_read_reg,
+       .write_reg       = mxl111sf_write_reg,
+       .program_regs    = mxl111sf_ctrl_program_regs,
+};
+
+static int mxl111sf_attach_demod(struct dvb_usb_adapter *adap, u8 fe_id)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct mxl111sf_state *state = d_to_priv(d);
+       struct mxl111sf_adap_state *adap_state = &state->adap_state[fe_id];
+       int ret;
+
+       deb_adv("%s()\n", __func__);
+
+       /* save a pointer to the dvb_usb_device in device state */
+       state->d = d;
+       adap_state->alt_mode = (dvb_usb_mxl111sf_isoc) ? 1 : 2;
+       state->alt_mode = adap_state->alt_mode;
+
+       if (usb_set_interface(d->udev, 0, state->alt_mode) < 0)
+               err("set interface failed");
+
+       state->gpio_mode = MXL111SF_GPIO_MOD_DVBT;
+       adap_state->gpio_mode = state->gpio_mode;
+       adap_state->device_mode = MXL_SOC_MODE;
+       adap_state->ep6_clockphase = 1;
+
+       ret = mxl1x1sf_soft_reset(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl111sf_init_tuner_demod(state);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl1x1sf_set_device_mode(state, adap_state->device_mode);
+       if (mxl_fail(ret))
+               goto fail;
+
+       ret = mxl111sf_enable_usb_output(state);
+       if (mxl_fail(ret))
+               goto fail;
+       ret = mxl1x1sf_top_master_ctrl(state, 1);
+       if (mxl_fail(ret))
+               goto fail;
+
+       /* dont care if this fails */
+       mxl111sf_init_port_expander(state);
+
+       adap->fe[fe_id] = dvb_attach(mxl111sf_demod_attach, state,
+                             &mxl_demod_config);
+       if (adap->fe[fe_id]) {
+               state->num_frontends++;
+               adap_state->fe_init = adap->fe[fe_id]->ops.init;
+               adap->fe[fe_id]->ops.init = mxl111sf_adap_fe_init;
+               adap_state->fe_sleep = adap->fe[fe_id]->ops.sleep;
+               adap->fe[fe_id]->ops.sleep = mxl111sf_adap_fe_sleep;
+               return 0;
+       }
+       ret = -EIO;
+fail:
+       return ret;
+}
+
+static inline int mxl111sf_set_ant_path(struct mxl111sf_state *state,
+                                       int antpath)
+{
+       return mxl111sf_idac_config(state, 1, 1,
+                                   (antpath == ANT_PATH_INTERNAL) ?
+                                   0x3f : 0x00, 0);
+}
+
+#define DbgAntHunt(x, pwr0, pwr1, pwr2, pwr3) \
+       err("%s(%d) FINAL input set to %s rxPwr:%d|%d|%d|%d\n", \
+           __func__, __LINE__, \
+           (ANT_PATH_EXTERNAL == x) ? "EXTERNAL" : "INTERNAL", \
+           pwr0, pwr1, pwr2, pwr3)
+
+#define ANT_HUNT_SLEEP 90
+#define ANT_EXT_TWEAK 0
+
+static int mxl111sf_ant_hunt(struct dvb_frontend *fe)
+{
+       struct mxl111sf_state *state = fe_to_priv(fe);
+       int antctrl = dvb_usb_mxl111sf_rfswitch;
+
+       u16 rxPwrA, rxPwr0, rxPwr1, rxPwr2;
+
+       /* FIXME: must force EXTERNAL for QAM - done elsewhere */
+       mxl111sf_set_ant_path(state, antctrl == ANT_PATH_AUTO ?
+                             ANT_PATH_EXTERNAL : antctrl);
+
+       if (antctrl == ANT_PATH_AUTO) {
+#if 0
+               msleep(ANT_HUNT_SLEEP);
+#endif
+               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwrA);
+
+               mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+               msleep(ANT_HUNT_SLEEP);
+               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr0);
+
+               mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+               msleep(ANT_HUNT_SLEEP);
+               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr1);
+
+               mxl111sf_set_ant_path(state, ANT_PATH_INTERNAL);
+               msleep(ANT_HUNT_SLEEP);
+               fe->ops.tuner_ops.get_rf_strength(fe, &rxPwr2);
+
+               if (rxPwr1+ANT_EXT_TWEAK >= rxPwr2) {
+                       /* return with EXTERNAL enabled */
+                       mxl111sf_set_ant_path(state, ANT_PATH_EXTERNAL);
+                       DbgAntHunt(ANT_PATH_EXTERNAL, rxPwrA,
+                                  rxPwr0, rxPwr1, rxPwr2);
+               } else {
+                       /* return with INTERNAL enabled */
+                       DbgAntHunt(ANT_PATH_INTERNAL, rxPwrA,
+                                  rxPwr0, rxPwr1, rxPwr2);
+               }
+       }
+       return 0;
+}
+
+static struct mxl111sf_tuner_config mxl_tuner_config = {
+       .if_freq         = MXL_IF_6_0, /* applies to external IF output, only */
+       .invert_spectrum = 0,
+       .read_reg        = mxl111sf_read_reg,
+       .write_reg       = mxl111sf_write_reg,
+       .program_regs    = mxl111sf_ctrl_program_regs,
+       .top_master_ctrl = mxl1x1sf_top_master_ctrl,
+       .ant_hunt        = mxl111sf_ant_hunt,
+};
+
+static int mxl111sf_attach_tuner(struct dvb_usb_adapter *adap)
+{
+       struct mxl111sf_state *state = adap_to_priv(adap);
+       int i;
+
+       deb_adv("%s()\n", __func__);
+
+       for (i = 0; i < state->num_frontends; i++) {
+               if (dvb_attach(mxl111sf_tuner_attach, adap->fe[i], state,
+                               &mxl_tuner_config) == NULL)
+                       return -EIO;
+               adap->fe[i]->ops.read_signal_strength = adap->fe[i]->ops.tuner_ops.get_rf_strength;
+       }
+
+       return 0;
+}
+
+static u32 mxl111sf_i2c_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_I2C;
+}
+
+struct i2c_algorithm mxl111sf_i2c_algo = {
+       .master_xfer   = mxl111sf_i2c_xfer,
+       .functionality = mxl111sf_i2c_func,
+#ifdef NEED_ALGO_CONTROL
+       .algo_control = dummy_algo_control,
+#endif
+};
+
+static int mxl111sf_init(struct dvb_usb_device *d)
+{
+       struct mxl111sf_state *state = d_to_priv(d);
+       int ret;
+       static u8 eeprom[256];
+       struct i2c_client c;
+
+       ret = get_chip_info(state);
+       if (mxl_fail(ret))
+               err("failed to get chip info during probe");
+
+       mutex_init(&state->fe_lock);
+
+       if (state->chip_rev > MXL111SF_V6)
+               mxl111sf_config_pin_mux_modes(state, PIN_MUX_TS_SPI_IN_MODE_1);
+
+       c.adapter = &d->i2c_adap;
+       c.addr = 0xa0 >> 1;
+
+       ret = tveeprom_read(&c, eeprom, sizeof(eeprom));
+       if (mxl_fail(ret))
+               return 0;
+       tveeprom_hauppauge_analog(&c, &state->tv, (0x84 == eeprom[0xa0]) ?
+                       eeprom + 0xa0 : eeprom + 0x80);
+#if 0
+       switch (state->tv.model) {
+       case 117001:
+       case 126001:
+       case 138001:
+               break;
+       default:
+               printk(KERN_WARNING "%s: warning: "
+                      "unknown hauppauge model #%d\n",
+                      __func__, state->tv.model);
+       }
+#endif
+       return 0;
+}
+
+static int mxl111sf_frontend_attach_dvbt(struct dvb_usb_adapter *adap)
+{
+       return mxl111sf_attach_demod(adap, 0);
+}
+
+static int mxl111sf_frontend_attach_atsc(struct dvb_usb_adapter *adap)
+{
+       return mxl111sf_lgdt3305_frontend_attach(adap, 0);
+}
+
+static int mxl111sf_frontend_attach_mh(struct dvb_usb_adapter *adap)
+{
+       return mxl111sf_lg2160_frontend_attach(adap, 0);
+}
+
+static int mxl111sf_frontend_attach_atsc_mh(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       deb_info("%s\n", __func__);
+
+       ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = mxl111sf_attach_demod(adap, 1);
+       if (ret < 0)
+               return ret;
+
+       ret = mxl111sf_lg2160_frontend_attach(adap, 2);
+       if (ret < 0)
+               return ret;
+
+       return ret;
+}
+
+static int mxl111sf_frontend_attach_mercury(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       deb_info("%s\n", __func__);
+
+       ret = mxl111sf_lgdt3305_frontend_attach(adap, 0);
+       if (ret < 0)
+               return ret;
+
+       ret = mxl111sf_attach_demod(adap, 1);
+       if (ret < 0)
+               return ret;
+
+       ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 2);
+       if (ret < 0)
+               return ret;
+
+       return ret;
+}
+
+static int mxl111sf_frontend_attach_mercury_mh(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       deb_info("%s\n", __func__);
+
+       ret = mxl111sf_attach_demod(adap, 0);
+       if (ret < 0)
+               return ret;
+
+       if (dvb_usb_mxl111sf_spi)
+               ret = mxl111sf_lg2161_frontend_attach(adap, 1);
+       else
+               ret = mxl111sf_lg2161_ep6_frontend_attach(adap, 1);
+
+       return ret;
+}
+
+static void mxl111sf_stream_config_bulk(struct usb_data_stream_properties *stream, u8 endpoint)
+{
+       deb_info("%s: endpoint=%d size=8192\n", __func__, endpoint);
+       stream->type = USB_BULK;
+       stream->count = 5;
+       stream->endpoint = endpoint;
+       stream->u.bulk.buffersize = 8192;
+}
+
+static void mxl111sf_stream_config_isoc(struct usb_data_stream_properties *stream,
+               u8 endpoint, int framesperurb, int framesize)
+{
+       deb_info("%s: endpoint=%d size=%d\n", __func__, endpoint,
+                       framesperurb * framesize);
+       stream->type = USB_ISOC;
+       stream->count = 5;
+       stream->endpoint = endpoint;
+       stream->u.isoc.framesperurb = framesperurb;
+       stream->u.isoc.framesize = framesize;
+       stream->u.isoc.interval = 1;
+}
+
+/* DVB USB Driver stuff */
+
+/* dvbt       mxl111sf
+ * bulk       EP4/BULK/5/8192
+ * isoc       EP4/ISOC/5/96/564
+ */
+static int mxl111sf_get_stream_config_dvbt(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       *ts_type = DVB_USB_FE_TS_TYPE_188;
+       if (dvb_usb_mxl111sf_isoc)
+               mxl111sf_stream_config_isoc(stream, 4, 96, 564);
+       else
+               mxl111sf_stream_config_bulk(stream, 4);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_dvbt = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_dvbt,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_ep4_streaming_ctrl,
+       .get_stream_config = mxl111sf_get_stream_config_dvbt,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+/* atsc       lgdt3305
+ * bulk       EP6/BULK/5/8192
+ * isoc       EP6/ISOC/5/24/3072
+ */
+static int mxl111sf_get_stream_config_atsc(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       *ts_type = DVB_USB_FE_TS_TYPE_188;
+       if (dvb_usb_mxl111sf_isoc)
+               mxl111sf_stream_config_isoc(stream, 6, 24, 3072);
+       else
+               mxl111sf_stream_config_bulk(stream, 6);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_atsc = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_atsc,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_ep6_streaming_ctrl,
+       .get_stream_config = mxl111sf_get_stream_config_atsc,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+/* mh         lg2160
+ * bulk       EP5/BULK/5/8192/RAW
+ * isoc       EP5/ISOC/5/96/200/RAW
+ */
+static int mxl111sf_get_stream_config_mh(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+       if (dvb_usb_mxl111sf_isoc)
+               mxl111sf_stream_config_isoc(stream, 5, 96, 200);
+       else
+               mxl111sf_stream_config_bulk(stream, 5);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_mh = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_ep5_streaming_ctrl,
+       .get_stream_config = mxl111sf_get_stream_config_mh,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+/* atsc mh    lgdt3305           mxl111sf          lg2160
+ * bulk       EP6/BULK/5/8192    EP4/BULK/5/8192   EP5/BULK/5/8192/RAW
+ * isoc       EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW
+ */
+static int mxl111sf_get_stream_config_atsc_mh(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       if (fe->id == 0) {
+               *ts_type = DVB_USB_FE_TS_TYPE_188;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 6, 24, 3072);
+               else
+                       mxl111sf_stream_config_bulk(stream, 6);
+       } else if (fe->id == 1) {
+               *ts_type = DVB_USB_FE_TS_TYPE_188;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 4, 96, 564);
+               else
+                       mxl111sf_stream_config_bulk(stream, 4);
+       } else if (fe->id == 2) {
+               *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 5, 96, 200);
+               else
+                       mxl111sf_stream_config_bulk(stream, 5);
+       }
+       return 0;
+}
+
+static int mxl111sf_streaming_ctrl_atsc_mh(struct dvb_frontend *fe, int onoff)
+{
+       deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+       if (fe->id == 0)
+               return mxl111sf_ep6_streaming_ctrl(fe, onoff);
+       else if (fe->id == 1)
+               return mxl111sf_ep4_streaming_ctrl(fe, onoff);
+       else if (fe->id == 2)
+               return mxl111sf_ep5_streaming_ctrl(fe, onoff);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_atsc_mh = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_atsc_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_streaming_ctrl_atsc_mh,
+       .get_stream_config = mxl111sf_get_stream_config_atsc_mh,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+/* mercury    lgdt3305           mxl111sf          lg2161
+ * tp bulk    EP6/BULK/5/8192    EP4/BULK/5/8192   EP6/BULK/5/8192/RAW
+ * tp isoc    EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW
+ * spi bulk   EP6/BULK/5/8192    EP4/BULK/5/8192   EP5/BULK/5/8192/RAW
+ * spi isoc   EP6/ISOC/5/24/3072 EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW
+ */
+static int mxl111sf_get_stream_config_mercury(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       if (fe->id == 0) {
+               *ts_type = DVB_USB_FE_TS_TYPE_188;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 6, 24, 3072);
+               else
+                       mxl111sf_stream_config_bulk(stream, 6);
+       } else if (fe->id == 1) {
+               *ts_type = DVB_USB_FE_TS_TYPE_188;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 4, 96, 564);
+               else
+                       mxl111sf_stream_config_bulk(stream, 4);
+       } else if (fe->id == 2 && dvb_usb_mxl111sf_spi) {
+               *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 5, 96, 200);
+               else
+                       mxl111sf_stream_config_bulk(stream, 5);
+       } else if (fe->id == 2 && !dvb_usb_mxl111sf_spi) {
+               *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 6, 24, 3072);
+               else
+                       mxl111sf_stream_config_bulk(stream, 6);
+       }
+       return 0;
+}
+
+static int mxl111sf_streaming_ctrl_mercury(struct dvb_frontend *fe, int onoff)
+{
+       deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+       if (fe->id == 0)
+               return mxl111sf_ep6_streaming_ctrl(fe, onoff);
+       else if (fe->id == 1)
+               return mxl111sf_ep4_streaming_ctrl(fe, onoff);
+       else if (fe->id == 2 && dvb_usb_mxl111sf_spi)
+               return mxl111sf_ep5_streaming_ctrl(fe, onoff);
+       else if (fe->id == 2 && !dvb_usb_mxl111sf_spi)
+               return mxl111sf_ep6_streaming_ctrl(fe, onoff);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_mercury = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mercury,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_streaming_ctrl_mercury,
+       .get_stream_config = mxl111sf_get_stream_config_mercury,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+/* mercury mh mxl111sf          lg2161
+ * tp bulk    EP4/BULK/5/8192   EP6/BULK/5/8192/RAW
+ * tp isoc    EP4/ISOC/5/96/564 EP6/ISOC/5/24/3072/RAW
+ * spi bulk   EP4/BULK/5/8192   EP5/BULK/5/8192/RAW
+ * spi isoc   EP4/ISOC/5/96/564 EP5/ISOC/5/96/200/RAW
+ */
+static int mxl111sf_get_stream_config_mercury_mh(struct dvb_frontend *fe,
+               u8 *ts_type, struct usb_data_stream_properties *stream)
+{
+       deb_info("%s: fe=%d\n", __func__, fe->id);
+
+       if (fe->id == 0) {
+               *ts_type = DVB_USB_FE_TS_TYPE_188;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 4, 96, 564);
+               else
+                       mxl111sf_stream_config_bulk(stream, 4);
+       } else if (fe->id == 1 && dvb_usb_mxl111sf_spi) {
+               *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 5, 96, 200);
+               else
+                       mxl111sf_stream_config_bulk(stream, 5);
+       } else if (fe->id == 1 && !dvb_usb_mxl111sf_spi) {
+               *ts_type = DVB_USB_FE_TS_TYPE_RAW;
+               if (dvb_usb_mxl111sf_isoc)
+                       mxl111sf_stream_config_isoc(stream, 6, 24, 3072);
+               else
+                       mxl111sf_stream_config_bulk(stream, 6);
+       }
+       return 0;
+}
+
+static int mxl111sf_streaming_ctrl_mercury_mh(struct dvb_frontend *fe, int onoff)
+{
+       deb_info("%s: fe=%d onoff=%d\n", __func__, fe->id, onoff);
+
+       if (fe->id == 0)
+               return mxl111sf_ep4_streaming_ctrl(fe, onoff);
+       else if (fe->id == 1  && dvb_usb_mxl111sf_spi)
+               return mxl111sf_ep5_streaming_ctrl(fe, onoff);
+       else if (fe->id == 1 && !dvb_usb_mxl111sf_spi)
+               return mxl111sf_ep6_streaming_ctrl(fe, onoff);
+       return 0;
+}
+
+static struct dvb_usb_device_properties mxl111sf_props_mercury_mh = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct mxl111sf_state),
+
+       .generic_bulk_ctrl_endpoint = 0x02,
+       .generic_bulk_ctrl_endpoint_response = 0x81,
+
+       .i2c_algo          = &mxl111sf_i2c_algo,
+       .frontend_attach   = mxl111sf_frontend_attach_mercury_mh,
+       .tuner_attach      = mxl111sf_attach_tuner,
+       .init              = mxl111sf_init,
+       .streaming_ctrl    = mxl111sf_streaming_ctrl_mercury_mh,
+       .get_stream_config = mxl111sf_get_stream_config_mercury_mh,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_ISOC(6, 5, 24, 3072, 1),
+               }
+       }
+};
+
+static const struct usb_device_id mxl111sf_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc600, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc601, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc602, &mxl111sf_props_mh, "HCW 126xxx", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc603, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc604, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc609, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60a, &mxl111sf_props_mh, "HCW 126xxx", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc60c, &mxl111sf_props_dvbt, "Hauppauge 126xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc653, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc65b, &mxl111sf_props_atsc_mh, "Hauppauge 126xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb700, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb701, &mxl111sf_props_atsc, "Hauppauge 126xxx ATSC", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb702, &mxl111sf_props_mh, "HCW 117xxx", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb703, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb704, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb753, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb763, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb764, &mxl111sf_props_dvbt, "Hauppauge 117xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd853, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd854, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd863, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd864, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8d4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e3, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8e4, &mxl111sf_props_dvbt, "Hauppauge 138xxx DVBT", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xd8ff, &mxl111sf_props_mercury, "Hauppauge Mercury", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc612, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc613, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61a, &mxl111sf_props_mercury_mh, "Hauppauge 126xxx", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xc61b, &mxl111sf_props_mercury, "Hauppauge WinTV-Aero-M", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb757, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { DVB_USB_DEVICE(USB_VID_HAUPPAUGE, 0xb767, &mxl111sf_props_atsc_mh, "Hauppauge 117xxx ATSC+", NULL) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, mxl111sf_id_table);
+
+static struct usb_driver mxl111sf_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = mxl111sf_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
+};
+
+module_usb_driver(mxl111sf_usb_driver);
+
+MODULE_AUTHOR("Michael Krufky <mkrufky@kernellabs.com>");
+MODULE_DESCRIPTION("Driver for MaxLinear MxL111SF");
+MODULE_VERSION("1.0");
+MODULE_LICENSE("GPL");
+
+/*
+ * Local variables:
+ * c-basic-offset: 8
+ * End:
+ */
similarity index 98%
rename from drivers/media/dvb/dvb-usb/mxl111sf.h
rename to drivers/media/usb/dvb-usb-v2/mxl111sf.h
index 364d89f826bd09318888175851cb3d357115f35f..9816de86e48cb4bd088c535b990d582db1e636db 100644 (file)
@@ -15,7 +15,7 @@
 #undef DVB_USB_LOG_PREFIX
 #endif
 #define DVB_USB_LOG_PREFIX "mxl111sf"
-#include "dvb-usb.h"
+#include "dvb_usb.h"
 #include <media/tveeprom.h>
 
 #define MXL_EP1_REG_READ     1
@@ -39,6 +39,15 @@ enum mxl111sf_gpio_port_expander {
        mxl111sf_PCA9534,
 };
 
+struct mxl111sf_adap_state {
+       int alt_mode;
+       int gpio_mode;
+       int device_mode;
+       int ep6_clockphase;
+       int (*fe_init)(struct dvb_frontend *);
+       int (*fe_sleep)(struct dvb_frontend *);
+};
+
 struct mxl111sf_state {
        struct dvb_usb_device *d;
 
@@ -74,15 +83,8 @@ struct mxl111sf_state {
        struct tveeprom tv;
 
        struct mutex fe_lock;
-};
-
-struct mxl111sf_adap_state {
-       int alt_mode;
-       int gpio_mode;
-       int device_mode;
-       int ep6_clockphase;
-       int (*fe_init)(struct dvb_frontend *);
-       int (*fe_sleep)(struct dvb_frontend *);
+       u8 num_frontends;
+       struct mxl111sf_adap_state adap_state[3];
 };
 
 int mxl111sf_read_reg(struct mxl111sf_state *state, u8 addr, u8 *data);
similarity index 62%
rename from drivers/media/dvb/dvb-usb/rtl28xxu.c
rename to drivers/media/usb/dvb-usb-v2/rtl28xxu.c
index 6bd0bd792437d38c2fd769470ddaa3a943f49016..adabba8d28bc80fa69b76348f40b83f63a680390 100644 (file)
 #include "mxl5005s.h"
 #include "fc0012.h"
 #include "fc0013.h"
+#include "e4000.h"
+#include "fc2580.h"
+#include "tua9001.h"
 
-/* debug */
-static int dvb_usb_rtl28xxu_debug;
-module_param_named(debug, dvb_usb_rtl28xxu_debug, int, 0644);
-MODULE_PARM_DESC(debug, "set debugging level" DVB_USB_DEBUG_STATUS);
 DVB_DEFINE_MOD_OPT_ADAPTER_NR(adapter_nr);
 
 static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
@@ -63,12 +62,13 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 
        ret = usb_control_msg(d->udev, pipe, 0, requesttype, req->value,
                        req->index, buf, req->size, 1000);
+
+       dvb_usb_dbg_usb_control_msg(d->udev, 0, requesttype, req->value,
+                       req->index, buf, req->size);
+
        if (ret > 0)
                ret = 0;
 
-       deb_dump(0, requesttype, req->value, req->index, buf, req->size,
-                       deb_xfer);
-
        /* read request, copy returned data to return buf */
        if (!ret && requesttype == (USB_TYPE_VENDOR | USB_DIR_IN))
                memcpy(req->data, buf, req->size);
@@ -80,7 +80,7 @@ static int rtl28xxu_ctrl_msg(struct dvb_usb_device *d, struct rtl28xxu_req *req)
 
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -130,6 +130,26 @@ static int rtl28xx_rd_reg(struct dvb_usb_device *d, u16 reg, u8 *val)
        return rtl2831_rd_regs(d, reg, val, 1);
 }
 
+static int rtl28xx_wr_reg_mask(struct dvb_usb_device *d, u16 reg, u8 val,
+               u8 mask)
+{
+       int ret;
+       u8 tmp;
+
+       /* no need for read if whole reg is written */
+       if (mask != 0xff) {
+               ret = rtl28xx_rd_reg(d, reg, &tmp);
+               if (ret)
+                       return ret;
+
+               val &= mask;
+               tmp &= ~mask;
+               val |= tmp;
+       }
+
+       return rtl28xx_wr_reg(d, reg, val);
+}
+
 /* I2C */
 static int rtl28xxu_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msg[],
        int num)
@@ -254,54 +274,18 @@ static struct i2c_algorithm rtl28xxu_i2c_algo = {
        .functionality = rtl28xxu_i2c_func,
 };
 
-static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
-       .i2c_addr = 0x10, /* 0x20 */
-       .xtal = 28800000,
-       .ts_mode = 0,
-       .spec_inv = 1,
-       .if_dvbt = 36150000,
-       .vtop = 0x20,
-       .krf = 0x04,
-       .agc_targ_val = 0x2d,
-
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
-       .i2c_addr = 0x10, /* 0x20 */
-       .xtal = 28800000,
-       .ts_mode = 0,
-       .spec_inv = 1,
-       .if_dvbt = 36125000,
-       .vtop = 0x20,
-       .krf = 0x04,
-       .agc_targ_val = 0x2d,
-};
-
-static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
-       .i2c_addr = 0x10, /* 0x20 */
-       .xtal = 28800000,
-       .ts_mode = 0,
-       .spec_inv = 0,
-       .if_dvbt = 4570000,
-       .vtop = 0x3f,
-       .krf = 0x04,
-       .agc_targ_val = 0x3e,
-};
-
-static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
+static int rtl2831u_read_config(struct dvb_usb_device *d)
 {
+       struct rtl28xxu_priv *priv = d_to_priv(d);
        int ret;
-       struct rtl28xxu_priv *priv = adap->dev->priv;
        u8 buf[1];
-       struct rtl2830_config *rtl2830_config;
        /* open RTL2831U/RTL2830 I2C gate */
-       struct rtl28xxu_req req_gate = { 0x0120, 0x0011, 0x0001, "\x08" };
-       /* for MT2060 tuner probe */
-       struct rtl28xxu_req req_mt2060 = { 0x00c0, CMD_I2C_RD, 1, buf };
-       /* for QT1010 tuner probe */
-       struct rtl28xxu_req req_qt1010 = { 0x0fc4, CMD_I2C_RD, 1, buf };
+       struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x08"};
+       /* tuner probes */
+       struct rtl28xxu_req req_mt2060 = {0x00c0, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_qt1010 = {0x0fc4, CMD_I2C_RD, 1, buf};
 
-       deb_info("%s:\n", __func__);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
        /*
         * RTL2831U GPIOs
@@ -312,12 +296,12 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
         */
 
        /* GPIO direction */
-       ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, 0x0a);
+       ret = rtl28xx_wr_reg(d, SYS_GPIO_DIR, 0x0a);
        if (ret)
                goto err;
 
        /* enable as output GPIO0, GPIO2, GPIO4 */
-       ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, 0x15);
+       ret = rtl28xx_wr_reg(d, SYS_GPIO_OUT_EN, 0x15);
        if (ret)
                goto err;
 
@@ -329,59 +313,253 @@ static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
        /* demod needs some time to wake up */
        msleep(20);
 
+       priv->tuner_name = "NONE";
+
        /* open demod I2C gate */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
+       ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
        if (ret)
                goto err;
 
        /* check QT1010 ID(?) register; reg=0f val=2c */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_qt1010);
+       ret = rtl28xxu_ctrl_msg(d, &req_qt1010);
        if (ret == 0 && buf[0] == 0x2c) {
                priv->tuner = TUNER_RTL2830_QT1010;
-               rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
-               deb_info("%s: QT1010\n", __func__);
+               priv->tuner_name = "QT1010";
                goto found;
-       } else {
-               deb_info("%s: QT1010 probe failed=%d - %02x\n",
-                       __func__, ret, buf[0]);
        }
 
        /* open demod I2C gate */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate);
+       ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
        if (ret)
                goto err;
 
        /* check MT2060 ID register; reg=00 val=63 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2060);
+       ret = rtl28xxu_ctrl_msg(d, &req_mt2060);
        if (ret == 0 && buf[0] == 0x63) {
                priv->tuner = TUNER_RTL2830_MT2060;
-               rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
-               deb_info("%s: MT2060\n", __func__);
+               priv->tuner_name = "MT2060";
                goto found;
-       } else {
-               deb_info("%s: MT2060 probe failed=%d - %02x\n",
-                       __func__, ret, buf[0]);
        }
 
        /* assume MXL5005S */
-       ret = 0;
        priv->tuner = TUNER_RTL2830_MXL5005S;
-       rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
-       deb_info("%s: MXL5005S\n", __func__);
+       priv->tuner_name = "MXL5005S";
        goto found;
 
 found:
+       dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static int rtl2832u_read_config(struct dvb_usb_device *d)
+{
+       struct rtl28xxu_priv *priv = d_to_priv(d);
+       int ret;
+       u8 buf[2];
+       /* open RTL2832U/RTL2832 I2C gate */
+       struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
+       /* close RTL2832U/RTL2832 I2C gate */
+       struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
+       /* tuner probes */
+       struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
+       struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
+       struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       /* enable GPIO3 and GPIO6 as output */
+       ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x40);
+       if (ret)
+               goto err;
+
+       ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x48, 0x48);
+       if (ret)
+               goto err;
+
+       /*
+        * Probe used tuner. We need to know used tuner before demod attach
+        * since there is some demod params needed to set according to tuner.
+        */
+
+       /* open demod I2C gate */
+       ret = rtl28xxu_ctrl_msg(d, &req_gate_open);
+       if (ret)
+               goto err;
+
+       priv->tuner_name = "NONE";
+
+       /* check FC0012 ID register; reg=00 val=a1 */
+       ret = rtl28xxu_ctrl_msg(d, &req_fc0012);
+       if (ret == 0 && buf[0] == 0xa1) {
+               priv->tuner = TUNER_RTL2832_FC0012;
+               priv->tuner_name = "FC0012";
+               goto found;
+       }
+
+       /* check FC0013 ID register; reg=00 val=a3 */
+       ret = rtl28xxu_ctrl_msg(d, &req_fc0013);
+       if (ret == 0 && buf[0] == 0xa3) {
+               priv->tuner = TUNER_RTL2832_FC0013;
+               priv->tuner_name = "FC0013";
+               goto found;
+       }
+
+       /* check MT2266 ID register; reg=00 val=85 */
+       ret = rtl28xxu_ctrl_msg(d, &req_mt2266);
+       if (ret == 0 && buf[0] == 0x85) {
+               priv->tuner = TUNER_RTL2832_MT2266;
+               priv->tuner_name = "MT2266";
+               goto found;
+       }
+
+       /* check FC2580 ID register; reg=01 val=56 */
+       ret = rtl28xxu_ctrl_msg(d, &req_fc2580);
+       if (ret == 0 && buf[0] == 0x56) {
+               priv->tuner = TUNER_RTL2832_FC2580;
+               priv->tuner_name = "FC2580";
+               goto found;
+       }
+
+       /* check MT2063 ID register; reg=00 val=9e || 9c */
+       ret = rtl28xxu_ctrl_msg(d, &req_mt2063);
+       if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
+               priv->tuner = TUNER_RTL2832_MT2063;
+               priv->tuner_name = "MT2063";
+               goto found;
+       }
+
+       /* check MAX3543 ID register; reg=00 val=38 */
+       ret = rtl28xxu_ctrl_msg(d, &req_max3543);
+       if (ret == 0 && buf[0] == 0x38) {
+               priv->tuner = TUNER_RTL2832_MAX3543;
+               priv->tuner_name = "MAX3543";
+               goto found;
+       }
+
+       /* check TUA9001 ID register; reg=7e val=2328 */
+       ret = rtl28xxu_ctrl_msg(d, &req_tua9001);
+       if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
+               priv->tuner = TUNER_RTL2832_TUA9001;
+               priv->tuner_name = "TUA9001";
+               goto found;
+       }
+
+       /* check MXL5007R ID register; reg=d9 val=14 */
+       ret = rtl28xxu_ctrl_msg(d, &req_mxl5007t);
+       if (ret == 0 && buf[0] == 0x14) {
+               priv->tuner = TUNER_RTL2832_MXL5007T;
+               priv->tuner_name = "MXL5007T";
+               goto found;
+       }
+
+       /* check E4000 ID register; reg=02 val=40 */
+       ret = rtl28xxu_ctrl_msg(d, &req_e4000);
+       if (ret == 0 && buf[0] == 0x40) {
+               priv->tuner = TUNER_RTL2832_E4000;
+               priv->tuner_name = "E4000";
+               goto found;
+       }
+
+       /* check TDA18272 ID register; reg=00 val=c760  */
+       ret = rtl28xxu_ctrl_msg(d, &req_tda18272);
+       if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
+               priv->tuner = TUNER_RTL2832_TDA18272;
+               priv->tuner_name = "TDA18272";
+               goto found;
+       }
+
+found:
+       dev_dbg(&d->udev->dev, "%s: tuner=%s\n", __func__, priv->tuner_name);
+
+       /* close demod I2C gate */
+       ret = rtl28xxu_ctrl_msg(d, &req_gate_close);
+       if (ret < 0)
+               goto err;
+
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
+
+static struct rtl2830_config rtl28xxu_rtl2830_mt2060_config = {
+       .i2c_addr = 0x10, /* 0x20 */
+       .xtal = 28800000,
+       .ts_mode = 0,
+       .spec_inv = 1,
+       .vtop = 0x20,
+       .krf = 0x04,
+       .agc_targ_val = 0x2d,
+
+};
+
+static struct rtl2830_config rtl28xxu_rtl2830_qt1010_config = {
+       .i2c_addr = 0x10, /* 0x20 */
+       .xtal = 28800000,
+       .ts_mode = 0,
+       .spec_inv = 1,
+       .vtop = 0x20,
+       .krf = 0x04,
+       .agc_targ_val = 0x2d,
+};
+
+static struct rtl2830_config rtl28xxu_rtl2830_mxl5005s_config = {
+       .i2c_addr = 0x10, /* 0x20 */
+       .xtal = 28800000,
+       .ts_mode = 0,
+       .spec_inv = 0,
+       .vtop = 0x3f,
+       .krf = 0x04,
+       .agc_targ_val = 0x3e,
+};
+
+static int rtl2831u_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
+       struct rtl2830_config *rtl2830_config;
+       int ret;
+
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
+
+       switch (priv->tuner) {
+       case TUNER_RTL2830_QT1010:
+               rtl2830_config = &rtl28xxu_rtl2830_qt1010_config;
+               break;
+       case TUNER_RTL2830_MT2060:
+               rtl2830_config = &rtl28xxu_rtl2830_mt2060_config;
+               break;
+       case TUNER_RTL2830_MXL5005S:
+               rtl2830_config = &rtl28xxu_rtl2830_mxl5005s_config;
+               break;
+       default:
+               dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
+                               KBUILD_MODNAME, priv->tuner_name);
+               ret = -ENODEV;
+               goto err;
+       }
+
        /* attach demodulator */
-       adap->fe_adap[0].fe = dvb_attach(rtl2830_attach, rtl2830_config,
-               &adap->dev->i2c_adap);
-       if (adap->fe_adap[0].fe == NULL) {
+       adap->fe[0] = dvb_attach(rtl2830_attach, rtl2830_config, &d->i2c_adap);
+       if (!adap->fe[0]) {
                ret = -ENODEV;
                goto err;
        }
 
-       return ret;
+       return 0;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -399,13 +577,26 @@ static struct rtl2832_config rtl28xxu_rtl2832_fc0013_config = {
        .tuner = TUNER_RTL2832_FC0013
 };
 
+static struct rtl2832_config rtl28xxu_rtl2832_tua9001_config = {
+       .i2c_addr = 0x10, /* 0x20 */
+       .xtal = 28800000,
+       .tuner = TUNER_RTL2832_TUA9001,
+};
+
+static struct rtl2832_config rtl28xxu_rtl2832_e4000_config = {
+       .i2c_addr = 0x10, /* 0x20 */
+       .xtal = 28800000,
+       .tuner = TUNER_RTL2832_E4000,
+};
+
 static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
                int cmd, int arg)
 {
        int ret;
        u8 val;
 
-       deb_info("%s cmd=%d arg=%d\n", __func__, cmd, arg);
+       dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg);
+
        switch (cmd) {
        case FC_FE_CALLBACK_VHF_ENABLE:
                /* set output values */
@@ -428,250 +619,135 @@ static int rtl2832u_fc0012_tuner_callback(struct dvb_usb_device *d,
                goto err;
        }
        return 0;
-
 err:
-       err("%s: failed=%d\n", __func__, ret);
-
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-
-static int rtl2832u_fc0013_tuner_callback(struct dvb_usb_device *d,
+static int rtl2832u_tua9001_tuner_callback(struct dvb_usb_device *d,
                int cmd, int arg)
-{
-       /* TODO implement*/
-       return 0;
-}
-
-static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
-{
-       struct rtl28xxu_priv *priv = d->priv;
-
-       switch (priv->tuner) {
-       case TUNER_RTL2832_FC0012:
-               return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
-
-       case TUNER_RTL2832_FC0013:
-               return rtl2832u_fc0013_tuner_callback(d, cmd, arg);
-       default:
-               break;
-       }
-
-       return -ENODEV;
-}
-
-static int rtl2832u_frontend_callback(void *adapter_priv, int component,
-                                   int cmd, int arg)
-{
-       struct i2c_adapter *adap = adapter_priv;
-       struct dvb_usb_device *d = i2c_get_adapdata(adap);
-
-       switch (component) {
-       case DVB_FRONTEND_COMPONENT_TUNER:
-               return rtl2832u_tuner_callback(d, cmd, arg);
-       default:
-               break;
-       }
-
-       return -EINVAL;
-}
-
-
-
-
-static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
-       struct rtl28xxu_priv *priv = adap->dev->priv;
-       struct rtl2832_config *rtl2832_config;
-
-       u8 buf[2], val;
-       /* open RTL2832U/RTL2832 I2C gate */
-       struct rtl28xxu_req req_gate_open = {0x0120, 0x0011, 0x0001, "\x18"};
-       /* close RTL2832U/RTL2832 I2C gate */
-       struct rtl28xxu_req req_gate_close = {0x0120, 0x0011, 0x0001, "\x10"};
-       /* for FC0012 tuner probe */
-       struct rtl28xxu_req req_fc0012 = {0x00c6, CMD_I2C_RD, 1, buf};
-       /* for FC0013 tuner probe */
-       struct rtl28xxu_req req_fc0013 = {0x00c6, CMD_I2C_RD, 1, buf};
-       /* for MT2266 tuner probe */
-       struct rtl28xxu_req req_mt2266 = {0x00c0, CMD_I2C_RD, 1, buf};
-       /* for FC2580 tuner probe */
-       struct rtl28xxu_req req_fc2580 = {0x01ac, CMD_I2C_RD, 1, buf};
-       /* for MT2063 tuner probe */
-       struct rtl28xxu_req req_mt2063 = {0x00c0, CMD_I2C_RD, 1, buf};
-       /* for MAX3543 tuner probe */
-       struct rtl28xxu_req req_max3543 = {0x00c0, CMD_I2C_RD, 1, buf};
-       /* for TUA9001 tuner probe */
-       struct rtl28xxu_req req_tua9001 = {0x7ec0, CMD_I2C_RD, 2, buf};
-       /* for MXL5007T tuner probe */
-       struct rtl28xxu_req req_mxl5007t = {0xd9c0, CMD_I2C_RD, 1, buf};
-       /* for E4000 tuner probe */
-       struct rtl28xxu_req req_e4000 = {0x02c8, CMD_I2C_RD, 1, buf};
-       /* for TDA18272 tuner probe */
-       struct rtl28xxu_req req_tda18272 = {0x00c0, CMD_I2C_RD, 2, buf};
-
-       deb_info("%s:\n", __func__);
-
-
-       ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_DIR, &val);
-       if (ret)
-               goto err;
-
-       val &= 0xbf;
-
-       ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_DIR, val);
-       if (ret)
-               goto err;
-
-
-       /* enable as output GPIO3 and GPIO6*/
-       ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_EN, &val);
-       if (ret)
-               goto err;
-
-       val |= 0x48;
-
-       ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_EN, val);
-       if (ret)
-               goto err;
-
+       u8 val;
 
+       dev_dbg(&d->udev->dev, "%s: cmd=%d arg=%d\n", __func__, cmd, arg);
 
        /*
-        * Probe used tuner. We need to know used tuner before demod attach
-        * since there is some demod params needed to set according to tuner.
-        */
-
-       /* open demod I2C gate */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_open);
-       if (ret)
-               goto err;
+        * CEN     always enabled by hardware wiring
+        * RESETN  GPIO4
+        * RXEN    GPIO1
+        */
 
-       priv->tuner = TUNER_NONE;
+       switch (cmd) {
+       case TUA9001_CMD_RESETN:
+               if (arg)
+                       val = (1 << 4);
+               else
+                       val = (0 << 4);
 
-       /* check FC0012 ID register; reg=00 val=a1 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0012);
-       if (ret == 0 && buf[0] == 0xa1) {
-               priv->tuner = TUNER_RTL2832_FC0012;
-               rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
-               info("%s: FC0012 tuner found", __func__);
-               goto found;
-       }
+               ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x10);
+               if (ret)
+                       goto err;
+               break;
+       case TUA9001_CMD_RXEN:
+               if (arg)
+                       val = (1 << 1);
+               else
+                       val = (0 << 1);
 
-       /* check FC0013 ID register; reg=00 val=a3 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc0013);
-       if (ret == 0 && buf[0] == 0xa3) {
-               priv->tuner = TUNER_RTL2832_FC0013;
-               rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
-               info("%s: FC0013 tuner found", __func__);
-               goto found;
+               ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_VAL, val, 0x02);
+               if (ret)
+                       goto err;
+               break;
        }
 
-       /* check MT2266 ID register; reg=00 val=85 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2266);
-       if (ret == 0 && buf[0] == 0x85) {
-               priv->tuner = TUNER_RTL2832_MT2266;
-               /* TODO implement tuner */
-               info("%s: MT2266 tuner found", __func__);
-               goto unsupported;
-       }
+       return 0;
+err:
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
+       return ret;
+}
 
-       /* check FC2580 ID register; reg=01 val=56 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_fc2580);
-       if (ret == 0 && buf[0] == 0x56) {
-               priv->tuner = TUNER_RTL2832_FC2580;
-               /* TODO implement tuner */
-               info("%s: FC2580 tuner found", __func__);
-               goto unsupported;
-       }
+static int rtl2832u_tuner_callback(struct dvb_usb_device *d, int cmd, int arg)
+{
+       struct rtl28xxu_priv *priv = d->priv;
 
-       /* check MT2063 ID register; reg=00 val=9e || 9c */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_mt2063);
-       if (ret == 0 && (buf[0] == 0x9e || buf[0] == 0x9c)) {
-               priv->tuner = TUNER_RTL2832_MT2063;
-               /* TODO implement tuner */
-               info("%s: MT2063 tuner found", __func__);
-               goto unsupported;
+       switch (priv->tuner) {
+       case TUNER_RTL2832_FC0012:
+               return rtl2832u_fc0012_tuner_callback(d, cmd, arg);
+       case TUNER_RTL2832_TUA9001:
+               return rtl2832u_tua9001_tuner_callback(d, cmd, arg);
+       default:
+               break;
        }
 
-       /* check MAX3543 ID register; reg=00 val=38 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_max3543);
-       if (ret == 0 && buf[0] == 0x38) {
-               priv->tuner = TUNER_RTL2832_MAX3543;
-               /* TODO implement tuner */
-               info("%s: MAX3534 tuner found", __func__);
-               goto unsupported;
-       }
+       return 0;
+}
 
-       /* check TUA9001 ID register; reg=7e val=2328 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_tua9001);
-       if (ret == 0 && buf[0] == 0x23 && buf[1] == 0x28) {
-               priv->tuner = TUNER_RTL2832_TUA9001;
-               /* TODO implement tuner */
-               info("%s: TUA9001 tuner found", __func__);
-               goto unsupported;
-       }
+static int rtl2832u_frontend_callback(void *adapter_priv, int component,
+               int cmd, int arg)
+{
+       struct i2c_adapter *adap = adapter_priv;
+       struct dvb_usb_device *d = i2c_get_adapdata(adap);
 
-       /* check MXL5007R ID register; reg=d9 val=14 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_mxl5007t);
-       if (ret == 0 && buf[0] == 0x14) {
-               priv->tuner = TUNER_RTL2832_MXL5007T;
-               /* TODO implement tuner */
-               info("%s: MXL5007T tuner found", __func__);
-               goto unsupported;
-       }
+       dev_dbg(&d->udev->dev, "%s: component=%d cmd=%d arg=%d\n",
+                       __func__, component, cmd, arg);
 
-       /* check E4000 ID register; reg=02 val=40 */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_e4000);
-       if (ret == 0 && buf[0] == 0x40) {
-               priv->tuner = TUNER_RTL2832_E4000;
-               /* TODO implement tuner */
-               info("%s: E4000 tuner found", __func__);
-               goto unsupported;
+       switch (component) {
+       case DVB_FRONTEND_COMPONENT_TUNER:
+               return rtl2832u_tuner_callback(d, cmd, arg);
+       default:
+               break;
        }
 
-       /* check TDA18272 ID register; reg=00 val=c760  */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_tda18272);
-       if (ret == 0 && (buf[0] == 0xc7 || buf[1] == 0x60)) {
-               priv->tuner = TUNER_RTL2832_TDA18272;
-               /* TODO implement tuner */
-               info("%s: TDA18272 tuner found", __func__);
-               goto unsupported;
-       }
+       return 0;
+}
 
-unsupported:
-       /* close demod I2C gate */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
-       if (ret)
-               goto err;
+static int rtl2832u_frontend_attach(struct dvb_usb_adapter *adap)
+{
+       int ret;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
+       struct rtl2832_config *rtl2832_config;
 
-       /* tuner not found */
-       deb_info("No compatible tuner found");
-       ret = -ENODEV;
-       return ret;
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-found:
-       /* close demod I2C gate */
-       ret = rtl28xxu_ctrl_msg(adap->dev, &req_gate_close);
-       if (ret)
+       switch (priv->tuner) {
+       case TUNER_RTL2832_FC0012:
+               rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
+               break;
+       case TUNER_RTL2832_FC0013:
+               rtl2832_config = &rtl28xxu_rtl2832_fc0013_config;
+               break;
+       case TUNER_RTL2832_FC2580:
+               /* FIXME: do not abuse fc0012 settings */
+               rtl2832_config = &rtl28xxu_rtl2832_fc0012_config;
+               break;
+       case TUNER_RTL2832_TUA9001:
+               rtl2832_config = &rtl28xxu_rtl2832_tua9001_config;
+               break;
+       case TUNER_RTL2832_E4000:
+               rtl2832_config = &rtl28xxu_rtl2832_e4000_config;
+               break;
+       default:
+               dev_err(&d->udev->dev, "%s: unknown tuner=%s\n",
+                               KBUILD_MODNAME, priv->tuner_name);
+               ret = -ENODEV;
                goto err;
+       }
 
        /* attach demodulator */
-       adap->fe_adap[0].fe = dvb_attach(rtl2832_attach, rtl2832_config,
-               &adap->dev->i2c_adap);
-               if (adap->fe_adap[0].fe == NULL) {
-                       ret = -ENODEV;
-                       goto err;
-               }
-
-       /* set fe callbacks */
-       adap->fe_adap[0].fe->callback = rtl2832u_frontend_callback;
+       adap->fe[0] = dvb_attach(rtl2832_attach, rtl2832_config, &d->i2c_adap);
+       if (!adap->fe[0]) {
+               ret = -ENODEV;
+               goto err;
+       }
 
-       return ret;
+       /* set fe callback */
+       adap->fe[0]->callback = rtl2832u_frontend_callback;
 
+       return 0;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -704,32 +780,34 @@ static struct mxl5005s_config rtl28xxu_mxl5005s_config = {
 static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
-       struct rtl28xxu_priv *priv = adap->dev->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
        struct i2c_adapter *rtl2830_tuner_i2c;
        struct dvb_frontend *fe;
 
-       deb_info("%s:\n", __func__);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
        /* use rtl2830 driver I2C adapter, for more info see rtl2830 driver */
-       rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe_adap[0].fe);
+       rtl2830_tuner_i2c = rtl2830_get_tuner_i2c_adapter(adap->fe[0]);
 
        switch (priv->tuner) {
        case TUNER_RTL2830_QT1010:
-               fe = dvb_attach(qt1010_attach, adap->fe_adap[0].fe,
+               fe = dvb_attach(qt1010_attach, adap->fe[0],
                                rtl2830_tuner_i2c, &rtl28xxu_qt1010_config);
                break;
        case TUNER_RTL2830_MT2060:
-               fe = dvb_attach(mt2060_attach, adap->fe_adap[0].fe,
+               fe = dvb_attach(mt2060_attach, adap->fe[0],
                                rtl2830_tuner_i2c, &rtl28xxu_mt2060_config,
                                1220);
                break;
        case TUNER_RTL2830_MXL5005S:
-               fe = dvb_attach(mxl5005s_attach, adap->fe_adap[0].fe,
+               fe = dvb_attach(mxl5005s_attach, adap->fe[0],
                                rtl2830_tuner_i2c, &rtl28xxu_mxl5005s_config);
                break;
        default:
                fe = NULL;
-               err("unknown tuner=%d", priv->tuner);
+               dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
+                               priv->tuner);
        }
 
        if (fe == NULL) {
@@ -739,40 +817,77 @@ static int rtl2831u_tuner_attach(struct dvb_usb_adapter *adap)
 
        return 0;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
+static const struct e4000_config rtl2832u_e4000_config = {
+       .i2c_addr = 0x64,
+       .clock = 28800000,
+};
+
+static const struct fc2580_config rtl2832u_fc2580_config = {
+       .i2c_addr = 0x56,
+       .clock = 16384000,
+};
+
+static struct tua9001_config rtl2832u_tua9001_config = {
+       .i2c_addr = 0x60,
+};
+
 static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 {
        int ret;
-       struct rtl28xxu_priv *priv = adap->dev->priv;
+       struct dvb_usb_device *d = adap_to_d(adap);
+       struct rtl28xxu_priv *priv = d_to_priv(d);
        struct dvb_frontend *fe;
 
-       deb_info("%s:\n", __func__);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
        switch (priv->tuner) {
        case TUNER_RTL2832_FC0012:
-               fe = dvb_attach(fc0012_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
+               fe = dvb_attach(fc0012_attach, adap->fe[0],
+                       &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
 
                /* since fc0012 includs reading the signal strength delegate
                 * that to the tuner driver */
-               adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0].
-                               fe->ops.tuner_ops.get_rf_strength;
+               adap->fe[0]->ops.read_signal_strength =
+                               adap->fe[0]->ops.tuner_ops.get_rf_strength;
                return 0;
                break;
        case TUNER_RTL2832_FC0013:
-               fe = dvb_attach(fc0013_attach, adap->fe_adap[0].fe,
-                       &adap->dev->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
+               fe = dvb_attach(fc0013_attach, adap->fe[0],
+                       &d->i2c_adap, 0xc6>>1, 0, FC_XTAL_28_8_MHZ);
 
                /* fc0013 also supports signal strength reading */
-               adap->fe_adap[0].fe->ops.read_signal_strength = adap->fe_adap[0]
-                       .fe->ops.tuner_ops.get_rf_strength;
+               adap->fe[0]->ops.read_signal_strength =
+                               adap->fe[0]->ops.tuner_ops.get_rf_strength;
                return 0;
+       case TUNER_RTL2832_E4000:
+               fe = dvb_attach(e4000_attach, adap->fe[0], &d->i2c_adap,
+                               &rtl2832u_e4000_config);
+               break;
+       case TUNER_RTL2832_FC2580:
+               fe = dvb_attach(fc2580_attach, adap->fe[0], &d->i2c_adap,
+                               &rtl2832u_fc2580_config);
+               break;
+       case TUNER_RTL2832_TUA9001:
+               /* enable GPIO1 and GPIO4 as output */
+               ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_DIR, 0x00, 0x12);
+               if (ret)
+                       goto err;
+
+               ret = rtl28xx_wr_reg_mask(d, SYS_GPIO_OUT_EN, 0x12, 0x12);
+               if (ret)
+                       goto err;
+
+               fe = dvb_attach(tua9001_attach, adap->fe[0], &d->i2c_adap,
+                               &rtl2832u_tua9001_config);
+               break;
        default:
                fe = NULL;
-               err("unknown tuner=%d", priv->tuner);
+               dev_err(&d->udev->dev, "%s: unknown tuner=%d\n", KBUILD_MODNAME,
+                               priv->tuner);
        }
 
        if (fe == NULL) {
@@ -782,77 +897,50 @@ static int rtl2832u_tuner_attach(struct dvb_usb_adapter *adap)
 
        return 0;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-static int rtl2831u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
+static int rtl28xxu_init(struct dvb_usb_device *d)
 {
        int ret;
-       u8 buf[2], gpio;
+       u8 val;
 
-       deb_info("%s: onoff=%d\n", __func__, onoff);
+       dev_dbg(&d->udev->dev, "%s:\n", __func__);
 
-       ret = rtl28xx_rd_reg(adap->dev, SYS_GPIO_OUT_VAL, &gpio);
+       /* init USB endpoints */
+       ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
        if (ret)
                goto err;
 
-       if (onoff) {
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-               gpio |= 0x04; /* LED on */
-       } else {
-               buf[0] = 0x10; /* stall EPA */
-               buf[1] = 0x02; /* reset EPA */
-               gpio &= (~0x04); /* LED off */
-       }
-
-       ret = rtl28xx_wr_reg(adap->dev, SYS_GPIO_OUT_VAL, gpio);
+       /* enable DMA and Full Packet Mode*/
+       val |= 0x09;
+       ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
        if (ret)
                goto err;
 
-       ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
+       /* set EPA maximum packet size to 0x0200 */
+       ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
        if (ret)
                goto err;
 
-       return ret;
-err:
-       deb_info("%s: failed=%d\n", __func__, ret);
-       return ret;
-}
-
-static int rtl2832u_streaming_ctrl(struct dvb_usb_adapter *adap , int onoff)
-{
-       int ret;
-       u8 buf[2];
-
-       deb_info("%s: onoff=%d\n", __func__, onoff);
-
-
-       if (onoff) {
-               buf[0] = 0x00;
-               buf[1] = 0x00;
-       } else {
-               buf[0] = 0x10; /* stall EPA */
-               buf[1] = 0x02; /* reset EPA */
-       }
-
-       ret = rtl28xx_wr_regs(adap->dev, USB_EPA_CTL, buf, 2);
+       /* change EPA FIFO length */
+       ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
        if (ret)
                goto err;
 
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
 static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
 {
        int ret;
-       u8 gpio, sys0;
+       u8 gpio, sys0, epa_ctl[2];
 
-       deb_info("%s: onoff=%d\n", __func__, onoff);
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
 
        /* demod adc */
        ret = rtl28xx_rd_reg(d, SYS_SYS0, &sys0);
@@ -864,20 +952,28 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
        if (ret)
                goto err;
 
-       deb_info("%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
+       dev_dbg(&d->udev->dev, "%s: RD SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__,
+                       sys0, gpio);
 
        if (onoff) {
                gpio |= 0x01; /* GPIO0 = 1 */
                gpio &= (~0x10); /* GPIO4 = 0 */
+               gpio |= 0x04; /* GPIO2 = 1, LED on */
                sys0 = sys0 & 0x0f;
                sys0 |= 0xe0;
+               epa_ctl[0] = 0x00; /* clear stall */
+               epa_ctl[1] = 0x00; /* clear reset */
        } else {
                gpio &= (~0x01); /* GPIO0 = 0 */
                gpio |= 0x10; /* GPIO4 = 1 */
+               gpio &= (~0x04); /* GPIO2 = 1, LED off */
                sys0 = sys0 & (~0xc0);
+               epa_ctl[0] = 0x10; /* set stall */
+               epa_ctl[1] = 0x02; /* set reset */
        }
 
-       deb_info("%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__, sys0, gpio);
+       dev_dbg(&d->udev->dev, "%s: WR SYS0=%02x GPIO_OUT_VAL=%02x\n", __func__,
+                       sys0, gpio);
 
        /* demod adc */
        ret = rtl28xx_wr_reg(d, SYS_SYS0, sys0);
@@ -889,9 +985,17 @@ static int rtl2831u_power_ctrl(struct dvb_usb_device *d, int onoff)
        if (ret)
                goto err;
 
+       /* streaming EP: stall & reset */
+       ret = rtl28xx_wr_regs(d, USB_EPA_CTL, epa_ctl, 2);
+       if (ret)
+               goto err;
+
+       if (onoff)
+               usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81));
+
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -900,7 +1004,7 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
        int ret;
        u8 val;
 
-       deb_info("%s: onoff=%d\n", __func__, onoff);
+       dev_dbg(&d->udev->dev, "%s: onoff=%d\n", __func__, onoff);
 
        if (onoff) {
                /* set output values */
@@ -935,17 +1039,6 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
                /* bit 7 to 1 */
                val |= 0x80;
 
-               ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
-               if (ret)
-                       goto err;
-
-               /* demod HW reset */
-               ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL, &val);
-               if (ret)
-                       goto err;
-               /* bit 5 to 0 */
-               val &= 0xdf;
-
                ret = rtl28xx_wr_reg(d, SYS_DEMOD_CTL, val);
                if (ret)
                        goto err;
@@ -973,7 +1066,14 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
                if (ret)
                        goto err;
 
+               /* streaming EP: clear stall & reset */
+               ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x00\x00", 2);
+               if (ret)
+                       goto err;
 
+               ret = usb_clear_halt(d->udev, usb_rcvbulkpipe(d->udev, 0x81));
+               if (ret)
+                       goto err;
        } else {
                /* demod_ctl_1 */
                ret = rtl28xx_rd_reg(d, SYS_DEMOD_CTL1, &val);
@@ -1008,11 +1108,15 @@ static int rtl2832u_power_ctrl(struct dvb_usb_device *d, int onoff)
                if (ret)
                        goto err;
 
+               /* streaming EP: set stall & reset */
+               ret = rtl28xx_wr_regs(d, USB_EPA_CTL, "\x10\x02", 2);
+               if (ret)
+                       goto err;
        }
 
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
@@ -1085,10 +1189,21 @@ static int rtl2831u_rc_query(struct dvb_usb_device *d)
 
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
+static int rtl2831u_get_rc_config(struct dvb_usb_device *d,
+               struct dvb_usb_rc *rc)
+{
+       rc->map_name = RC_MAP_EMPTY;
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query = rtl2831u_rc_query;
+       rc->interval = 400;
+
+       return 0;
+}
+
 static int rtl2832u_rc_query(struct dvb_usb_device *d)
 {
        int ret, i;
@@ -1146,281 +1261,108 @@ static int rtl2832u_rc_query(struct dvb_usb_device *d)
 exit:
        return ret;
 err:
-       deb_info("%s: failed=%d\n", __func__, ret);
+       dev_dbg(&d->udev->dev, "%s: failed=%d\n", __func__, ret);
        return ret;
 }
 
-enum rtl28xxu_usb_table_entry {
-       RTL2831U_0BDA_2831,
-       RTL2831U_14AA_0160,
-       RTL2831U_14AA_0161,
-       RTL2832U_0CCD_00A9,
-       RTL2832U_1F4D_B803,
-       RTL2832U_0CCD_00B3,
-};
-
-static struct usb_device_id rtl28xxu_table[] = {
-       /* RTL2831U */
-       [RTL2831U_0BDA_2831] = {
-               USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U)},
-       [RTL2831U_14AA_0160] = {
-               USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT)},
-       [RTL2831U_14AA_0161] = {
-               USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2)},
-
-       /* RTL2832U */
-       [RTL2832U_0CCD_00A9] = {
-               USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1)},
-       [RTL2832U_1F4D_B803] = {
-               USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT)},
-       [RTL2832U_0CCD_00B3] = {
-               USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK)},
-       {} /* terminating entry */
-};
-
-MODULE_DEVICE_TABLE(usb, rtl28xxu_table);
-
-static struct dvb_usb_device_properties rtl28xxu_properties[] = {
-       {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct rtl28xxu_priv),
-
-               .num_adapters = 1,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = rtl2831u_frontend_attach,
-                                               .tuner_attach    = rtl2831u_tuner_attach,
-                                               .streaming_ctrl  = rtl2831u_streaming_ctrl,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x81,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = 8*512,
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
+static int rtl2832u_get_rc_config(struct dvb_usb_device *d,
+               struct dvb_usb_rc *rc)
+{
+       rc->map_name = RC_MAP_EMPTY;
+       rc->allowed_protos = RC_TYPE_NEC;
+       rc->query = rtl2832u_rc_query;
+       rc->interval = 400;
 
-               .power_ctrl = rtl2831u_power_ctrl,
+       return 0;
+}
 
-               .rc.core = {
-                       .protocol       = RC_TYPE_NEC,
-                       .module_name    = "rtl28xxu",
-                       .rc_query       = rtl2831u_rc_query,
-                       .rc_interval    = 400,
-                       .allowed_protos = RC_TYPE_NEC,
-                       .rc_codes       = RC_MAP_EMPTY,
+static const struct dvb_usb_device_properties rtl2831u_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct rtl28xxu_priv),
+
+       .power_ctrl = rtl2831u_power_ctrl,
+       .i2c_algo = &rtl28xxu_i2c_algo,
+       .read_config = rtl2831u_read_config,
+       .frontend_attach = rtl2831u_frontend_attach,
+       .tuner_attach = rtl2831u_tuner_attach,
+       .init = rtl28xxu_init,
+       .get_rc_config = rtl2831u_get_rc_config,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512),
                },
-
-               .i2c_algo = &rtl28xxu_i2c_algo,
-
-               .num_device_descs = 2,
-               .devices = {
-                       {
-                               .name = "Realtek RTL2831U reference design",
-                               .warm_ids = {
-                                       &rtl28xxu_table[RTL2831U_0BDA_2831],
-                               },
-                       },
-                       {
-                               .name = "Freecom USB2.0 DVB-T",
-                               .warm_ids = {
-                                       &rtl28xxu_table[RTL2831U_14AA_0160],
-                                       &rtl28xxu_table[RTL2831U_14AA_0161],
-                               },
-                       },
-               }
        },
-       {
-               .caps = DVB_USB_IS_AN_I2C_ADAPTER,
-
-               .usb_ctrl = DEVICE_SPECIFIC,
-               .no_reconnect = 1,
-
-               .size_of_priv = sizeof(struct rtl28xxu_priv),
-
-               .num_adapters = 1,
-               .adapter = {
-                       {
-                               .num_frontends = 1,
-                               .fe = {
-                                       {
-                                               .frontend_attach = rtl2832u_frontend_attach,
-                                               .tuner_attach    = rtl2832u_tuner_attach,
-                                               .streaming_ctrl  = rtl2832u_streaming_ctrl,
-                                               .stream = {
-                                                       .type = USB_BULK,
-                                                       .count = 6,
-                                                       .endpoint = 0x81,
-                                                       .u = {
-                                                               .bulk = {
-                                                                       .buffersize = 8*512,
-                                                               }
-                                                       }
-                                               }
-                                       }
-                               }
-                       }
-               },
-
-               .power_ctrl = rtl2832u_power_ctrl,
+};
 
-               .rc.core = {
-                       .protocol       = RC_TYPE_NEC,
-                       .module_name    = "rtl28xxu",
-                       .rc_query       = rtl2832u_rc_query,
-                       .rc_interval    = 400,
-                       .allowed_protos = RC_TYPE_NEC,
-                       .rc_codes       = RC_MAP_EMPTY,
+static const struct dvb_usb_device_properties rtl2832u_props = {
+       .driver_name = KBUILD_MODNAME,
+       .owner = THIS_MODULE,
+       .adapter_nr = adapter_nr,
+       .size_of_priv = sizeof(struct rtl28xxu_priv),
+
+       .power_ctrl = rtl2832u_power_ctrl,
+       .i2c_algo = &rtl28xxu_i2c_algo,
+       .read_config = rtl2832u_read_config,
+       .frontend_attach = rtl2832u_frontend_attach,
+       .tuner_attach = rtl2832u_tuner_attach,
+       .init = rtl28xxu_init,
+       .get_rc_config = rtl2832u_get_rc_config,
+
+       .num_adapters = 1,
+       .adapter = {
+               {
+                       .stream = DVB_USB_STREAM_BULK(0x81, 6, 8 * 512),
                },
-
-               .i2c_algo = &rtl28xxu_i2c_algo,
-
-               .num_device_descs = 3,
-               .devices = {
-                       {
-                               .name = "Terratec Cinergy T Stick Black",
-                               .warm_ids = {
-                                       &rtl28xxu_table[RTL2832U_0CCD_00A9],
-                               },
-                       },
-                       {
-                               .name = "G-Tek Electronics Group Lifeview LV5TDLX DVB-T",
-                               .warm_ids = {
-                                       &rtl28xxu_table[RTL2832U_1F4D_B803],
-                               },
-                       },
-                       {
-                               .name = "NOXON DAB/DAB+ USB dongle",
-                               .warm_ids = {
-                                       &rtl28xxu_table[RTL2832U_0CCD_00B3],
-                               },
-                       },
-               }
        },
-
 };
 
-static int rtl28xxu_probe(struct usb_interface *intf,
-               const struct usb_device_id *id)
-{
-       int ret, i;
-       u8 val;
-       int properties_count = ARRAY_SIZE(rtl28xxu_properties);
-       struct dvb_usb_device *d;
-       struct usb_device *udev;
-       bool found;
-
-       deb_info("%s: interface=%d\n", __func__,
-               intf->cur_altsetting->desc.bInterfaceNumber);
-
-       if (intf->cur_altsetting->desc.bInterfaceNumber != 0)
-               return 0;
-
-       /* Dynamic USB ID support. Replaces first device ID with current one .*/
-       udev = interface_to_usbdev(intf);
-
-       for (i = 0, found = false; i < ARRAY_SIZE(rtl28xxu_table) - 1; i++) {
-               if (rtl28xxu_table[i].idVendor ==
-                               le16_to_cpu(udev->descriptor.idVendor) &&
-                               rtl28xxu_table[i].idProduct ==
-                               le16_to_cpu(udev->descriptor.idProduct)) {
-                       found = true;
-                       break;
-               }
-       }
-
-       if (!found) {
-               deb_info("%s: using dynamic ID %04x:%04x\n", __func__,
-                               le16_to_cpu(udev->descriptor.idVendor),
-                               le16_to_cpu(udev->descriptor.idProduct));
-               rtl28xxu_properties[0].devices[0].warm_ids[0]->idVendor =
-                               le16_to_cpu(udev->descriptor.idVendor);
-               rtl28xxu_properties[0].devices[0].warm_ids[0]->idProduct =
-                               le16_to_cpu(udev->descriptor.idProduct);
-       }
-
-       for (i = 0; i < properties_count; i++) {
-               ret = dvb_usb_device_init(intf, &rtl28xxu_properties[i],
-                               THIS_MODULE, &d, adapter_nr);
-               if (ret == 0 || ret != -ENODEV)
-                       break;
-       }
-
-       if (ret)
-               goto err;
-
-
-       /* init USB endpoints */
-       ret = rtl28xx_rd_reg(d, USB_SYSCTL_0, &val);
-       if (ret)
-                       goto err;
-
-       /* enable DMA and Full Packet Mode*/
-       val |= 0x09;
-       ret = rtl28xx_wr_reg(d, USB_SYSCTL_0, val);
-       if (ret)
-               goto err;
-
-       /* set EPA maximum packet size to 0x0200 */
-       ret = rtl28xx_wr_regs(d, USB_EPA_MAXPKT, "\x00\x02\x00\x00", 4);
-       if (ret)
-               goto err;
-
-       /* change EPA FIFO length */
-       ret = rtl28xx_wr_regs(d, USB_EPA_FIFO_CFG, "\x14\x00\x00\x00", 4);
-       if (ret)
-               goto err;
-
-       return ret;
-err:
-       deb_info("%s: failed=%d\n", __func__, ret);
-       return ret;
-}
-
-static struct usb_driver rtl28xxu_driver = {
-       .name       = "dvb_usb_rtl28xxu",
-       .probe      = rtl28xxu_probe,
-       .disconnect = dvb_usb_device_exit,
-       .id_table   = rtl28xxu_table,
+static const struct usb_device_id rtl28xxu_id_table[] = {
+       { DVB_USB_DEVICE(USB_VID_REALTEK, USB_PID_REALTEK_RTL2831U,
+               &rtl2831u_props, "Realtek RTL2831U reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT,
+               &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) },
+       { DVB_USB_DEVICE(USB_VID_WIDEVIEW, USB_PID_FREECOM_DVBT_2,
+               &rtl2831u_props, "Freecom USB2.0 DVB-T", NULL) },
+
+       { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2832,
+               &rtl2832u_props, "Realtek RTL2832U reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_REALTEK, 0x2838,
+               &rtl2832u_props, "Realtek RTL2832U reference design", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_TERRATEC_CINERGY_T_STICK_BLACK_REV1,
+               &rtl2832u_props, "Terratec Cinergy T Stick Black", NULL) },
+       { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_DELOCK_USB2_DVBT,
+               &rtl2832u_props, "G-Tek Electronics Group Lifeview LV5TDLX DVB-T", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, USB_PID_NOXON_DAB_STICK,
+               &rtl2832u_props, "NOXON DAB/DAB+ USB dongle", NULL) },
+       { DVB_USB_DEVICE(USB_VID_GTEK, USB_PID_TREKSTOR_TERRES_2_0,
+               &rtl2832u_props, "Trekstor DVB-T Stick Terres 2.0", NULL) },
+       { DVB_USB_DEVICE(USB_VID_DEXATEK, 0x1101,
+               &rtl2832u_props, "Dexatek DK DVB-T Dongle", NULL) },
+       { DVB_USB_DEVICE(USB_VID_LEADTEK, 0x6680,
+               &rtl2832u_props, "DigitalNow Quad DVB-T Receiver", NULL) },
+       { DVB_USB_DEVICE(USB_VID_TERRATEC, 0x00d3,
+               &rtl2832u_props, "TerraTec Cinergy T Stick RC (Rev. 3)", NULL) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, rtl28xxu_id_table);
+
+static struct usb_driver rtl28xxu_usb_driver = {
+       .name = KBUILD_MODNAME,
+       .id_table = rtl28xxu_id_table,
+       .probe = dvb_usbv2_probe,
+       .disconnect = dvb_usbv2_disconnect,
+       .suspend = dvb_usbv2_suspend,
+       .resume = dvb_usbv2_resume,
+       .reset_resume = dvb_usbv2_reset_resume,
+       .no_dynamic_id = 1,
+       .soft_unbind = 1,
 };
 
-/* module stuff */
-static int __init rtl28xxu_module_init(void)
-{
-       int ret;
-
-       deb_info("%s:\n", __func__);
-
-       ret = usb_register(&rtl28xxu_driver);
-       if (ret)
-               err("usb_register failed=%d", ret);
-
-       return ret;
-}
-
-static void __exit rtl28xxu_module_exit(void)
-{
-       deb_info("%s:\n", __func__);
-
-       /* deregister this driver from the USB subsystem */
-       usb_deregister(&rtl28xxu_driver);
-}
-
-module_init(rtl28xxu_module_init);
-module_exit(rtl28xxu_module_exit);
+module_usb_driver(rtl28xxu_usb_driver);
 
 MODULE_DESCRIPTION("Realtek RTL28xxU DVB USB driver");
 MODULE_AUTHOR("Antti Palosaari <crope@iki.fi>");
similarity index 91%
rename from drivers/media/dvb/dvb-usb/rtl28xxu.h
rename to drivers/media/usb/dvb-usb-v2/rtl28xxu.h
index 90f3bb4f4c0ec2c6fdaf8e8763e0d6e4d3819eb2..2f3af2d3b6ce5ec365aab25093ea9b3c1994dcef 100644 (file)
 #ifndef RTL28XXU_H
 #define RTL28XXU_H
 
-#define DVB_USB_LOG_PREFIX "rtl28xxu"
-#include "dvb-usb.h"
-
-#define deb_info(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x01, args)
-#define deb_rc(args...)   dprintk(dvb_usb_rtl28xxu_debug, 0x02, args)
-#define deb_xfer(args...) dprintk(dvb_usb_rtl28xxu_debug, 0x04, args)
-#define deb_reg(args...)  dprintk(dvb_usb_rtl28xxu_debug, 0x08, args)
-#define deb_i2c(args...)  dprintk(dvb_usb_rtl28xxu_debug, 0x10, args)
-#define deb_fw(args...)   dprintk(dvb_usb_rtl28xxu_debug, 0x20, args)
-
-#define deb_dump(r, t, v, i, b, l, func) { \
-       int loop_; \
-       func("%02x %02x %02x %02x %02x %02x %02x %02x", \
-               t, r, v & 0xff, v >> 8, i & 0xff, i >> 8, l & 0xff, l >> 8); \
-       if (t == (USB_TYPE_VENDOR | USB_DIR_OUT)) \
-               func(" >>> "); \
-       else \
-               func(" <<< "); \
-       for (loop_ = 0; loop_ < l; loop_++) \
-               func("%02x ", b[loop_]); \
-       func("\n");\
-}
+#include "dvb_usb.h"
 
 /*
  * USB commands
@@ -74,6 +53,7 @@
 struct rtl28xxu_priv {
        u8 chip_id;
        u8 tuner;
+       char *tuner_name;
        u8 page; /* integrated demod active register page */
        bool rc_active;
 };
@@ -84,14 +64,15 @@ enum rtl28xxu_chip_id {
        CHIP_ID_RTL2832U,
 };
 
+/* XXX: Hack. This must be keep sync with rtl2832 demod driver. */
 enum rtl28xxu_tuner {
        TUNER_NONE,
 
-       TUNER_RTL2830_QT1010,
+       TUNER_RTL2830_QT1010          = 0x10,
        TUNER_RTL2830_MT2060,
        TUNER_RTL2830_MXL5005S,
 
-       TUNER_RTL2832_MT2266,
+       TUNER_RTL2832_MT2266          = 0x20,
        TUNER_RTL2832_FC2580,
        TUNER_RTL2832_MT2063,
        TUNER_RTL2832_MAX3543,
diff --git a/drivers/media/usb/dvb-usb-v2/usb_urb.c b/drivers/media/usb/dvb-usb-v2/usb_urb.c
new file mode 100644 (file)
index 0000000..5989b65
--- /dev/null
@@ -0,0 +1,358 @@
+/* usb-urb.c is part of the DVB USB library.
+ *
+ * Copyright (C) 2004-6 Patrick Boettcher (patrick.boettcher@desy.de)
+ * see dvb-usb-init.c for copyright information.
+ *
+ * This file keeps functions for initializing and handling the
+ * BULK and ISOC USB data transfers in a generic way.
+ * Can be used for DVB-only and also, that's the plan, for
+ * Hybrid USB devices (analog and DVB).
+ */
+#include "dvb_usb_common.h"
+
+/* URB stuff for streaming */
+
+int usb_urb_reconfig(struct usb_data_stream *stream,
+               struct usb_data_stream_properties *props);
+
+static void usb_urb_complete(struct urb *urb)
+{
+       struct usb_data_stream *stream = urb->context;
+       int ptype = usb_pipetype(urb->pipe);
+       int i;
+       u8 *b;
+
+       dev_dbg_ratelimited(&stream->udev->dev, "%s: %s urb completed " \
+                       "status=%d length=%d/%d pack_num=%d errors=%d\n",
+                       __func__, ptype == PIPE_ISOCHRONOUS ? "isoc" : "bulk",
+                       urb->status, urb->actual_length,
+                       urb->transfer_buffer_length,
+                       urb->number_of_packets, urb->error_count);
+
+       switch (urb->status) {
+       case 0:         /* success */
+       case -ETIMEDOUT:    /* NAK */
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               return;
+       default:        /* error */
+               dev_dbg_ratelimited(&stream->udev->dev,
+                               "%s: urb completition failed=%d\n",
+                               __func__, urb->status);
+               break;
+       }
+
+       b = (u8 *) urb->transfer_buffer;
+       switch (ptype) {
+       case PIPE_ISOCHRONOUS:
+               for (i = 0; i < urb->number_of_packets; i++) {
+                       if (urb->iso_frame_desc[i].status != 0)
+                               dev_dbg(&stream->udev->dev, "%s: iso frame " \
+                                               "descriptor has an error=%d\n",
+                                               __func__,
+                                               urb->iso_frame_desc[i].status);
+                       else if (urb->iso_frame_desc[i].actual_length > 0)
+                               stream->complete(stream,
+                                       b + urb->iso_frame_desc[i].offset,
+                                       urb->iso_frame_desc[i].actual_length);
+
+                       urb->iso_frame_desc[i].status = 0;
+                       urb->iso_frame_desc[i].actual_length = 0;
+               }
+               break;
+       case PIPE_BULK:
+               if (urb->actual_length > 0)
+                       stream->complete(stream, b, urb->actual_length);
+               break;
+       default:
+               dev_err(&stream->udev->dev, "%s: unknown endpoint type in " \
+                               "completition handler\n", KBUILD_MODNAME);
+               return;
+       }
+       usb_submit_urb(urb, GFP_ATOMIC);
+}
+
+int usb_urb_killv2(struct usb_data_stream *stream)
+{
+       int i;
+       for (i = 0; i < stream->urbs_submitted; i++) {
+               dev_dbg(&stream->udev->dev, "%s: kill urb=%d\n", __func__, i);
+               /* stop the URB */
+               usb_kill_urb(stream->urb_list[i]);
+       }
+       stream->urbs_submitted = 0;
+       return 0;
+}
+
+int usb_urb_submitv2(struct usb_data_stream *stream,
+               struct usb_data_stream_properties *props)
+{
+       int i, ret;
+
+       if (props) {
+               ret = usb_urb_reconfig(stream, props);
+               if (ret < 0)
+                       return ret;
+       }
+
+       for (i = 0; i < stream->urbs_initialized; i++) {
+               dev_dbg(&stream->udev->dev, "%s: submit urb=%d\n", __func__, i);
+               ret = usb_submit_urb(stream->urb_list[i], GFP_ATOMIC);
+               if (ret) {
+                       dev_err(&stream->udev->dev, "%s: could not submit " \
+                                       "urb no. %d - get them all back\n",
+                                       KBUILD_MODNAME, i);
+                       usb_urb_killv2(stream);
+                       return ret;
+               }
+               stream->urbs_submitted++;
+       }
+       return 0;
+}
+
+int usb_urb_free_urbs(struct usb_data_stream *stream)
+{
+       int i;
+
+       usb_urb_killv2(stream);
+
+       for (i = stream->urbs_initialized - 1; i >= 0; i--) {
+               if (stream->urb_list[i]) {
+                       dev_dbg(&stream->udev->dev, "%s: free urb=%d\n",
+                                       __func__, i);
+                       /* free the URBs */
+                       usb_free_urb(stream->urb_list[i]);
+               }
+       }
+       stream->urbs_initialized = 0;
+
+       return 0;
+}
+
+static int usb_urb_alloc_bulk_urbs(struct usb_data_stream *stream)
+{
+       int i, j;
+
+       /* allocate the URBs */
+       for (i = 0; i < stream->props.count; i++) {
+               dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+               stream->urb_list[i] = usb_alloc_urb(0, GFP_ATOMIC);
+               if (!stream->urb_list[i]) {
+                       dev_dbg(&stream->udev->dev, "%s: failed\n", __func__);
+                       for (j = 0; j < i; j++)
+                               usb_free_urb(stream->urb_list[j]);
+                       return -ENOMEM;
+               }
+               usb_fill_bulk_urb(stream->urb_list[i],
+                               stream->udev,
+                               usb_rcvbulkpipe(stream->udev,
+                                               stream->props.endpoint),
+                               stream->buf_list[i],
+                               stream->props.u.bulk.buffersize,
+                               usb_urb_complete, stream);
+
+               stream->urb_list[i]->transfer_flags = URB_NO_TRANSFER_DMA_MAP;
+               stream->urb_list[i]->transfer_dma = stream->dma_addr[i];
+               stream->urbs_initialized++;
+       }
+       return 0;
+}
+
+static int usb_urb_alloc_isoc_urbs(struct usb_data_stream *stream)
+{
+       int i, j;
+
+       /* allocate the URBs */
+       for (i = 0; i < stream->props.count; i++) {
+               struct urb *urb;
+               int frame_offset = 0;
+               dev_dbg(&stream->udev->dev, "%s: alloc urb=%d\n", __func__, i);
+               stream->urb_list[i] = usb_alloc_urb(
+                               stream->props.u.isoc.framesperurb, GFP_ATOMIC);
+               if (!stream->urb_list[i]) {
+                       dev_dbg(&stream->udev->dev, "%s: failed\n", __func__);
+                       for (j = 0; j < i; j++)
+                               usb_free_urb(stream->urb_list[j]);
+                       return -ENOMEM;
+               }
+
+               urb = stream->urb_list[i];
+
+               urb->dev = stream->udev;
+               urb->context = stream;
+               urb->complete = usb_urb_complete;
+               urb->pipe = usb_rcvisocpipe(stream->udev,
+                               stream->props.endpoint);
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+               urb->interval = stream->props.u.isoc.interval;
+               urb->number_of_packets = stream->props.u.isoc.framesperurb;
+               urb->transfer_buffer_length = stream->props.u.isoc.framesize *
+                               stream->props.u.isoc.framesperurb;
+               urb->transfer_buffer = stream->buf_list[i];
+               urb->transfer_dma = stream->dma_addr[i];
+
+               for (j = 0; j < stream->props.u.isoc.framesperurb; j++) {
+                       urb->iso_frame_desc[j].offset = frame_offset;
+                       urb->iso_frame_desc[j].length =
+                                       stream->props.u.isoc.framesize;
+                       frame_offset += stream->props.u.isoc.framesize;
+               }
+
+               stream->urbs_initialized++;
+       }
+       return 0;
+}
+
+int usb_free_stream_buffers(struct usb_data_stream *stream)
+{
+       if (stream->state & USB_STATE_URB_BUF) {
+               while (stream->buf_num) {
+                       stream->buf_num--;
+                       dev_dbg(&stream->udev->dev, "%s: free buf=%d\n",
+                               __func__, stream->buf_num);
+                       usb_free_coherent(stream->udev, stream->buf_size,
+                                         stream->buf_list[stream->buf_num],
+                                         stream->dma_addr[stream->buf_num]);
+               }
+       }
+
+       stream->state &= ~USB_STATE_URB_BUF;
+
+       return 0;
+}
+
+int usb_alloc_stream_buffers(struct usb_data_stream *stream, int num,
+               unsigned long size)
+{
+       stream->buf_num = 0;
+       stream->buf_size = size;
+
+       dev_dbg(&stream->udev->dev, "%s: all in all I will use %lu bytes for " \
+                       "streaming\n", __func__,  num * size);
+
+       for (stream->buf_num = 0; stream->buf_num < num; stream->buf_num++) {
+               stream->buf_list[stream->buf_num] = usb_alloc_coherent(
+                               stream->udev, size, GFP_ATOMIC,
+                               &stream->dma_addr[stream->buf_num]);
+               if (!stream->buf_list[stream->buf_num]) {
+                       dev_dbg(&stream->udev->dev, "%s: alloc buf=%d failed\n",
+                                       __func__, stream->buf_num);
+                       usb_free_stream_buffers(stream);
+                       return -ENOMEM;
+               }
+
+               dev_dbg(&stream->udev->dev, "%s: alloc buf=%d %p (dma %llu)\n",
+                               __func__, stream->buf_num,
+                               stream->buf_list[stream->buf_num],
+                               (long long)stream->dma_addr[stream->buf_num]);
+               memset(stream->buf_list[stream->buf_num], 0, size);
+               stream->state |= USB_STATE_URB_BUF;
+       }
+
+       return 0;
+}
+
+int usb_urb_reconfig(struct usb_data_stream *stream,
+               struct usb_data_stream_properties *props)
+{
+       int buf_size;
+
+       if (!props)
+               return 0;
+
+       /* check allocated buffers are large enough for the request */
+       if (props->type == USB_BULK) {
+               buf_size = stream->props.u.bulk.buffersize;
+       } else if (props->type == USB_ISOC) {
+               buf_size = props->u.isoc.framesize * props->u.isoc.framesperurb;
+       } else {
+               dev_err(&stream->udev->dev, "%s: invalid endpoint type=%d\n",
+                               KBUILD_MODNAME, props->type);
+               return -EINVAL;
+       }
+
+       if (stream->buf_num < props->count || stream->buf_size < buf_size) {
+               dev_err(&stream->udev->dev, "%s: cannot reconfigure as " \
+                               "allocated buffers are too small\n",
+                               KBUILD_MODNAME);
+               return -EINVAL;
+       }
+
+       /* check if all fields are same */
+       if (stream->props.type == props->type &&
+                       stream->props.count == props->count &&
+                       stream->props.endpoint == props->endpoint) {
+               if (props->type == USB_BULK &&
+                               props->u.bulk.buffersize ==
+                               stream->props.u.bulk.buffersize)
+                       return 0;
+               else if (props->type == USB_ISOC &&
+                               props->u.isoc.framesperurb ==
+                               stream->props.u.isoc.framesperurb &&
+                               props->u.isoc.framesize ==
+                               stream->props.u.isoc.framesize &&
+                               props->u.isoc.interval ==
+                               stream->props.u.isoc.interval)
+                       return 0;
+       }
+
+       dev_dbg(&stream->udev->dev, "%s: re-alloc urbs\n", __func__);
+
+       usb_urb_free_urbs(stream);
+       memcpy(&stream->props, props, sizeof(*props));
+       if (props->type == USB_BULK)
+               return usb_urb_alloc_bulk_urbs(stream);
+       else if (props->type == USB_ISOC)
+               return usb_urb_alloc_isoc_urbs(stream);
+
+       return 0;
+}
+
+int usb_urb_initv2(struct usb_data_stream *stream,
+               const struct usb_data_stream_properties *props)
+{
+       int ret;
+
+       if (!stream || !props)
+               return -EINVAL;
+
+       memcpy(&stream->props, props, sizeof(*props));
+
+       if (!stream->complete) {
+               dev_err(&stream->udev->dev, "%s: there is no data callback - " \
+                               "this doesn't make sense\n", KBUILD_MODNAME);
+               return -EINVAL;
+       }
+
+       switch (stream->props.type) {
+       case USB_BULK:
+               ret = usb_alloc_stream_buffers(stream, stream->props.count,
+                               stream->props.u.bulk.buffersize);
+               if (ret < 0)
+                       return ret;
+
+               return usb_urb_alloc_bulk_urbs(stream);
+       case USB_ISOC:
+               ret = usb_alloc_stream_buffers(stream, stream->props.count,
+                               stream->props.u.isoc.framesize *
+                               stream->props.u.isoc.framesperurb);
+               if (ret < 0)
+                       return ret;
+
+               return usb_urb_alloc_isoc_urbs(stream);
+       default:
+               dev_err(&stream->udev->dev, "%s: unknown urb-type for data " \
+                               "transfer\n", KBUILD_MODNAME);
+               return -EINVAL;
+       }
+}
+
+int usb_urb_exitv2(struct usb_data_stream *stream)
+{
+       usb_urb_free_urbs(stream);
+       usb_free_stream_buffers(stream);
+
+       return 0;
+}
diff --git a/drivers/media/usb/dvb-usb/Kconfig b/drivers/media/usb/dvb-usb/Kconfig
new file mode 100644 (file)
index 0000000..fa0b293
--- /dev/null
@@ -0,0 +1,313 @@
+config DVB_USB
+       tristate "Support for various USB DVB devices"
+       depends on DVB_CORE && USB && I2C && RC_CORE
+       help
+         By enabling this you will be able to choose the various supported
+         USB1.1 and USB2.0 DVB devices.
+
+         Almost every USB device needs a firmware, please look into
+         <file:Documentation/dvb/README.dvb-usb>.
+
+         For a complete list of supported USB devices see the LinuxTV DVB Wiki:
+         <http://www.linuxtv.org/wiki/index.php/DVB_USB>
+
+         Say Y if you own a USB DVB device.
+
+config DVB_USB_DEBUG
+       bool "Enable extended debug support for all DVB-USB devices"
+       depends on DVB_USB
+       help
+         Say Y if you want to enable debugging. See modinfo dvb-usb (and the
+         appropriate drivers) for debug levels.
+
+config DVB_USB_A800
+       tristate "AVerMedia AverTV DVB-T USB 2.0 (A800)"
+       depends on DVB_USB
+       select DVB_DIB3000MC
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the AVerMedia AverTV DVB-T USB 2.0 (A800) receiver.
+
+config DVB_USB_DIBUSB_MB
+       tristate "DiBcom USB DVB-T devices (based on the DiB3000M-B) (see help for device list)"
+       depends on DVB_USB
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB3000MB
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for USB 1.1 and 2.0 DVB-T receivers based on reference designs made by
+         DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-B demodulator.
+
+         For an up-to-date list of devices supported by this driver, have a look
+         on the Linux-DVB Wiki at www.linuxtv.org.
+
+         Say Y if you own such a device and want to use it. You should build it as
+         a module.
+
+config DVB_USB_DIBUSB_MB_FAULTY
+       bool "Support faulty USB IDs"
+       depends on DVB_USB_DIBUSB_MB
+       help
+         Support for faulty USB IDs due to an invalid EEPROM on some Artec devices.
+
+config DVB_USB_DIBUSB_MC
+       tristate "DiBcom USB DVB-T devices (based on the DiB3000M-C/P) (see help for device list)"
+       depends on DVB_USB
+       select DVB_DIB3000MC
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for USB2.0 DVB-T receivers based on reference designs made by
+         DiBcom (<http://www.dibcom.fr>) equipped with a DiB3000M-C/P demodulator.
+
+         For an up-to-date list of devices supported by this driver, have a look
+         on the Linux-DVB Wiki at www.linuxtv.org.
+
+         Say Y if you own such a device and want to use it. You should build it as
+         a module.
+
+config DVB_USB_DIB0700
+       tristate "DiBcom DiB0700 USB DVB devices (see help for supported devices)"
+       depends on DVB_USB
+       select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB7000M if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB8000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB3000MC if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT3305 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUNER_DIB0090 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2266 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC2028 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC5000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_XC4000 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MXL5007T if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for USB2.0/1.1 DVB receivers based on the DiB0700 USB bridge. The
+         USB bridge is also present in devices having the DiB7700 DVB-T-USB
+         silicon. This chip can be found in devices offered by Hauppauge,
+         Avermedia and other big and small companies.
+
+         For an up-to-date list of devices supported by this driver, have a look
+         on the LinuxTV Wiki at www.linuxtv.org.
+
+         Say Y if you own such a device and want to use it. You should build it as
+         a module.
+
+config DVB_USB_UMT_010
+       tristate "HanfTek UMT-010 DVB-T USB2.0 support"
+       depends on DVB_USB
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB3000MC
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the HanfTek UMT-010 USB2.0 stick-sized DVB-T receiver.
+
+config DVB_USB_CXUSB
+       tristate "Conexant USB2.0 hybrid reference design support"
+       depends on DVB_USB
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX22702 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DIB7000P if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TUNER_DIB0070 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ATBM8830 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LGS8GXX 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
+       help
+         Say Y here to support the Conexant USB2.0 hybrid reference design.
+         Currently, only DVB and ATSC modes are supported, analog mode
+         shall be added in the future. Devices that require this module:
+
+         Medion MD95700 hybrid USB2.0 device.
+         DViCO FusionHDTV (Bluebird) USB2.0 devices
+
+config DVB_USB_M920X
+       tristate "Uli m920x DVB-T USB2.0 support"
+       depends on DVB_USB
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA827X if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the MSI Mega Sky 580 USB2.0 DVB-T receiver.
+         Currently, only devices with a product id of
+         "DTV USB MINI" (in cold state) are supported.
+         Firmware required.
+
+config DVB_USB_DIGITV
+       tristate "Nebula Electronics uDigiTV DVB-T USB2.0 support"
+       depends on DVB_USB
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_NXT6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT352 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Nebula Electronics uDigitV USB2.0 DVB-T receiver.
+
+config DVB_USB_VP7045
+       tristate "TwinhanDTV Alpha/MagicBoxII, DNTV tinyUSB2, Beetle USB2.0 support"
+       depends on DVB_USB
+       help
+         Say Y here to support the
+
+           TwinhanDTV Alpha (stick) (VP-7045),
+               TwinhanDTV MagicBox II (VP-7046),
+               DigitalNow TinyUSB 2 DVB-t,
+               DigitalRise USB 2.0 Ter (Beetle) and
+               TYPHOON DVB-T USB DRIVE
+
+         DVB-T USB2.0 receivers.
+
+config DVB_USB_VP702X
+       tristate "TwinhanDTV StarBox and clones DVB-S USB2.0 support"
+       depends on DVB_USB
+       help
+         Say Y here to support the
+
+           TwinhanDTV StarBox,
+               DigitalRise USB Starbox and
+               TYPHOON DVB-S USB 2.0 BOX
+
+         DVB-S USB2.0 receivers.
+
+config DVB_USB_GP8PSK
+       tristate "GENPIX 8PSK->USB module support"
+       depends on DVB_USB
+       help
+         Say Y here to support the
+           GENPIX 8psk module
+
+         DVB-S USB2.0 receivers.
+
+config DVB_USB_NOVA_T_USB2
+       tristate "Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 support"
+       depends on DVB_USB
+       select DVB_DIB3000MC
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Hauppauge WinTV-NOVA-T usb2 DVB-T USB2.0 receiver.
+
+config DVB_USB_TTUSB2
+       tristate "Pinnacle 400e DVB-S USB2.0 support"
+       depends on DVB_USB
+       select DVB_TDA10086 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA826X if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Pinnacle 400e DVB-S USB2.0 receiver. The
+         firmware protocol used by this module is similar to the one used by the
+         old ttusb-driver - that's why the module is called dvb-usb-ttusb2.
+
+config DVB_USB_DTT200U
+       tristate "WideView WT-200U and WT-220U (pen) DVB-T USB2.0 support (Yakumo/Hama/Typhoon/Yuan)"
+       depends on DVB_USB
+       help
+         Say Y here to support the WideView/Yakumo/Hama/Typhoon/Yuan DVB-T USB2.0 receiver.
+
+         The receivers are also known as DTT200U (Yakumo) and UB300 (Yuan).
+
+         The WT-220U and its clones are pen-sized.
+
+config DVB_USB_OPERA1
+       tristate "Opera1 DVB-S USB2.0 receiver"
+       depends on DVB_USB
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Opera DVB-S USB2.0 receiver.
+
+config DVB_USB_AF9005
+       tristate "Afatech AF9005 DVB-T USB1.1 support"
+       depends on DVB_USB
+       select MEDIA_TUNER_MT2060 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Afatech AF9005 based DVB-T USB1.1 receiver
+         and the TerraTec Cinergy T USB XE (Rev.1)
+
+config DVB_USB_AF9005_REMOTE
+       tristate "Afatech AF9005 default remote control support"
+       depends on DVB_USB_AF9005
+       help
+         Say Y here to support the default remote control decoding for the
+         Afatech AF9005 based receiver.
+
+config DVB_USB_PCTV452E
+       tristate "Pinnacle PCTV HDTV Pro USB device/TT Connect S2-3600"
+       depends on DVB_USB
+       select TTPCI_EEPROM
+       select DVB_LNBP22 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Support for external USB adapter designed by Pinnacle,
+         shipped under the brand name 'PCTV HDTV Pro USB'.
+         Also supports TT Connect S2-3600/3650 cards.
+         Say Y if you own such a device and want to use it.
+
+config DVB_USB_DW2102
+       tristate "DvbWorld & TeVii DVB-S/S2 USB2.0 support"
+       depends on DVB_USB
+       select DVB_PLL if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0288 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CX24116 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_SI21XX if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_MT312 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10039 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DS3000 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0900 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the DvbWorld, TeVii, Prof DVB-S/S2 USB2.0
+         receivers.
+
+config DVB_USB_CINERGY_T2
+       tristate "Terratec CinergyT2/qanu USB 2.0 DVB-T receiver"
+       depends on DVB_USB
+       help
+         Support for "TerraTec CinergyT2" USB2.0 Highspeed DVB Receivers
+
+         Say Y if you own such a device and want to use it.
+
+config DVB_USB_DTV5100
+       tristate "AME DTV-5100 USB2.0 DVB-T support"
+       depends on DVB_USB
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_QT1010 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the AME DTV-5100 USB2.0 DVB-T receiver.
+
+config DVB_USB_FRIIO
+       tristate "Friio ISDB-T USB2.0 Receiver support"
+       depends on DVB_USB
+       help
+         Say Y here to support the Japanese DTV receiver Friio.
+
+config DVB_USB_AZ6027
+       tristate "Azurewave DVB-S/S2 USB2.0 AZ6027 support"
+       depends on DVB_USB
+       select DVB_STB0899 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STB6100 if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the AZ6027 device
+
+config DVB_USB_TECHNISAT_USB2
+       tristate "Technisat DVB-S/S2 USB2.0 support"
+       depends on DVB_USB
+       select DVB_STV090x if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV6110x if MEDIA_SUBDRV_AUTOSELECT
+       help
+         Say Y here to support the Technisat USB2 DVB-S/S2 device
diff --git a/drivers/media/usb/dvb-usb/Makefile b/drivers/media/usb/dvb-usb/Makefile
new file mode 100644 (file)
index 0000000..acdd1ef
--- /dev/null
@@ -0,0 +1,83 @@
+dvb-usb-objs += dvb-usb-firmware.o dvb-usb-init.o dvb-usb-urb.o dvb-usb-i2c.o
+dvb-usb-objs += dvb-usb-dvb.o dvb-usb-remote.o usb-urb.o
+obj-$(CONFIG_DVB_USB) += dvb-usb.o
+
+dvb-usb-vp7045-objs := vp7045.o vp7045-fe.o
+obj-$(CONFIG_DVB_USB_VP7045) += dvb-usb-vp7045.o
+
+dvb-usb-vp702x-objs := vp702x.o vp702x-fe.o
+obj-$(CONFIG_DVB_USB_VP702X) += dvb-usb-vp702x.o
+
+dvb-usb-gp8psk-objs := gp8psk.o gp8psk-fe.o
+obj-$(CONFIG_DVB_USB_GP8PSK) += dvb-usb-gp8psk.o
+
+dvb-usb-dtt200u-objs := dtt200u.o dtt200u-fe.o
+obj-$(CONFIG_DVB_USB_DTT200U) += dvb-usb-dtt200u.o
+
+dvb-usb-dibusb-common-objs := dibusb-common.o
+
+dvb-usb-a800-objs := a800.o
+obj-$(CONFIG_DVB_USB_A800) += dvb-usb-dibusb-common.o dvb-usb-a800.o
+
+dvb-usb-dibusb-mb-objs := dibusb-mb.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MB) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mb.o
+
+dvb-usb-dibusb-mc-objs := dibusb-mc.o
+obj-$(CONFIG_DVB_USB_DIBUSB_MC) += dvb-usb-dibusb-common.o dvb-usb-dibusb-mc.o
+
+dvb-usb-nova-t-usb2-objs := nova-t-usb2.o
+obj-$(CONFIG_DVB_USB_NOVA_T_USB2) += dvb-usb-dibusb-common.o dvb-usb-nova-t-usb2.o
+
+dvb-usb-umt-010-objs := umt-010.o
+obj-$(CONFIG_DVB_USB_UMT_010) += dvb-usb-dibusb-common.o dvb-usb-umt-010.o
+
+dvb-usb-m920x-objs := m920x.o
+obj-$(CONFIG_DVB_USB_M920X) += dvb-usb-m920x.o
+
+dvb-usb-digitv-objs := digitv.o
+obj-$(CONFIG_DVB_USB_DIGITV) += dvb-usb-digitv.o
+
+dvb-usb-cxusb-objs := cxusb.o
+obj-$(CONFIG_DVB_USB_CXUSB) += dvb-usb-cxusb.o
+
+dvb-usb-ttusb2-objs := ttusb2.o
+obj-$(CONFIG_DVB_USB_TTUSB2) += dvb-usb-ttusb2.o
+
+dvb-usb-dib0700-objs := dib0700_core.o dib0700_devices.o
+obj-$(CONFIG_DVB_USB_DIB0700) += dvb-usb-dib0700.o
+
+dvb-usb-opera-objs := opera1.o
+obj-$(CONFIG_DVB_USB_OPERA1) += dvb-usb-opera.o
+
+dvb-usb-af9005-objs := af9005.o af9005-fe.o
+obj-$(CONFIG_DVB_USB_AF9005) += dvb-usb-af9005.o
+
+dvb-usb-af9005-remote-objs := af9005-remote.o
+obj-$(CONFIG_DVB_USB_AF9005_REMOTE) += dvb-usb-af9005-remote.o
+
+dvb-usb-pctv452e-objs := pctv452e.o
+obj-$(CONFIG_DVB_USB_PCTV452E) += dvb-usb-pctv452e.o
+
+dvb-usb-dw2102-objs := dw2102.o
+obj-$(CONFIG_DVB_USB_DW2102) += dvb-usb-dw2102.o
+
+dvb-usb-dtv5100-objs := dtv5100.o
+obj-$(CONFIG_DVB_USB_DTV5100) += dvb-usb-dtv5100.o
+
+dvb-usb-cinergyT2-objs := cinergyT2-core.o cinergyT2-fe.o
+obj-$(CONFIG_DVB_USB_CINERGY_T2) += dvb-usb-cinergyT2.o
+
+dvb-usb-friio-objs := friio.o friio-fe.o
+obj-$(CONFIG_DVB_USB_FRIIO) += dvb-usb-friio.o
+
+dvb-usb-az6027-objs := az6027.o
+obj-$(CONFIG_DVB_USB_AZ6027) += dvb-usb-az6027.o
+
+dvb-usb-technisat-usb2-objs := technisat-usb2.o
+obj-$(CONFIG_DVB_USB_TECHNISAT_USB2) += dvb-usb-technisat-usb2.o
+
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends/
+# due to tuner-xc3028
+ccflags-y += -I$(srctree)/drivers/media/tuners
+ccflags-y += -I$(srctree)/drivers/media/pci/ttpci
similarity index 99%
rename from drivers/media/dvb/dvb-usb/dib0700_core.c
rename to drivers/media/usb/dvb-usb/dib0700_core.c
index 7e9e00fae04e140aa4dafddb6e322386442980de..ef87229de6af5d791060b00cd82188bcebbc8c20 100644 (file)
@@ -768,13 +768,13 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
        /* Starting in firmware 1.20, the RC info is provided on a bulk pipe */
        purb = usb_alloc_urb(0, GFP_KERNEL);
        if (purb == NULL) {
-               err("rc usb alloc urb failed\n");
+               err("rc usb alloc urb failed");
                return -ENOMEM;
        }
 
        purb->transfer_buffer = kzalloc(RC_MSG_SIZE_V1_20, GFP_KERNEL);
        if (purb->transfer_buffer == NULL) {
-               err("rc kzalloc failed\n");
+               err("rc kzalloc failed");
                usb_free_urb(purb);
                return -ENOMEM;
        }
@@ -786,7 +786,7 @@ int dib0700_rc_setup(struct dvb_usb_device *d)
 
        ret = usb_submit_urb(purb, GFP_ATOMIC);
        if (ret) {
-               err("rc submit urb failed\n");
+               err("rc submit urb failed");
                kfree(purb->transfer_buffer);
                usb_free_urb(purb);
        }
similarity index 99%
rename from drivers/media/dvb/dvb-usb/dvb-usb-dvb.c
rename to drivers/media/usb/dvb-usb/dvb-usb-dvb.c
index ddf282f355b3c78f9f71608f4f445f196d68d3fc..719413b15f208b7ceb165422ff4d1111dfcfd6e1 100644 (file)
@@ -106,7 +106,6 @@ int dvb_usb_adapter_dvb_init(struct dvb_usb_adapter *adap, short *adapter_nums)
                goto err;
        }
        adap->dvb_adap.priv = adap;
-       adap->dvb_adap.fe_ioctl_override = adap->props.fe_ioctl_override;
 
        if (adap->dev->props.read_mac_address) {
                if (adap->dev->props.read_mac_address(adap->dev,adap->dvb_adap.proposed_mac) == 0)
similarity index 99%
rename from drivers/media/dvb/dvb-usb/dvb-usb.h
rename to drivers/media/usb/dvb-usb/dvb-usb.h
index 99f94409efa1768ebf1d20590dcaf633fda1a414..aab0f99bc892bc764530e9966b87561eede5974f 100644 (file)
@@ -162,8 +162,6 @@ struct dvb_usb_adapter_properties {
        int size_of_priv;
 
        int (*frontend_ctrl)   (struct dvb_frontend *, int);
-       int (*fe_ioctl_override) (struct dvb_frontend *,
-                                 unsigned int, void *, unsigned int);
 
        int num_frontends;
        struct dvb_usb_adapter_fe_properties fe[MAX_NO_OF_FE_PER_ADAP];
similarity index 99%
rename from drivers/media/dvb/dvb-usb/pctv452e.c
rename to drivers/media/usb/dvb-usb/pctv452e.c
index f526eb05cc7a1f4db4327dfe286ecc2174d62ca4..02e878577c3dcb33f2cb18f0cfe9b6361a73b452 100644 (file)
@@ -136,8 +136,8 @@ static int tt3650_ci_msg(struct dvb_usb_device *d, u8 cmd, u8 *data,
        return 0;
 
 failed:
-       err("CI error %d; %02X %02X %02X -> %02X %02X %02X.",
-            ret, SYNC_BYTE_OUT, id, cmd, buf[0], buf[1], buf[2]);
+       err("CI error %d; %02X %02X %02X -> %*ph.",
+            ret, SYNC_BYTE_OUT, id, cmd, 3, buf);
 
        return ret;
 }
@@ -556,8 +556,7 @@ static int pctv452e_rc_query(struct dvb_usb_device *d)
                return ret;
 
        if (debug > 3) {
-               info("%s: read: %2d: %02x %02x %02x: ", __func__,
-                               ret, rx[0], rx[1], rx[2]);
+               info("%s: read: %2d: %*ph: ", __func__, ret, 3, rx);
                for (i = 0; (i < rx[3]) && ((i+3) < PCTV_ANSWER_LEN); i++)
                        info(" %02x", rx[i+3]);
 
similarity index 99%
rename from drivers/media/dvb/dvb-usb/technisat-usb2.c
rename to drivers/media/usb/dvb-usb/technisat-usb2.c
index acefaa89cc53724fa69d8c2afe1831990d8ed433..7a8c8c18590fdcb16c561cff57ea6d2abc6f875e 100644 (file)
@@ -677,6 +677,7 @@ static struct usb_device_id technisat_usb2_id_table[] = {
        { USB_DEVICE(USB_VID_TECHNISAT, USB_PID_TECHNISAT_USB2_DVB_S2) },
        { 0 }           /* Terminating entry */
 };
+MODULE_DEVICE_TABLE(usb, technisat_usb2_id_table);
 
 /* device description */
 static struct dvb_usb_device_properties technisat_usb2_devices = {
similarity index 99%
rename from drivers/media/dvb/dvb-usb/ttusb2.c
rename to drivers/media/usb/dvb-usb/ttusb2.c
index e53a1061cb8e4451eeda3251376c9c0461106761..6a50cdea3bcee539a79ccecd9a211c13309b803d 100644 (file)
@@ -440,7 +440,7 @@ static int tt3650_rc_query(struct dvb_usb_device *d)
                /* got a "press" event */
                st->last_rc_key = (rx[3] << 8) | rx[2];
                deb_info("%s: cmd=0x%02x sys=0x%02x\n", __func__, rx[2], rx[3]);
-               rc_keydown(d->rc_dev, st->last_rc_key, 0);
+               rc_keydown(d->rc_dev, st->last_rc_key, rx[1]);
        } else if (st->last_rc_key) {
                rc_keyup(d->rc_dev);
                st->last_rc_key = 0;
similarity index 67%
rename from drivers/media/video/em28xx/Kconfig
rename to drivers/media/usb/em28xx/Kconfig
index 928ef0d0429f2855062654956577943ef8c5f032..7a5bd61bd3bbb039fdb74bbb291bd1110d67ab02 100644 (file)
@@ -4,10 +4,10 @@ config VIDEO_EM28XX
        select VIDEO_TUNER
        select VIDEO_TVEEPROM
        select VIDEOBUF_VMALLOC
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TVP5150 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_MT9V011 if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_TVP5150 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_MSP3400 if MEDIA_SUBDRV_AUTOSELECT
+       select VIDEO_MT9V011 if MEDIA_SUBDRV_AUTOSELECT
 
        ---help---
          This is a video4linux driver for Empia 28xx based TV cards.
@@ -33,16 +33,16 @@ config VIDEO_EM28XX_ALSA
 config VIDEO_EM28XX_DVB
        tristate "DVB/ATSC Support for em28xx based TV cards"
        depends on VIDEO_EM28XX && DVB_CORE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10023 if !DVB_FE_CUSTOMISE
-       select DVB_S921 if !DVB_FE_CUSTOMISE
-       select DVB_DRXD if !DVB_FE_CUSTOMISE
-       select DVB_CXD2820R if !DVB_FE_CUSTOMISE
-       select DVB_DRXK if !DVB_FE_CUSTOMISE
-       select DVB_TDA18271C2DD if !DVB_FE_CUSTOMISE
-       select DVB_TDA10071 if !DVB_FE_CUSTOMISE
-       select DVB_A8293 if !DVB_FE_CUSTOMISE
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_ZL10353 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10023 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S921 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DRXD if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_CXD2820R if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_DRXK if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA18271C2DD if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10071 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_A8293 if MEDIA_SUBDRV_AUTOSELECT
        select VIDEOBUF_DVB
        ---help---
          This adds support for DVB cards based on the
similarity index 57%
rename from drivers/media/video/em28xx/Makefile
rename to drivers/media/usb/em28xx/Makefile
index c8b338d4be05b270c9415899d9fd771a05a8d933..634fb920dd39c47ca4e7f31e7eed400553f54a7d 100644 (file)
@@ -1,4 +1,4 @@
-em28xx-y :=    em28xx-video.o em28xx-i2c.o em28xx-cards.o
+em28xx-y +=    em28xx-video.o em28xx-i2c.o em28xx-cards.o
 em28xx-y +=    em28xx-core.o  em28xx-vbi.o
 
 em28xx-alsa-objs := em28xx-audio.o
@@ -9,7 +9,7 @@ obj-$(CONFIG_VIDEO_EM28XX_ALSA) += em28xx-alsa.o
 obj-$(CONFIG_VIDEO_EM28XX_DVB) += em28xx-dvb.o
 obj-$(CONFIG_VIDEO_EM28XX_RC) += em28xx-rc.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
similarity index 99%
rename from drivers/media/video/em28xx/em28xx-audio.c
rename to drivers/media/usb/em28xx/em28xx-audio.c
index 07dc594e79f04bea706c8cebfba1b514a8a3623e..2fdb66ee44ab7532b7e0d6a9bf3e043eddec8a87 100644 (file)
@@ -306,7 +306,6 @@ static int snd_em28xx_capture_open(struct snd_pcm_substream *substream)
 
        snd_pcm_hw_constraint_integer(runtime, SNDRV_PCM_HW_PARAM_PERIODS);
        dev->adev.capture_pcm_substream = substream;
-       runtime->private_data = dev;
 
        return 0;
 err:
similarity index 99%
rename from drivers/media/video/em28xx/em28xx-cards.c
rename to drivers/media/usb/em28xx/em28xx-cards.c
index ca62b9981380427b587efb684d36a60f88105a21..ab98d0845861bbbe4fdb3027fe7ccd2391b2ac34 100644 (file)
@@ -2875,12 +2875,20 @@ static void em28xx_card_setup(struct em28xx *dev)
 }
 
 
-#if defined(CONFIG_MODULES) && defined(MODULE)
 static void request_module_async(struct work_struct *work)
 {
        struct em28xx *dev = container_of(work,
                             struct em28xx, request_module_wk);
 
+       /*
+        * The em28xx extensions can be modules or builtin. If the
+        * modules are already loaded or are built in, those extensions
+        * can be initialised right now. Otherwise, the module init
+        * code will do it.
+        */
+       em28xx_init_extension(dev);
+
+#if defined(CONFIG_MODULES) && defined(MODULE)
        if (dev->has_audio_class)
                request_module("snd-usb-audio");
        else if (dev->has_alsa_audio)
@@ -2890,6 +2898,7 @@ static void request_module_async(struct work_struct *work)
                request_module("em28xx-dvb");
        if (dev->board.ir_codes && !disable_ir)
                request_module("em28xx-rc");
+#endif /* CONFIG_MODULES */
 }
 
 static void request_modules(struct em28xx *dev)
@@ -2902,10 +2911,6 @@ static void flush_request_modules(struct em28xx *dev)
 {
        flush_work_sync(&dev->request_module_wk);
 }
-#else
-#define request_modules(dev)
-#define flush_request_modules(dev)
-#endif /* CONFIG_MODULES */
 
 /*
  * em28xx_release_resources()
@@ -3324,13 +3329,6 @@ static int em28xx_usb_probe(struct usb_interface *interface,
         */
        mutex_unlock(&dev->lock);
 
-       /*
-        * These extensions can be modules. If the modules are already
-        * loaded then we can initialise the device now, otherwise we
-        * will initialise it when the modules load instead.
-        */
-       em28xx_init_extension(dev);
-
        return 0;
 
 unlock_and_free:
similarity index 99%
rename from drivers/media/video/em28xx/em28xx-core.c
rename to drivers/media/usb/em28xx/em28xx-core.c
index de2cb20ad2cc1d676c6aa0c532e36bc251c4273e..bed07a6c33f8156df80919725c05857cd0fd9b37 100644 (file)
@@ -785,12 +785,8 @@ int em28xx_resolution_set(struct em28xx *dev)
        else
                dev->vbi_height = 18;
 
-       if (!dev->progressive)
-               height >>= norm_maxh(dev);
-
        em28xx_set_outfmt(dev);
 
-
        em28xx_accumulator_set(dev, 1, (width - 4) >> 2, 1, (height - 4) >> 2);
 
        /* If we don't set the start position to 2 in VBI mode, we end up
similarity index 95%
rename from drivers/media/video/em28xx/em28xx-dvb.c
rename to drivers/media/usb/em28xx/em28xx-dvb.c
index a16531fa937a1ec395e3490e741e0d46d0a3cccd..913e5227897a3c4b68a7ad51ec254c7bb51d41e0 100644 (file)
@@ -28,6 +28,7 @@
 #include <media/videobuf-vmalloc.h>
 #include <media/tuner.h>
 #include "tuner-simple.h"
+#include <linux/gpio.h>
 
 #include "lgdt330x.h"
 #include "lgdt3305.h"
@@ -80,6 +81,7 @@ struct em28xx_dvb {
        int (*gate_ctrl)(struct dvb_frontend *, int);
        struct semaphore      pll_mutex;
        bool                    dont_attach_fe1;
+       int                     lna_gpio;
 };
 
 
@@ -316,6 +318,7 @@ static struct drxk_config terratec_h5_drxk = {
        .no_i2c_bridge = 1,
        .microcode_name = "dvb-usb-terratec-h5-drxk.fw",
        .qam_demod_parameter_count = 2,
+       .load_firmware_sync = true,
 };
 
 static struct drxk_config hauppauge_930c_drxk = {
@@ -325,6 +328,7 @@ static struct drxk_config hauppauge_930c_drxk = {
        .microcode_name = "dvb-usb-hauppauge-hvr930c-drxk.fw",
        .chunk_size = 56,
        .qam_demod_parameter_count = 2,
+       .load_firmware_sync = true,
 };
 
 struct drxk_config terratec_htc_stick_drxk = {
@@ -338,12 +342,14 @@ struct drxk_config terratec_htc_stick_drxk = {
        .antenna_dvbt = true,
        /* The windows driver uses the same. This will disable LNA. */
        .antenna_gpio = 0x6,
+       .load_firmware_sync = true,
 };
 
 static struct drxk_config maxmedia_ub425_tc_drxk = {
        .adr = 0x29,
        .single_master = 1,
        .no_i2c_bridge = 1,
+       .load_firmware_sync = true,
 };
 
 static struct drxk_config pctv_520e_drxk = {
@@ -354,6 +360,7 @@ static struct drxk_config pctv_520e_drxk = {
        .chunk_size = 58,
        .antenna_dvbt = true, /* disable LNA */
        .antenna_gpio = (1 << 2), /* disable LNA */
+       .load_firmware_sync = true,
 };
 
 static int drxk_gate_ctrl(struct dvb_frontend *fe, int enable)
@@ -567,6 +574,33 @@ static void pctv_520e_init(struct em28xx *dev)
                i2c_master_send(&dev->i2c_client, regs[i].r, regs[i].len);
 };
 
+static int em28xx_pctv_290e_set_lna(struct dvb_frontend *fe, int val)
+{
+       struct em28xx *dev = fe->dvb->priv;
+#ifdef CONFIG_GPIOLIB
+       struct em28xx_dvb *dvb = dev->dvb;
+       int ret;
+       unsigned long flags;
+
+       if (val)
+               flags = GPIOF_OUT_INIT_LOW;
+       else
+               flags = GPIOF_OUT_INIT_HIGH;
+
+       ret = gpio_request_one(dvb->lna_gpio, flags, NULL);
+       if (ret)
+               em28xx_errdev("gpio request failed %d\n", ret);
+       else
+               gpio_free(dvb->lna_gpio);
+
+       return ret;
+#else
+       dev_warn(&dev->udev->dev, "%s: LNA control is disabled\n",
+                       KBUILD_MODNAME);
+       return 0;
+#endif
+}
+
 static int em28xx_mt352_terratec_xs_init(struct dvb_frontend *fe)
 {
        /* Values extracted from a USB trace of the Terratec Windows driver */
@@ -610,11 +644,6 @@ static struct tda10023_config em28xx_tda10023_config = {
 static struct cxd2820r_config em28xx_cxd2820r_config = {
        .i2c_address = (0xd8 >> 1),
        .ts_mode = CXD2820R_TS_SERIAL,
-
-       /* enable LNA for DVB-T, DVB-T2 and DVB-C */
-       .gpio_dvbt[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
-       .gpio_dvbt2[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
-       .gpio_dvbc[0] = CXD2820R_GPIO_E | CXD2820R_GPIO_O | CXD2820R_GPIO_L,
 };
 
 static struct tda18271_config em28xx_cxd2820r_tda18271_config = {
@@ -959,9 +988,13 @@ static int em28xx_dvb_init(struct em28xx *dev)
                                   &dev->i2c_adap, &kworld_a340_config);
                break;
        case EM28174_BOARD_PCTV_290E:
+               /* set default GPIO0 for LNA, used if GPIOLIB is undefined */
+               dvb->lna_gpio = CXD2820R_GPIO_E | CXD2820R_GPIO_O |
+                               CXD2820R_GPIO_L;
                dvb->fe[0] = dvb_attach(cxd2820r_attach,
                                        &em28xx_cxd2820r_config,
-                                       &dev->i2c_adap);
+                                       &dev->i2c_adap,
+                                       &dvb->lna_gpio);
                if (dvb->fe[0]) {
                        /* FE 0 attach tuner */
                        if (!dvb_attach(tda18271_attach,
@@ -974,7 +1007,22 @@ static int em28xx_dvb_init(struct em28xx *dev)
                                result = -EINVAL;
                                goto out_free;
                        }
+
+#ifdef CONFIG_GPIOLIB
+                       /* enable LNA for DVB-T, DVB-T2 and DVB-C */
+                       result = gpio_request_one(dvb->lna_gpio,
+                                       GPIOF_OUT_INIT_LOW, NULL);
+                       if (result)
+                               em28xx_errdev("gpio request failed %d\n",
+                                               result);
+                       else
+                               gpio_free(dvb->lna_gpio);
+
+                       result = 0; /* continue even set LNA fails */
+#endif
+                       dvb->fe[0]->ops.set_lna = em28xx_pctv_290e_set_lna;
                }
+
                break;
        case EM2884_BOARD_HAUPPAUGE_WINTV_HVR_930C:
        {
similarity index 98%
rename from drivers/media/video/em28xx/em28xx-video.c
rename to drivers/media/usb/em28xx/em28xx-video.c
index 50f5f4fc2148ce76db99619930137345e3d4b0a3..1e553d3573805795dc8cb1debdbd50f82d6a42c4 100644 (file)
@@ -1352,7 +1352,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *a)
 {
        struct em28xx_fh   *fh  = priv;
        struct em28xx      *dev = fh->dev;
@@ -2087,7 +2087,7 @@ static int radio_s_tuner(struct file *file, void *priv,
 }
 
 static int radio_s_audio(struct file *file, void *fh,
-                        struct v4l2_audio *a)
+                        const struct v4l2_audio *a)
 {
        return 0;
 }
@@ -2146,9 +2146,12 @@ static int em28xx_v4l2_open(struct file *filp)
                        dev->users);
 
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        fh = kzalloc(sizeof(struct em28xx_fh), GFP_KERNEL);
        if (!fh) {
                em28xx_errdev("em28xx-video.c: Out of memory?!\n");
+               mutex_unlock(&dev->lock);
                return -ENOMEM;
        }
        fh->dev = dev;
@@ -2189,6 +2192,7 @@ static int em28xx_v4l2_open(struct file *filp)
                                    V4L2_BUF_TYPE_VBI_CAPTURE,
                                    V4L2_FIELD_SEQ_TB,
                                    sizeof(struct em28xx_buffer), fh, &dev->lock);
+       mutex_unlock(&dev->lock);
 
        return errCode;
 }
@@ -2243,6 +2247,7 @@ static int em28xx_v4l2_close(struct file *filp)
 
        em28xx_videodbg("users=%d\n", dev->users);
 
+       mutex_lock(&dev->lock);
        if (res_check(fh, EM28XX_RESOURCE_VIDEO)) {
                videobuf_stop(&fh->vb_vidq);
                res_free(fh, EM28XX_RESOURCE_VIDEO);
@@ -2259,6 +2264,7 @@ static int em28xx_v4l2_close(struct file *filp)
                if (dev->state & DEV_DISCONNECTED) {
                        em28xx_release_resources(dev);
                        kfree(dev->alt_max_pkt_size);
+                       mutex_unlock(&dev->lock);
                        kfree(dev);
                        kfree(fh);
                        return 0;
@@ -2285,6 +2291,7 @@ static int em28xx_v4l2_close(struct file *filp)
        videobuf_mmap_free(&fh->vb_vbiq);
        kfree(fh);
        dev->users--;
+       mutex_unlock(&dev->lock);
        return 0;
 }
 
@@ -2304,35 +2311,35 @@ em28xx_v4l2_read(struct file *filp, char __user *buf, size_t count,
        if (rc < 0)
                return rc;
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        /* FIXME: read() is not prepared to allow changing the video
           resolution while streaming. Seems a bug at em28xx_set_fmt
         */
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
                if (res_locked(dev, EM28XX_RESOURCE_VIDEO))
-                       return -EBUSY;
-
-               return videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
+                       rc = -EBUSY;
+               else
+                       rc = videobuf_read_stream(&fh->vb_vidq, buf, count, pos, 0,
                                        filp->f_flags & O_NONBLOCK);
-       }
-
-
-       if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
+       } else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE) {
                if (!res_get(fh, EM28XX_RESOURCE_VBI))
-                       return -EBUSY;
-
-               return videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
+                       rc = -EBUSY;
+               else
+                       rc = videobuf_read_stream(&fh->vb_vbiq, buf, count, pos, 0,
                                        filp->f_flags & O_NONBLOCK);
        }
+       mutex_unlock(&dev->lock);
 
-       return 0;
+       return rc;
 }
 
 /*
- * em28xx_v4l2_poll()
+ * em28xx_poll()
  * will allocate buffers when called for the first time
  */
-static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
+static unsigned int em28xx_poll(struct file *filp, poll_table *wait)
 {
        struct em28xx_fh *fh = filp->private_data;
        struct em28xx *dev = fh->dev;
@@ -2355,6 +2362,18 @@ static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
        }
 }
 
+static unsigned int em28xx_v4l2_poll(struct file *filp, poll_table *wait)
+{
+       struct em28xx_fh *fh = filp->private_data;
+       struct em28xx *dev = fh->dev;
+       unsigned int res;
+
+       mutex_lock(&dev->lock);
+       res = em28xx_poll(filp, wait);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
 /*
  * em28xx_v4l2_mmap()
  */
@@ -2368,10 +2387,13 @@ static int em28xx_v4l2_mmap(struct file *filp, struct vm_area_struct *vma)
        if (rc < 0)
                return rc;
 
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE)
                rc = videobuf_mmap_mapper(&fh->vb_vidq, vma);
        else if (fh->type == V4L2_BUF_TYPE_VBI_CAPTURE)
                rc = videobuf_mmap_mapper(&fh->vb_vbiq, vma);
+       mutex_unlock(&dev->lock);
 
        em28xx_videodbg("vma start=0x%08lx, size=%ld, ret=%d\n",
                (unsigned long)vma->vm_start,
@@ -2495,10 +2517,6 @@ static struct video_device *em28xx_vdev_init(struct em28xx *dev,
        vfd->release    = video_device_release;
        vfd->debug      = video_debug;
        vfd->lock       = &dev->lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s",
                 dev->name, type_name);
similarity index 98%
rename from drivers/media/video/gspca/Kconfig
rename to drivers/media/usb/gspca/Kconfig
index dfe268bfa4f8f55a1e18139515546cd45365eb93..6345f9331e7fa15f173cce993970a93ba7ca197d 100644 (file)
@@ -17,9 +17,9 @@ menuconfig USB_GSPCA
 
 if USB_GSPCA && VIDEO_V4L2
 
-source "drivers/media/video/gspca/m5602/Kconfig"
-source "drivers/media/video/gspca/stv06xx/Kconfig"
-source "drivers/media/video/gspca/gl860/Kconfig"
+source "drivers/media/usb/gspca/m5602/Kconfig"
+source "drivers/media/usb/gspca/stv06xx/Kconfig"
+source "drivers/media/usb/gspca/gl860/Kconfig"
 
 config USB_GSPCA_BENQ
        tristate "Benq USB Camera Driver"
similarity index 99%
rename from drivers/media/video/gspca/cpia1.c
rename to drivers/media/usb/gspca/cpia1.c
index 2499a881d9a3ab68c8a4190f9ac19fb6d41ad3ed..b3ba47d4d6a2932fd518f00bc05947d73004839e 100644 (file)
@@ -751,7 +751,7 @@ static int goto_high_power(struct gspca_dev *gspca_dev)
        if (signal_pending(current))
                return -EINTR;
 
-       do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
+       ret = do_command(gspca_dev, CPIA_COMMAND_GetCameraStatus, 0, 0, 0, 0);
        if (ret)
                return ret;
 
similarity index 92%
rename from drivers/media/video/gspca/finepix.c
rename to drivers/media/usb/gspca/finepix.c
index c8f2201cc35ad96403230150b999363a7f362a93..52bdb569760b4139bb20dfca693746b5a267ddf6 100644 (file)
@@ -77,7 +77,14 @@ static int command(struct gspca_dev *gspca_dev,
                        12, FPIX_TIMEOUT);
 }
 
-/* workqueue */
+/*
+ * This function is called as a workqueue function and runs whenever the camera
+ * is streaming data. Because it is a workqueue function it is allowed to sleep
+ * so we can use synchronous USB calls. To avoid possible collisions with other
+ * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
+ * performing USB operations using it. In practice we don't really need this
+ * as the camera doesn't provide any controls.
+ */
 static void dostream(struct work_struct *work)
 {
        struct usb_fpix *dev = container_of(work, struct usb_fpix, work_struct);
@@ -87,14 +94,11 @@ static void dostream(struct work_struct *work)
        int ret = 0;
        int len;
 
-       /* synchronize with the main driver */
-       mutex_lock(&gspca_dev->usb_lock);
-       mutex_unlock(&gspca_dev->usb_lock);
        PDEBUG(D_STREAM, "dostream started");
 
        /* loop reading a frame */
 again:
-       while (gspca_dev->dev && gspca_dev->streaming) {
+       while (gspca_dev->present && gspca_dev->streaming) {
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        break;
@@ -110,7 +114,7 @@ again:
                if (gspca_dev->frozen)
                        break;
 #endif
-               if (!gspca_dev->dev || !gspca_dev->streaming)
+               if (!gspca_dev->present || !gspca_dev->streaming)
                        break;
 
                /* the frame comes in parts */
@@ -129,7 +133,7 @@ again:
                        if (gspca_dev->frozen)
                                goto out;
 #endif
-                       if (!gspca_dev->dev || !gspca_dev->streaming)
+                       if (!gspca_dev->present || !gspca_dev->streaming)
                                goto out;
                        if (len < FPIX_MAX_TRANSFER ||
                                (data[len - 2] == 0xff &&
similarity index 75%
rename from drivers/media/video/gspca/gl860/Makefile
rename to drivers/media/usb/gspca/gl860/Makefile
index 773ea3426561c68588f43502b2b0278a3ff2c542..cf6397415aad6bc0534aa2510b80b3b8d8ccb603 100644 (file)
@@ -6,5 +6,5 @@ gspca_gl860-objs := gl860.o \
                    gl860-ov9655.o \
                    gl860-mi2020.o
 
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
 
similarity index 99%
rename from drivers/media/video/gspca/gspca.c
rename to drivers/media/usb/gspca/gspca.c
index d4e8343f5b1013b17b1d9541bbaf287c193a6b48..a2b934146ebf9245da1a972b36addc89eb7b026c 100644 (file)
@@ -1686,7 +1686,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
 }
 
 static int vidioc_s_jpegcomp(struct file *file, void *priv,
-                       struct v4l2_jpegcompression *jpegcomp)
+                       const struct v4l2_jpegcompression *jpegcomp)
 {
        struct gspca_dev *gspca_dev = video_drvdata(file);
 
@@ -2358,8 +2358,6 @@ void gspca_disconnect(struct usb_interface *intf)
 
        mutex_lock(&gspca_dev->usb_lock);
 
-       usb_set_intfdata(intf, NULL);
-       gspca_dev->dev = NULL;
        gspca_dev->present = 0;
        destroy_urbs(gspca_dev);
 
@@ -2375,6 +2373,7 @@ void gspca_disconnect(struct usb_interface *intf)
        if (gspca_dev->sd_desc->stop0 && gspca_dev->streaming)
                gspca_dev->sd_desc->stop0(gspca_dev);
        gspca_dev->streaming = 0;
+       gspca_dev->dev = NULL;
        wake_up_interruptible(&gspca_dev->wq);
 
        v4l2_device_disconnect(&gspca_dev->v4l2_dev);
@@ -2392,19 +2391,22 @@ int gspca_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct gspca_dev *gspca_dev = usb_get_intfdata(intf);
 
+       gspca_input_destroy_urb(gspca_dev);
+
        if (!gspca_dev->streaming)
                return 0;
+
        mutex_lock(&gspca_dev->usb_lock);
        gspca_dev->frozen = 1;          /* avoid urb error messages */
        gspca_dev->usb_err = 0;
        if (gspca_dev->sd_desc->stopN)
                gspca_dev->sd_desc->stopN(gspca_dev);
        destroy_urbs(gspca_dev);
-       gspca_input_destroy_urb(gspca_dev);
        gspca_set_alt0(gspca_dev);
        if (gspca_dev->sd_desc->stop0)
                gspca_dev->sd_desc->stop0(gspca_dev);
        mutex_unlock(&gspca_dev->usb_lock);
+
        return 0;
 }
 EXPORT_SYMBOL(gspca_suspend);
@@ -2418,7 +2420,6 @@ int gspca_resume(struct usb_interface *intf)
        gspca_dev->frozen = 0;
        gspca_dev->usb_err = 0;
        gspca_dev->sd_desc->init(gspca_dev);
-       gspca_input_create_urb(gspca_dev);
        /*
         * Most subdrivers send all ctrl values on sd_start and thus
         * only write to the device registers on s_ctrl when streaming ->
@@ -2428,7 +2429,10 @@ int gspca_resume(struct usb_interface *intf)
        gspca_dev->streaming = 0;
        if (streaming)
                ret = gspca_init_transfer(gspca_dev);
+       else
+               gspca_input_create_urb(gspca_dev);
        mutex_unlock(&gspca_dev->usb_lock);
+
        return ret;
 }
 EXPORT_SYMBOL(gspca_resume);
similarity index 97%
rename from drivers/media/video/gspca/gspca.h
rename to drivers/media/usb/gspca/gspca.h
index dc688c7f5e4811845ce5f8add9de98a3ea2cdeec..e3eab82cd4e5d31097b064e654e18a9079d8ee43 100644 (file)
@@ -83,8 +83,10 @@ struct gspca_frame;
 typedef int (*cam_op) (struct gspca_dev *);
 typedef void (*cam_v_op) (struct gspca_dev *);
 typedef int (*cam_cf_op) (struct gspca_dev *, const struct usb_device_id *);
-typedef int (*cam_jpg_op) (struct gspca_dev *,
+typedef int (*cam_get_jpg_op) (struct gspca_dev *,
                                struct v4l2_jpegcompression *);
+typedef int (*cam_set_jpg_op) (struct gspca_dev *,
+                               const struct v4l2_jpegcompression *);
 typedef int (*cam_reg_op) (struct gspca_dev *,
                                struct v4l2_dbg_register *);
 typedef int (*cam_ident_op) (struct gspca_dev *,
@@ -126,8 +128,8 @@ struct sd_desc {
        cam_v_op stopN;         /* called on stream off - main alt */
        cam_v_op stop0;         /* called on stream off & disconnect - alt 0 */
        cam_v_op dq_callback;   /* called when a frame has been dequeued */
-       cam_jpg_op get_jcomp;
-       cam_jpg_op set_jcomp;
+       cam_get_jpg_op get_jcomp;
+       cam_set_jpg_op set_jcomp;
        cam_qmnu_op querymenu;
        cam_streamparm_op get_streamparm;
        cam_streamparm_op set_streamparm;
similarity index 99%
rename from drivers/media/video/gspca/jeilinj.c
rename to drivers/media/usb/gspca/jeilinj.c
index 26b99310d628f50d4be973e317f7a84104d0c449..b897aa86f315665645808efa95be5b11d3ac2171 100644 (file)
@@ -474,7 +474,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
 }
 
 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
+                       const struct v4l2_jpegcompression *jcomp)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
similarity index 95%
rename from drivers/media/video/gspca/jl2005bcd.c
rename to drivers/media/usb/gspca/jl2005bcd.c
index 234777116e5fc5e8cc25a6f4e1940feca8a31412..62ba80d9b9988478dbc9727eb1b6a50d210b583c 100644 (file)
@@ -306,15 +306,13 @@ static int jl2005c_stop(struct gspca_dev *gspca_dev)
        return retval;
 }
 
-/* This function is called as a workqueue function and runs whenever the camera
+/*
+ * This function is called as a workqueue function and runs whenever the camera
  * is streaming data. Because it is a workqueue function it is allowed to sleep
  * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface the gspca usb_lock is
- * used when performing the one USB control operation inside the workqueue,
- * which tells the camera to close the stream. In practice the only thing
- * which needs to be protected against is the usb_set_interface call that
- * gspca makes during stream_off. Otherwise the camera doesn't provide any
- * controls that the user could try to change.
+ * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
+ * performing USB operations using it. In practice we don't really need this
+ * as the camera doesn't provide any controls.
  */
 static void jl2005c_dostream(struct work_struct *work)
 {
@@ -335,7 +333,7 @@ static void jl2005c_dostream(struct work_struct *work)
                goto quit_stream;
        }
 
-       while (gspca_dev->dev && gspca_dev->streaming) {
+       while (gspca_dev->present && gspca_dev->streaming) {
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        break;
@@ -371,7 +369,7 @@ static void jl2005c_dostream(struct work_struct *work)
                                        buffer, act_len);
                        header_read = 1;
                }
-               while (bytes_left > 0 && gspca_dev->dev) {
+               while (bytes_left > 0 && gspca_dev->present) {
                        data_len = bytes_left > JL2005C_MAX_TRANSFER ?
                                JL2005C_MAX_TRANSFER : bytes_left;
                        ret = usb_bulk_msg(gspca_dev->dev,
@@ -394,7 +392,7 @@ static void jl2005c_dostream(struct work_struct *work)
                }
        }
 quit_stream:
-       if (gspca_dev->dev) {
+       if (gspca_dev->present) {
                mutex_lock(&gspca_dev->usb_lock);
                jl2005c_stop(gspca_dev);
                mutex_unlock(&gspca_dev->usb_lock);
similarity index 80%
rename from drivers/media/video/gspca/m5602/Makefile
rename to drivers/media/usb/gspca/m5602/Makefile
index 575b75bacb62118ae5cb4b004c7fcec5dc7402b0..8e1fb5a1d2a1ef6b024d7500379abc9a69fcfce5 100644 (file)
@@ -8,4 +8,4 @@ gspca_m5602-objs := m5602_core.o \
                    m5602_s5k83a.o \
                    m5602_s5k4aa.o
 
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
similarity index 99%
rename from drivers/media/video/gspca/ov519.c
rename to drivers/media/usb/gspca/ov519.c
index bfc7cefa59f8ac2a0dd55f2b706133a020307047..9aa09f845ce4c2ca05b1d4bf7e34575b19436dc9 100644 (file)
@@ -141,14 +141,14 @@ enum sensors {
 
 /* table of the disabled controls */
 struct ctrl_valid {
-       int has_brightness:1;
-       int has_contrast:1;
-       int has_exposure:1;
-       int has_autogain:1;
-       int has_sat:1;
-       int has_hvflip:1;
-       int has_autobright:1;
-       int has_freq:1;
+       unsigned int has_brightness:1;
+       unsigned int has_contrast:1;
+       unsigned int has_exposure:1;
+       unsigned int has_autogain:1;
+       unsigned int has_sat:1;
+       unsigned int has_hvflip:1;
+       unsigned int has_autobright:1;
+       unsigned int has_freq:1;
 };
 
 static const struct ctrl_valid valid_controls[] = {
@@ -4762,7 +4762,7 @@ static int sd_get_jcomp(struct gspca_dev *gspca_dev,
 }
 
 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
+                       const struct v4l2_jpegcompression *jcomp)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
similarity index 95%
rename from drivers/media/video/gspca/pac7302.c
rename to drivers/media/usb/gspca/pac7302.c
index 4877f7ab3d597eba3574abbab1a3945b0b18cca6..2d5c6d8343a01c475291b3435de77cec7112ff35 100644 (file)
 /*
  * Some documentation about various registers as determined by trial and error.
  *
+ * Register page 0:
+ *
+ * Address     Description
+ * 0x02                Red balance control
+ * 0x03                Green balance control
+ * 0x04        Blue balance control
+ *                  Valus are inverted (0=max, 255=min).
+ *                  The Windows driver uses a quadratic approach to map
+ *                  the settable values (0-200) on register values:
+ *                  min=0x80, default=0x40, max=0x20
+ * 0x0f-0x20   Colors, saturation and exposure control
+ * 0xa2-0xab   Brightness, contrast and gamma control
+ * 0xb6                Sharpness control (bits 0-4)
+ *
  * Register page 1:
  *
  * Address     Description
@@ -66,6 +80,7 @@
  * -----+------------+---------------------------------------------------
  *  0   | 0x0f..0x20 | setcolors()
  *  0   | 0xa2..0xab | setbrightcont()
+ *  0   | 0xb6       | setsharpness()
  *  0   | 0xc5       | setredbalance()
  *  0   | 0xc6       | setwhitebalance()
  *  0   | 0xc7       | setbluebalance()
@@ -109,6 +124,7 @@ struct sd {
                struct v4l2_ctrl *hflip;
                struct v4l2_ctrl *vflip;
        };
+       struct v4l2_ctrl *sharpness;
        u8 flags;
 #define FL_HFLIP 0x01          /* mirrored by default */
 #define FL_VFLIP 0x02          /* vertical flipped by default */
@@ -531,6 +547,16 @@ static void sethvflip(struct gspca_dev *gspca_dev)
        reg_w(gspca_dev, 0x11, 0x01);
 }
 
+static void setsharpness(struct gspca_dev *gspca_dev)
+{
+       struct sd *sd = (struct sd *) gspca_dev;
+
+       reg_w(gspca_dev, 0xff, 0x00);           /* page 0 */
+       reg_w(gspca_dev, 0xb6, sd->sharpness->val);
+
+       reg_w(gspca_dev, 0xdc, 0x01);
+}
+
 /* this function is called at probe and resume time for pac7302 */
 static int sd_init(struct gspca_dev *gspca_dev)
 {
@@ -584,6 +610,9 @@ static int sd_s_ctrl(struct v4l2_ctrl *ctrl)
        case V4L2_CID_HFLIP:
                sethvflip(gspca_dev);
                break;
+       case V4L2_CID_SHARPNESS:
+               setsharpness(gspca_dev);
+               break;
        default:
                return -EINVAL;
        }
@@ -601,7 +630,7 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
        struct v4l2_ctrl_handler *hdl = &gspca_dev->ctrl_handler;
 
        gspca_dev->vdev.ctrl_handler = hdl;
-       v4l2_ctrl_handler_init(hdl, 11);
+       v4l2_ctrl_handler_init(hdl, 12);
 
        sd->brightness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                                        V4L2_CID_BRIGHTNESS, 0, 32, 1, 16);
@@ -612,11 +641,11 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
                                        V4L2_CID_SATURATION, 0, 255, 1, 127);
        sd->white_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                                        V4L2_CID_WHITE_BALANCE_TEMPERATURE,
-                                       0, 255, 1, 4);
+                                       0, 255, 1, 55);
        sd->red_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                                        V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
        sd->blue_balance = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
-                                       V4L2_CID_RED_BALANCE, 0, 3, 1, 1);
+                                       V4L2_CID_BLUE_BALANCE, 0, 3, 1, 1);
 
        gspca_dev->autogain = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                                        V4L2_CID_AUTOGAIN, 0, 1, 1, 1);
@@ -632,6 +661,9 @@ static int sd_init_controls(struct gspca_dev *gspca_dev)
        sd->vflip = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
                V4L2_CID_VFLIP, 0, 1, 1, 0);
 
+       sd->sharpness = v4l2_ctrl_new_std(hdl, &sd_ctrl_ops,
+                                       V4L2_CID_SHARPNESS, 0, 15, 1, 8);
+
        if (hdl->error) {
                pr_err("Could not initialize controls\n");
                return hdl->error;
@@ -650,14 +682,6 @@ static int sd_start(struct gspca_dev *gspca_dev)
 
        reg_w_var(gspca_dev, start_7302,
                page3_7302, sizeof(page3_7302));
-       setbrightcont(gspca_dev);
-       setcolors(gspca_dev);
-       setwhitebalance(gspca_dev);
-       setredbalance(gspca_dev);
-       setbluebalance(gspca_dev);
-       setexposure(gspca_dev);
-       setgain(gspca_dev);
-       sethvflip(gspca_dev);
 
        sd->sof_read = 0;
        sd->autogain_ignore_frames = 0;
@@ -905,6 +929,7 @@ static const struct usb_device_id device_table[] = {
        {USB_DEVICE(0x093a, 0x262a)},
        {USB_DEVICE(0x093a, 0x262c)},
        {USB_DEVICE(0x145f, 0x013c)},
+       {USB_DEVICE(0x1ae7, 0x2001)}, /* SpeedLink Snappy Mic SL-6825-SBK */
        {}
 };
 MODULE_DEVICE_TABLE(usb, device_table);
similarity index 99%
rename from drivers/media/video/gspca/sn9c20x.c
rename to drivers/media/usb/gspca/sn9c20x.c
index b9c6f17eabb245fde118e3b198f163782d92a7bc..41f769fe340c9f1a6a9f01ef7a84e4e9feb323b1 100644 (file)
@@ -2197,8 +2197,10 @@ static void qual_upd(struct work_struct *work)
        struct gspca_dev *gspca_dev = &sd->gspca_dev;
        s32 qual = v4l2_ctrl_g_ctrl(sd->jpegqual);
 
+       /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
        mutex_lock(&gspca_dev->usb_lock);
        PDEBUG(D_STREAM, "qual_upd %d%%", qual);
+       gspca_dev->usb_err = 0;
        set_quality(gspca_dev, qual);
        mutex_unlock(&gspca_dev->usb_lock);
 }
similarity index 99%
rename from drivers/media/video/gspca/sonixj.c
rename to drivers/media/usb/gspca/sonixj.c
index 150b2df40f7f56e54e29a5acffd7c7b42f3b3d13..5a86047b846f484c2d1c22d88023878d2249b646 100644 (file)
@@ -2380,8 +2380,10 @@ static void qual_upd(struct work_struct *work)
        struct sd *sd = container_of(work, struct sd, work);
        struct gspca_dev *gspca_dev = &sd->gspca_dev;
 
+       /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
        mutex_lock(&gspca_dev->usb_lock);
        PDEBUG(D_STREAM, "qual_upd %d%%", sd->quality);
+       gspca_dev->usb_err = 0;
        setjpegqual(gspca_dev);
        mutex_unlock(&gspca_dev->usb_lock);
 }
similarity index 95%
rename from drivers/media/video/gspca/sq905.c
rename to drivers/media/usb/gspca/sq905.c
index a8ac97931ad68abe6986ab19fc959bc2596e0d5a..1d99f10a3e19962e4263acbdb630b8d6912165c8 100644 (file)
@@ -201,14 +201,13 @@ sq905_read_data(struct gspca_dev *gspca_dev, u8 *data, int size, int need_lock)
        return 0;
 }
 
-/* This function is called as a workqueue function and runs whenever the camera
+/*
+ * This function is called as a workqueue function and runs whenever the camera
  * is streaming data. Because it is a workqueue function it is allowed to sleep
  * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface we take the gspca
- * usb_lock when performing USB operations. In practice the only thing we need
- * to protect against is the usb_set_interface call that gspca makes during
- * stream_off as the camera doesn't provide any controls that the user could try
- * to change.
+ * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
+ * performing USB operations using it. In practice we don't really need this
+ * as the camera doesn't provide any controls.
  */
 static void sq905_dostream(struct work_struct *work)
 {
@@ -232,7 +231,7 @@ static void sq905_dostream(struct work_struct *work)
        frame_sz = gspca_dev->cam.cam_mode[gspca_dev->curr_mode].sizeimage
                        + FRAME_HEADER_LEN;
 
-       while (gspca_dev->dev && gspca_dev->streaming) {
+       while (gspca_dev->present && gspca_dev->streaming) {
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        break;
@@ -246,7 +245,7 @@ static void sq905_dostream(struct work_struct *work)
                   we must finish reading an entire frame, otherwise the
                   next time we stream we start reading in the middle of a
                   frame. */
-               while (bytes_left > 0 && gspca_dev->dev) {
+               while (bytes_left > 0 && gspca_dev->present) {
                        data_len = bytes_left > SQ905_MAX_TRANSFER ?
                                SQ905_MAX_TRANSFER : bytes_left;
                        ret = sq905_read_data(gspca_dev, buffer, data_len, 1);
@@ -278,7 +277,7 @@ static void sq905_dostream(struct work_struct *work)
                                gspca_frame_add(gspca_dev, LAST_PACKET,
                                                NULL, 0);
                }
-               if (gspca_dev->dev) {
+               if (gspca_dev->present) {
                        /* acknowledge the frame */
                        mutex_lock(&gspca_dev->usb_lock);
                        ret = sq905_ack_frame(gspca_dev);
@@ -288,7 +287,7 @@ static void sq905_dostream(struct work_struct *work)
                }
        }
 quit_stream:
-       if (gspca_dev->dev) {
+       if (gspca_dev->present) {
                mutex_lock(&gspca_dev->usb_lock);
                sq905_command(gspca_dev, SQ905_CLEAR);
                mutex_unlock(&gspca_dev->usb_lock);
similarity index 91%
rename from drivers/media/video/gspca/sq905c.c
rename to drivers/media/usb/gspca/sq905c.c
index 2c2f3d2f357f99afda2554d48feb89ede3fb8940..410cdcbb55d45984a9d81a9f630ad7bff4aca0bf 100644 (file)
@@ -123,15 +123,13 @@ static int sq905c_read(struct gspca_dev *gspca_dev, u16 command, u16 index,
        return 0;
 }
 
-/* This function is called as a workqueue function and runs whenever the camera
+/*
+ * This function is called as a workqueue function and runs whenever the camera
  * is streaming data. Because it is a workqueue function it is allowed to sleep
  * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface the gspca usb_lock is
- * used when performing the one USB control operation inside the workqueue,
- * which tells the camera to close the stream. In practice the only thing
- * which needs to be protected against is the usb_set_interface call that
- * gspca makes during stream_off. Otherwise the camera doesn't provide any
- * controls that the user could try to change.
+ * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
+ * performing USB operations using it. In practice we don't really need this
+ * as the camera doesn't provide any controls.
  */
 static void sq905c_dostream(struct work_struct *work)
 {
@@ -150,7 +148,7 @@ static void sq905c_dostream(struct work_struct *work)
                goto quit_stream;
        }
 
-       while (gspca_dev->dev && gspca_dev->streaming) {
+       while (gspca_dev->present && gspca_dev->streaming) {
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        break;
@@ -173,7 +171,7 @@ static void sq905c_dostream(struct work_struct *work)
                packet_type = FIRST_PACKET;
                gspca_frame_add(gspca_dev, packet_type,
                                buffer, FRAME_HEADER_LEN);
-               while (bytes_left > 0 && gspca_dev->dev) {
+               while (bytes_left > 0 && gspca_dev->present) {
                        data_len = bytes_left > SQ905C_MAX_TRANSFER ?
                                SQ905C_MAX_TRANSFER : bytes_left;
                        ret = usb_bulk_msg(gspca_dev->dev,
@@ -195,7 +193,7 @@ static void sq905c_dostream(struct work_struct *work)
                }
        }
 quit_stream:
-       if (gspca_dev->dev) {
+       if (gspca_dev->present) {
                mutex_lock(&gspca_dev->usb_lock);
                sq905c_command(gspca_dev, SQ905C_CLEAR, 0);
                mutex_unlock(&gspca_dev->usb_lock);
@@ -228,11 +226,8 @@ static int sd_config(struct gspca_dev *gspca_dev,
        }
        /* Note we leave out the usb id and the manufacturing date */
        PDEBUG(D_PROBE,
-              "SQ9050 ID string: %02x - %02x %02x %02x %02x %02x %02x",
-               gspca_dev->usb_buf[3],
-               gspca_dev->usb_buf[14], gspca_dev->usb_buf[15],
-               gspca_dev->usb_buf[16], gspca_dev->usb_buf[17],
-               gspca_dev->usb_buf[18], gspca_dev->usb_buf[19]);
+              "SQ9050 ID string: %02x - %*ph",
+               gspca_dev->usb_buf[3], 6, gspca_dev->usb_buf + 14);
 
        cam->cam_mode = sq905c_mode;
        cam->nmodes = 2;
similarity index 99%
rename from drivers/media/video/gspca/sq930x.c
rename to drivers/media/usb/gspca/sq930x.c
index 3e1e486af883dfaddc6cd8527c8c03a80dfd90c3..7e8748b31e858dddd1865735584d5657c531df02 100644 (file)
@@ -863,15 +863,7 @@ static int sd_init(struct gspca_dev *gspca_dev)
  * 6: c8 / c9 / ca / cf = mode webcam?, sensor? webcam?
  * 7: 00
  */
-       PDEBUG(D_PROBE, "info: %02x %02x %02x %02x %02x %02x %02x %02x",
-                       gspca_dev->usb_buf[0],
-                       gspca_dev->usb_buf[1],
-                       gspca_dev->usb_buf[2],
-                       gspca_dev->usb_buf[3],
-                       gspca_dev->usb_buf[4],
-                       gspca_dev->usb_buf[5],
-                       gspca_dev->usb_buf[6],
-                       gspca_dev->usb_buf[7]);
+       PDEBUG(D_PROBE, "info: %*ph", 8, gspca_dev->usb_buf);
 
        bridge_init(sd);
 
similarity index 78%
rename from drivers/media/video/gspca/stv06xx/Makefile
rename to drivers/media/usb/gspca/stv06xx/Makefile
index 38bc41061d8341b21455049ef24456b0a8306962..3a4b2f899049de856579231782aa8e809af59384 100644 (file)
@@ -6,5 +6,5 @@ gspca_stv06xx-objs := stv06xx.o \
                      stv06xx_pb0100.o \
                      stv06xx_st6422.o
 
-ccflags-y += -I$(srctree)/drivers/media/video/gspca
+ccflags-y += -I$(srctree)/drivers/media/usb/gspca
 
similarity index 99%
rename from drivers/media/video/gspca/topro.c
rename to drivers/media/usb/gspca/topro.c
index a6055246cb9d720c13dbd880c167a6aec94ba79c..4cb511ccc5f6ecbefadee9ef64de47f9fd75f3e2 100644 (file)
@@ -4806,7 +4806,7 @@ static void sd_set_streamparm(struct gspca_dev *gspca_dev,
 }
 
 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
+                       const struct v4l2_jpegcompression *jcomp)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
similarity index 99%
rename from drivers/media/video/gspca/vc032x.c
rename to drivers/media/usb/gspca/vc032x.c
index f21fd1677c388a383cea3583de2b7114bd460209..e50079503d9607fc33e107f2c56e079575f581a8 100644 (file)
@@ -2934,11 +2934,8 @@ static void reg_r(struct gspca_dev *gspca_dev,
                PDEBUG(D_USBI, "GET %02x 0001 %04x %02x", req, index,
                                gspca_dev->usb_buf[0]);
        else
-               PDEBUG(D_USBI, "GET %02x 0001 %04x %02x %02x %02x",
-                               req, index,
-                               gspca_dev->usb_buf[0],
-                               gspca_dev->usb_buf[1],
-                               gspca_dev->usb_buf[2]);
+               PDEBUG(D_USBI, "GET %02x 0001 %04x %*ph",
+                               req, index, 3, gspca_dev->usb_buf);
 #endif
 }
 
similarity index 94%
rename from drivers/media/video/gspca/vicam.c
rename to drivers/media/usb/gspca/vicam.c
index b1a64b912666a000647ef28af79bf3d8f67475a6..d6890bc3719862e54c87af2fe6b1f60ba958997e 100644 (file)
@@ -110,7 +110,7 @@ static int vicam_set_camera_power(struct gspca_dev *gspca_dev, int state)
 }
 
 /*
- *  request and read a block of data - see warning on vicam_command.
+ *  request and read a block of data
  */
 static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
 {
@@ -170,14 +170,13 @@ static int vicam_read_frame(struct gspca_dev *gspca_dev, u8 *data, int size)
        return 0;
 }
 
-/* This function is called as a workqueue function and runs whenever the camera
+/*
+ * This function is called as a workqueue function and runs whenever the camera
  * is streaming data. Because it is a workqueue function it is allowed to sleep
  * so we can use synchronous USB calls. To avoid possible collisions with other
- * threads attempting to use the camera's USB interface we take the gspca
- * usb_lock when performing USB operations. In practice the only thing we need
- * to protect against is the usb_set_interface call that gspca makes during
- * stream_off as the camera doesn't provide any controls that the user could try
- * to change.
+ * threads attempting to use gspca_dev->usb_buf we take the usb_lock when
+ * performing USB operations using it. In practice we don't really need this
+ * as the cameras controls are only written from the workqueue.
  */
 static void vicam_dostream(struct work_struct *work)
 {
@@ -194,7 +193,7 @@ static void vicam_dostream(struct work_struct *work)
                goto exit;
        }
 
-       while (gspca_dev->dev && gspca_dev->streaming) {
+       while (gspca_dev->present && gspca_dev->streaming) {
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        break;
@@ -299,7 +298,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
        dev->work_thread = NULL;
        mutex_lock(&gspca_dev->usb_lock);
 
-       if (gspca_dev->dev)
+       if (gspca_dev->present)
                vicam_set_camera_power(gspca_dev, 0);
 }
 
similarity index 99%
rename from drivers/media/video/gspca/xirlink_cit.c
rename to drivers/media/usb/gspca/xirlink_cit.c
index 13b8d395d21072040c089f13a41090f117d8e55f..d4b23c9bf90c0dad4427091c91a92257d502d23b 100644 (file)
@@ -2697,9 +2697,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
 
-       /* We cannot use gspca_dev->present here as that is not set when
-          sd_init gets called and we get called from sd_init */
-       if (!gspca_dev->dev)
+       if (!gspca_dev->present)
                return;
 
        switch (sd->model) {
similarity index 99%
rename from drivers/media/video/gspca/zc3xx.c
rename to drivers/media/usb/gspca/zc3xx.c
index f0bacee33ef9a4e22c7876030c026468336df1d8..77c57755e7b4623a07c81b2324fb20f291ee1dc0 100644 (file)
@@ -5945,12 +5945,13 @@ static void transfer_update(struct work_struct *work)
        for (;;) {
                msleep(100);
 
+               /* To protect gspca_dev->usb_buf and gspca_dev->usb_err */
                mutex_lock(&gspca_dev->usb_lock);
 #ifdef CONFIG_PM
                if (gspca_dev->frozen)
                        goto err;
 #endif
-               if (!gspca_dev->dev || !gspca_dev->streaming)
+               if (!gspca_dev->present || !gspca_dev->streaming)
                        goto err;
 
                /* Bit 0 of register 11 indicates FIFO overflow */
@@ -6831,7 +6832,8 @@ static int sd_start(struct gspca_dev *gspca_dev)
        return 0;
 }
 
-/* called on streamoff with alt 0 and on disconnect */
+/* called on streamoff with alt==0 and on disconnect */
+/* the usb_lock is held at entry - restore on exit */
 static void sd_stop0(struct gspca_dev *gspca_dev)
 {
        struct sd *sd = (struct sd *) gspca_dev;
@@ -6842,7 +6844,7 @@ static void sd_stop0(struct gspca_dev *gspca_dev)
                mutex_lock(&gspca_dev->usb_lock);
                sd->work_thread = NULL;
        }
-       if (!gspca_dev->dev)
+       if (!gspca_dev->present)
                return;
        send_unknown(gspca_dev, sd->sensor);
 }
@@ -6881,16 +6883,11 @@ static void sd_pkt_scan(struct gspca_dev *gspca_dev,
 }
 
 static int sd_set_jcomp(struct gspca_dev *gspca_dev,
-                       struct v4l2_jpegcompression *jcomp)
+                       const struct v4l2_jpegcompression *jcomp)
 {
        struct sd *sd = (struct sd *) gspca_dev;
-       int ret;
 
-       ret = v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
-       if (ret)
-               return ret;
-       jcomp->quality = v4l2_ctrl_g_ctrl(sd->jpegqual);
-       return 0;
+       return v4l2_ctrl_s_ctrl(sd->jpegqual, jcomp->quality);
 }
 
 static int sd_get_jcomp(struct gspca_dev *gspca_dev,
similarity index 81%
rename from drivers/media/video/hdpvr/Makefile
rename to drivers/media/usb/hdpvr/Makefile
index 52f057f24e3944a174b134bc65921abb55b78070..9b8d1463c52636dd18814ca3b8f61b7463a306eb 100644 (file)
@@ -2,6 +2,6 @@ hdpvr-objs      := hdpvr-control.o hdpvr-core.o hdpvr-video.o hdpvr-i2c.o
 
 obj-$(CONFIG_VIDEO_HDPVR) += hdpvr.o
 
-ccflags-y += -Idrivers/media/video
+ccflags-y += -Idrivers/media/i2c
 
 ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
similarity index 99%
rename from drivers/media/video/hdpvr/hdpvr-video.c
rename to drivers/media/usb/hdpvr/hdpvr-video.c
index 0e9e156bb2aa16c4bfa9e5a38fe4fa6053583383..da6b77912222421dffd5d808c4885c27d5647246 100644 (file)
@@ -677,7 +677,7 @@ static int vidioc_enumaudio(struct file *file, void *priv,
 }
 
 static int vidioc_s_audio(struct file *file, void *private_data,
-                         struct v4l2_audio *audio)
+                         const struct v4l2_audio *audio)
 {
        struct hdpvr_fh *fh = file->private_data;
        struct hdpvr_device *dev = fh->dev;
similarity index 82%
rename from drivers/media/video/pvrusb2/Kconfig
rename to drivers/media/usb/pvrusb2/Kconfig
index 25e412ecad2cf7bfb05087f2b4f6639485627690..32b11c15bb1a03702dff1023114954c772e4a5cd 100644 (file)
@@ -36,13 +36,13 @@ config VIDEO_PVRUSB2_DVB
        bool "pvrusb2 ATSC/DVB support (EXPERIMENTAL)"
        default y
        depends on VIDEO_PVRUSB2 && DVB_CORE && EXPERIMENTAL
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_SIMPLE if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
+       select DVB_LGDT330X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1409 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_S5H1411 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA10048 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA18271 if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_SIMPLE if MEDIA_SUBDRV_AUTOSELECT
+       select MEDIA_TUNER_TDA8290 if MEDIA_SUBDRV_AUTOSELECT
        ---help---
 
          This option enables a DVB interface for the pvrusb2 driver.
similarity index 80%
rename from drivers/media/video/pvrusb2/Makefile
rename to drivers/media/usb/pvrusb2/Makefile
index c17f37d964ad00460700abcc3a4105e3f84605d9..ad705547bdcedb7c448effb65cf35732317c4d3e 100644 (file)
@@ -16,7 +16,7 @@ pvrusb2-objs  := pvrusb2-i2c-core.o \
 
 obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
similarity index 97%
rename from drivers/media/video/pvrusb2/pvrusb2-devattr.c
rename to drivers/media/usb/pvrusb2/pvrusb2-devattr.c
index d8c898278e8ca9b2a40c0db69dfe1c139d82e5ef..adc501d3c287fe0f6ba8893abd58d06603440873 100644 (file)
@@ -54,8 +54,9 @@ static const struct pvr2_device_client_desc pvr2_cli_29xxx[] = {
        { .module_id = PVR2_CLIENT_ID_DEMOD },
 };
 
+#define PVR2_FIRMWARE_29xxx "v4l-pvrusb2-29xxx-01.fw"
 static const char *pvr2_fw1_names_29xxx[] = {
-               "v4l-pvrusb2-29xxx-01.fw",
+               PVR2_FIRMWARE_29xxx,
 };
 
 static const struct pvr2_device_desc pvr2_device_29xxx = {
@@ -87,8 +88,9 @@ static const struct pvr2_device_client_desc pvr2_cli_24xxx[] = {
        { .module_id = PVR2_CLIENT_ID_DEMOD },
 };
 
+#define PVR2_FIRMWARE_24xxx "v4l-pvrusb2-24xxx-01.fw"
 static const char *pvr2_fw1_names_24xxx[] = {
-               "v4l-pvrusb2-24xxx-01.fw",
+               PVR2_FIRMWARE_24xxx,
 };
 
 static const struct pvr2_device_desc pvr2_device_24xxx = {
@@ -369,8 +371,9 @@ static const struct pvr2_device_client_desc pvr2_cli_73xxx[] = {
          .i2c_address_list = "\x42"},
 };
 
+#define PVR2_FIRMWARE_73xxx "v4l-pvrusb2-73xxx-01.fw"
 static const char *pvr2_fw1_names_73xxx[] = {
-               "v4l-pvrusb2-73xxx-01.fw",
+               PVR2_FIRMWARE_73xxx,
 };
 
 static const struct pvr2_device_desc pvr2_device_73xxx = {
@@ -475,8 +478,9 @@ static const struct pvr2_dvb_props pvr2_751xx_dvb_props = {
 };
 #endif
 
+#define PVR2_FIRMWARE_75xxx "v4l-pvrusb2-73xxx-01.fw"
 static const char *pvr2_fw1_names_75xxx[] = {
-               "v4l-pvrusb2-73xxx-01.fw",
+               PVR2_FIRMWARE_75xxx,
 };
 
 static const struct pvr2_device_desc pvr2_device_750xx = {
@@ -556,7 +560,10 @@ struct usb_device_id pvr2_device_table[] = {
 };
 
 MODULE_DEVICE_TABLE(usb, pvr2_device_table);
-
+MODULE_FIRMWARE(PVR2_FIRMWARE_29xxx);
+MODULE_FIRMWARE(PVR2_FIRMWARE_24xxx);
+MODULE_FIRMWARE(PVR2_FIRMWARE_73xxx);
+MODULE_FIRMWARE(PVR2_FIRMWARE_75xxx);
 
 /*
   Stuff for Emacs to see, in order to encourage consistent editing style:
similarity index 99%
rename from drivers/media/video/pvrusb2/pvrusb2-v4l2.c
rename to drivers/media/usb/pvrusb2/pvrusb2-v4l2.c
index f344aed32a936cdcfcfd93c45c4ae377c79bdb7d..db249cad3cd975f1be344057d5d6cab7fda344f6 100644 (file)
@@ -333,7 +333,7 @@ static int pvr2_g_audio(struct file *file, void *priv, struct v4l2_audio *vin)
        return 0;
 }
 
-static int pvr2_s_audio(struct file *file, void *priv, struct v4l2_audio *vout)
+static int pvr2_s_audio(struct file *file, void *priv, const struct v4l2_audio *vout)
 {
        if (vout->index)
                return -EINVAL;
@@ -760,7 +760,7 @@ static int pvr2_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
        return 0;
 }
 
-static int pvr2_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+static int pvr2_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
 {
        struct pvr2_v4l2_fh *fh = file->private_data;
        struct pvr2_hdw *hdw = fh->channel.mc_head->hdw;
similarity index 60%
rename from drivers/media/video/pwc/Makefile
rename to drivers/media/usb/pwc/Makefile
index f5c8ec261e87d1cf64412c6bfbaf31529ceeb82c..d7fdbcb9edd301c32c5bf8f92eee7429a12d1c44 100644 (file)
@@ -1,4 +1,4 @@
-pwc-objs       := pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
+pwc-objs       += pwc-if.o pwc-misc.o pwc-ctrl.o pwc-v4l.o pwc-uncompress.o
 pwc-objs       += pwc-dec1.o pwc-dec23.o pwc-kiara.o pwc-timon.o
 
 obj-$(CONFIG_USB_PWC) += pwc.o
similarity index 99%
rename from drivers/media/video/pwc/pwc-if.c
rename to drivers/media/usb/pwc/pwc-if.c
index de7c7ba99ef494bd60bf9ae659c0d1e72b80608b..42e36bac4d72a93add64b485652fc957bf0a30a3 100644 (file)
@@ -994,7 +994,6 @@ static int usb_pwc_probe(struct usb_interface *intf, const struct usb_device_id
        pdev->power_save = my_power_save;
 
        /* Init videobuf2 queue structure */
-       memset(&pdev->vb_queue, 0, sizeof(pdev->vb_queue));
        pdev->vb_queue.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
        pdev->vb_queue.io_modes = VB2_MMAP | VB2_USERPTR | VB2_READ;
        pdev->vb_queue.drv_priv = pdev;
@@ -1127,7 +1126,7 @@ static void usb_pwc_disconnect(struct usb_interface *intf)
        v4l2_device_disconnect(&pdev->v4l2_dev);
        video_unregister_device(&pdev->vdev);
        mutex_unlock(&pdev->v4l2_lock);
-       mutex_unlock(pdev->vb_queue.lock);
+       mutex_unlock(&pdev->vb_queue_lock);
 
 #ifdef CONFIG_USB_PWC_INPUT_EVDEV
        if (pdev->button_dev)
diff --git a/drivers/media/usb/s2255/Kconfig b/drivers/media/usb/s2255/Kconfig
new file mode 100644 (file)
index 0000000..7e8ee1f
--- /dev/null
@@ -0,0 +1,9 @@
+config USB_S2255
+       tristate "USB Sensoray 2255 video capture device"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_VMALLOC
+       default n
+       help
+         Say Y here if you want support for the Sensoray 2255 USB device.
+         This driver can be compiled as a module, called s2255drv.
+
diff --git a/drivers/media/usb/s2255/Makefile b/drivers/media/usb/s2255/Makefile
new file mode 100644 (file)
index 0000000..197d0bb
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_USB_S2255)                += s2255drv.o
+
similarity index 99%
rename from drivers/media/video/s2255drv.c
rename to drivers/media/usb/s2255/s2255drv.c
index 95007dda0c93e8ed8a2395d0dd63ba05f3064583..2191f6ddf9e7536883a6b7e7973ceeba30b0ef61 100644 (file)
@@ -258,7 +258,6 @@ struct s2255_dev {
        atomic_t                num_channels;
        int                     frames;
        struct mutex            lock;   /* channels[].vdev.lock */
-       struct mutex            open_lock;
        struct usb_device       *udev;
        struct usb_interface    *interface;
        u8                      read_endpoint;
@@ -1557,7 +1556,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
 }
 
 static int vidioc_s_jpegcomp(struct file *file, void *priv,
-                        struct v4l2_jpegcompression *jc)
+                        const struct v4l2_jpegcompression *jc)
 {
        struct s2255_fh *fh = priv;
        struct s2255_channel *channel = fh->channel;
@@ -1684,7 +1683,7 @@ static int vidioc_enum_frameintervals(struct file *file, void *priv,
        return 0;
 }
 
-static int s2255_open(struct file *file)
+static int __s2255_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct s2255_channel *channel = video_drvdata(file);
@@ -1694,16 +1693,9 @@ static int s2255_open(struct file *file)
        int state;
        dprintk(1, "s2255: open called (dev=%s)\n",
                video_device_node_name(vdev));
-       /*
-        * open lock necessary to prevent multiple instances
-        * of v4l-conf (or other programs) from simultaneously
-        * reloading firmware.
-        */
-       mutex_lock(&dev->open_lock);
        state = atomic_read(&dev->fw_data->fw_state);
        switch (state) {
        case S2255_FW_DISCONNECTING:
-               mutex_unlock(&dev->open_lock);
                return -ENODEV;
        case S2255_FW_FAILED:
                s2255_dev_err(&dev->udev->dev,
@@ -1742,11 +1734,9 @@ static int s2255_open(struct file *file)
                break;
        case S2255_FW_FAILED:
                printk(KERN_INFO "2255 firmware load failed.\n");
-               mutex_unlock(&dev->open_lock);
                return -ENODEV;
        case S2255_FW_DISCONNECTING:
                printk(KERN_INFO "%s: disconnecting\n", __func__);
-               mutex_unlock(&dev->open_lock);
                return -ENODEV;
        case S2255_FW_LOADED_DSPWAIT:
        case S2255_FW_NOTLOADED:
@@ -1760,14 +1750,11 @@ static int s2255_open(struct file *file)
                 */
                atomic_set(&dev->fw_data->fw_state,
                           S2255_FW_FAILED);
-               mutex_unlock(&dev->open_lock);
                return -EAGAIN;
        default:
                printk(KERN_INFO "%s: unknown state\n", __func__);
-               mutex_unlock(&dev->open_lock);
                return -EFAULT;
        }
-       mutex_unlock(&dev->open_lock);
        /* allocate + initialize per filehandle data */
        fh = kzalloc(sizeof(*fh), GFP_KERNEL);
        if (NULL == fh)
@@ -1798,16 +1785,30 @@ static int s2255_open(struct file *file)
        return 0;
 }
 
+static int s2255_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       int ret;
+
+       if (mutex_lock_interruptible(vdev->lock))
+               return -ERESTARTSYS;
+       ret = __s2255_open(file);
+       mutex_unlock(vdev->lock);
+       return ret;
+}
 
 static unsigned int s2255_poll(struct file *file,
                               struct poll_table_struct *wait)
 {
        struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev = fh->dev;
        int rc;
        dprintk(100, "%s\n", __func__);
        if (V4L2_BUF_TYPE_VIDEO_CAPTURE != fh->type)
                return POLLERR;
+       mutex_lock(&dev->lock);
        rc = videobuf_poll_stream(file, &fh->vb_vidq, wait);
+       mutex_unlock(&dev->lock);
        return rc;
 }
 
@@ -1827,7 +1828,6 @@ static void s2255_destroy(struct s2255_dev *dev)
        kfree(dev->fw_data);
        /* reset the DSP so firmware can be reloaded next time */
        s2255_reset_dsppower(dev);
-       mutex_destroy(&dev->open_lock);
        mutex_destroy(&dev->lock);
        usb_put_dev(dev->udev);
        v4l2_device_unregister(&dev->v4l2_dev);
@@ -1843,6 +1843,7 @@ static int s2255_release(struct file *file)
        struct s2255_channel *channel = fh->channel;
        if (!dev)
                return -ENODEV;
+       mutex_lock(&dev->lock);
        /* turn off stream */
        if (res_check(fh)) {
                if (channel->b_acquire)
@@ -1851,6 +1852,7 @@ static int s2255_release(struct file *file)
                res_free(fh);
        }
        videobuf_mmap_free(&fh->vb_vidq);
+       mutex_unlock(&dev->lock);
        dprintk(1, "%s (dev=%s)\n", __func__, video_device_node_name(vdev));
        kfree(fh);
        return 0;
@@ -1859,12 +1861,17 @@ static int s2255_release(struct file *file)
 static int s2255_mmap_v4l(struct file *file, struct vm_area_struct *vma)
 {
        struct s2255_fh *fh = file->private_data;
+       struct s2255_dev *dev;
        int ret;
 
        if (!fh)
                return -ENODEV;
+       dev = fh->dev;
        dprintk(4, "%s, vma=0x%08lx\n", __func__, (unsigned long)vma);
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
        ret = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
        dprintk(4, "%s vma start=0x%08lx, size=%ld, ret=%d\n", __func__,
                (unsigned long)vma->vm_start,
                (unsigned long)vma->vm_end - (unsigned long)vma->vm_start, ret);
@@ -1944,10 +1951,6 @@ static int s2255_probe_v4l(struct s2255_dev *dev)
                /* register 4 video devices */
                channel->vdev = template;
                channel->vdev.lock = &dev->lock;
-               /* Locking in file operations other than ioctl should be done
-                  by the driver, not the V4L2 core.
-                  This driver needs auditing so that this flag can be removed. */
-               set_bit(V4L2_FL_LOCK_ALL_FOPS, &channel->vdev.flags);
                channel->vdev.v4l2_dev = &dev->v4l2_dev;
                video_set_drvdata(&channel->vdev, channel);
                if (video_nr == -1)
@@ -2535,7 +2538,6 @@ static int s2255_probe(struct usb_interface *interface,
        if (!dev->fw_data)
                goto errorFWDATA1;
        mutex_init(&dev->lock);
-       mutex_init(&dev->open_lock);
        /* grab usb_device and save it */
        dev->udev = usb_get_dev(interface_to_usbdev(interface));
        if (dev->udev == NULL) {
@@ -2637,7 +2639,6 @@ errorEP:
        usb_put_dev(dev->udev);
 errorUDEV:
        kfree(dev->fw_data);
-       mutex_destroy(&dev->open_lock);
        mutex_destroy(&dev->lock);
 errorFWDATA1:
        kfree(dev);
diff --git a/drivers/media/usb/siano/Kconfig b/drivers/media/usb/siano/Kconfig
new file mode 100644 (file)
index 0000000..3c76e62
--- /dev/null
@@ -0,0 +1,10 @@
+#
+# Siano Mobile Silicon Digital TV device configuration
+#
+
+config SMS_USB_DRV
+       tristate "Siano SMS1xxx based MDTV receiver"
+       depends on DVB_CORE && RC_CORE && HAS_DMA
+       ---help---
+         Choose if you would like to have Siano's support for USB interface
+
diff --git a/drivers/media/usb/siano/Makefile b/drivers/media/usb/siano/Makefile
new file mode 100644 (file)
index 0000000..758b6a0
--- /dev/null
@@ -0,0 +1,6 @@
+obj-$(CONFIG_SMS_USB_DRV) += smsusb.o
+
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/common/siano
+ccflags-y += $(extra-cflags-y) $(extra-cflags-m)
+
diff --git a/drivers/media/usb/stk1160/Kconfig b/drivers/media/usb/stk1160/Kconfig
new file mode 100644 (file)
index 0000000..1c3a1ec
--- /dev/null
@@ -0,0 +1,20 @@
+config VIDEO_STK1160
+       tristate "STK1160 USB video capture support"
+       depends on VIDEO_DEV && I2C
+       select VIDEOBUF2_VMALLOC
+       select VIDEO_SAA711X
+
+       ---help---
+         This is a video4linux driver for STK1160 based video capture devices.
+
+         To compile this driver as a module, choose M here: the
+         module will be called stk1160
+
+config VIDEO_STK1160_AC97
+       bool "STK1160 AC97 codec support"
+       depends on VIDEO_STK1160 && SND
+       select SND_AC97_CODEC
+
+       ---help---
+         Enables AC97 codec support for stk1160 driver.
+.
diff --git a/drivers/media/usb/stk1160/Makefile b/drivers/media/usb/stk1160/Makefile
new file mode 100644 (file)
index 0000000..dfe3e90
--- /dev/null
@@ -0,0 +1,11 @@
+obj-stk1160-ac97-$(CONFIG_VIDEO_STK1160_AC97) := stk1160-ac97.o
+
+stk1160-y :=   stk1160-core.o \
+               stk1160-v4l.o \
+               stk1160-video.o \
+               stk1160-i2c.o \
+               $(obj-stk1160-ac97-y)
+
+obj-$(CONFIG_VIDEO_STK1160) += stk1160.o
+
+ccflags-y += -Idrivers/media/i2c
diff --git a/drivers/media/usb/stk1160/stk1160-ac97.c b/drivers/media/usb/stk1160/stk1160-ac97.c
new file mode 100644 (file)
index 0000000..c8583c2
--- /dev/null
@@ -0,0 +1,152 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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 <sound/core.h>
+#include <sound/initval.h>
+#include <sound/ac97_codec.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static struct snd_ac97 *stk1160_ac97;
+
+static void stk1160_write_ac97(struct snd_ac97 *ac97, u16 reg, u16 value)
+{
+       struct stk1160 *dev = ac97->private_data;
+
+       /* Set codec register address */
+       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
+
+       /* Set codec command */
+       stk1160_write_reg(dev, STK1160_AC97_CMD, value & 0xff);
+       stk1160_write_reg(dev, STK1160_AC97_CMD + 1, (value & 0xff00) >> 8);
+
+       /*
+        * Set command write bit to initiate write operation.
+        * The bit will be cleared when transfer is done.
+        */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8c);
+}
+
+static u16 stk1160_read_ac97(struct snd_ac97 *ac97, u16 reg)
+{
+       struct stk1160 *dev = ac97->private_data;
+       u8 vall = 0;
+       u8 valh = 0;
+
+       /* Set codec register address */
+       stk1160_write_reg(dev, STK1160_AC97_ADDR, reg);
+
+       /*
+        * Set command read bit to initiate read operation.
+        * The bit will be cleared when transfer is done.
+        */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x8b);
+
+       /* Retrieve register value */
+       stk1160_read_reg(dev, STK1160_AC97_CMD, &vall);
+       stk1160_read_reg(dev, STK1160_AC97_CMD + 1, &valh);
+
+       return (valh << 8) | vall;
+}
+
+static void stk1160_reset_ac97(struct snd_ac97 *ac97)
+{
+       struct stk1160 *dev = ac97->private_data;
+       /* Two-step reset AC97 interface and hardware codec */
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x94);
+       stk1160_write_reg(dev, STK1160_AC97CTL_0, 0x88);
+
+       /* Set 16-bit audio data and choose L&R channel*/
+       stk1160_write_reg(dev, STK1160_AC97CTL_1 + 2, 0x01);
+}
+
+static struct snd_ac97_bus_ops stk1160_ac97_ops = {
+       .read   = stk1160_read_ac97,
+       .write  = stk1160_write_ac97,
+       .reset  = stk1160_reset_ac97,
+};
+
+int stk1160_ac97_register(struct stk1160 *dev)
+{
+       struct snd_card *card = NULL;
+       struct snd_ac97_bus *ac97_bus;
+       struct snd_ac97_template ac97_template;
+       int rc;
+
+       /*
+        * Just want a card to access ac96 controls,
+        * the actual capture interface will be handled by snd-usb-audio
+        */
+       rc = snd_card_create(SNDRV_DEFAULT_IDX1, SNDRV_DEFAULT_STR1,
+                             THIS_MODULE, 0, &card);
+       if (rc < 0)
+               return rc;
+
+       snd_card_set_dev(card, dev->dev);
+
+       /* TODO: I'm not sure where should I get these names :-( */
+       snprintf(card->shortname, sizeof(card->shortname),
+                "stk1160-mixer");
+       snprintf(card->longname, sizeof(card->longname),
+                "stk1160 ac97 codec mixer control");
+       strncpy(card->driver, dev->dev->driver->name, sizeof(card->driver));
+
+       rc = snd_ac97_bus(card, 0, &stk1160_ac97_ops, NULL, &ac97_bus);
+       if (rc)
+               goto err;
+
+       /* We must set private_data before calling snd_ac97_mixer */
+       memset(&ac97_template, 0, sizeof(ac97_template));
+       ac97_template.private_data = dev;
+       ac97_template.scaps = AC97_SCAP_SKIP_MODEM;
+       rc = snd_ac97_mixer(ac97_bus, &ac97_template, &stk1160_ac97);
+       if (rc)
+               goto err;
+
+       dev->snd_card = card;
+       rc = snd_card_register(card);
+       if (rc)
+               goto err;
+
+       return 0;
+
+err:
+       dev->snd_card = NULL;
+       snd_card_free(card);
+       return rc;
+}
+
+int stk1160_ac97_unregister(struct stk1160 *dev)
+{
+       struct snd_card *card = dev->snd_card;
+
+       /*
+        * We need to check usb_device,
+        * because ac97 release attempts to communicate with codec
+        */
+       if (card && dev->udev)
+               snd_card_free(card);
+
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-core.c b/drivers/media/usb/stk1160/stk1160-core.c
new file mode 100644 (file)
index 0000000..b627408
--- /dev/null
@@ -0,0 +1,430 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ * TODO:
+ *
+ * 1. (Try to) detect if we must register ac97 mixer
+ * 2. Support stream at lower speed: lower frame rate or lower frame size.
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+#include <linux/errno.h>
+#include <linux/slab.h>
+
+#include <linux/usb.h>
+#include <linux/mm.h>
+#include <linux/vmalloc.h>
+#include <media/saa7115.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static unsigned int input;
+module_param(input, int, 0644);
+MODULE_PARM_DESC(input, "Set default input");
+
+MODULE_LICENSE("GPL");
+MODULE_AUTHOR("Ezequiel Garcia");
+MODULE_DESCRIPTION("STK1160 driver");
+
+/* Devices supported by this driver */
+static struct usb_device_id stk1160_id_table[] = {
+       { USB_DEVICE(0x05e1, 0x0408) },
+       { }
+};
+MODULE_DEVICE_TABLE(usb, stk1160_id_table);
+
+/* saa7113 I2C address */
+static unsigned short saa7113_addrs[] = {
+       0x4a >> 1,
+       I2C_CLIENT_END
+};
+
+/*
+ * Read/Write stk registers
+ */
+int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value)
+{
+       int ret;
+       int pipe = usb_rcvctrlpipe(dev->udev, 0);
+
+       *value = 0;
+       ret = usb_control_msg(dev->udev, pipe, 0x00,
+                       USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       0x00, reg, value, sizeof(u8), HZ);
+       if (ret < 0) {
+               stk1160_err("read failed on reg 0x%x (%d)\n",
+                       reg, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value)
+{
+       int ret;
+       int pipe = usb_sndctrlpipe(dev->udev, 0);
+
+       ret =  usb_control_msg(dev->udev, pipe, 0x01,
+                       USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE,
+                       value, reg, NULL, 0, HZ);
+       if (ret < 0) {
+               stk1160_err("write failed on reg 0x%x (%d)\n",
+                       reg, ret);
+               return ret;
+       }
+
+       return 0;
+}
+
+void stk1160_select_input(struct stk1160 *dev)
+{
+       static const u8 gctrl[] = {
+               0x98, 0x90, 0x88, 0x80
+       };
+
+       if (dev->ctl_input < ARRAY_SIZE(gctrl))
+               stk1160_write_reg(dev, STK1160_GCTRL, gctrl[dev->ctl_input]);
+}
+
+/* TODO: We should break this into pieces */
+static void stk1160_reg_reset(struct stk1160 *dev)
+{
+       int i;
+
+       static const struct regval ctl[] = {
+               {STK1160_GCTRL+2, 0x0078},
+
+               {STK1160_RMCTL+1, 0x0000},
+               {STK1160_RMCTL+3, 0x0002},
+
+               {STK1160_PLLSO,   0x0010},
+               {STK1160_PLLSO+1, 0x0000},
+               {STK1160_PLLSO+2, 0x0014},
+               {STK1160_PLLSO+3, 0x000E},
+
+               {STK1160_PLLFD,   0x0046},
+
+               /* Timing generator setup */
+               {STK1160_TIGEN,   0x0012},
+               {STK1160_TICTL,   0x002D},
+               {STK1160_TICTL+1, 0x0001},
+               {STK1160_TICTL+2, 0x0000},
+               {STK1160_TICTL+3, 0x0000},
+               {STK1160_TIGEN,   0x0080},
+
+               {0xffff, 0xffff}
+       };
+
+       for (i = 0; ctl[i].reg != 0xffff; i++)
+               stk1160_write_reg(dev, ctl[i].reg, ctl[i].val);
+}
+
+static void stk1160_release(struct v4l2_device *v4l2_dev)
+{
+       struct stk1160 *dev = container_of(v4l2_dev, struct stk1160, v4l2_dev);
+
+       stk1160_info("releasing all resources\n");
+
+       stk1160_i2c_unregister(dev);
+
+       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+       v4l2_device_unregister(&dev->v4l2_dev);
+       kfree(dev->alt_max_pkt_size);
+       kfree(dev);
+}
+
+/* high bandwidth multiplier, as encoded in highspeed endpoint descriptors */
+#define hb_mult(wMaxPacketSize) (1 + (((wMaxPacketSize) >> 11) & 0x03))
+
+/*
+ * Scan usb interface and populate max_pkt_size array
+ * with information on each alternate setting.
+ * The array should be allocated by the caller.
+ */
+static int stk1160_scan_usb(struct usb_interface *intf, struct usb_device *udev,
+               unsigned int *max_pkt_size)
+{
+       int i, e, sizedescr, size, ifnum;
+       const struct usb_endpoint_descriptor *desc;
+
+       bool has_video = false, has_audio = false;
+       const char *speed;
+
+       ifnum = intf->altsetting[0].desc.bInterfaceNumber;
+
+       /* Get endpoints */
+       for (i = 0; i < intf->num_altsetting; i++) {
+
+               for (e = 0; e < intf->altsetting[i].desc.bNumEndpoints; e++) {
+
+                       /* This isn't clear enough, at least to me */
+                       desc = &intf->altsetting[i].endpoint[e].desc;
+                       sizedescr = le16_to_cpu(desc->wMaxPacketSize);
+                       size = sizedescr & 0x7ff;
+
+                       if (udev->speed == USB_SPEED_HIGH)
+                               size = size * hb_mult(sizedescr);
+
+                       if (usb_endpoint_xfer_isoc(desc) &&
+                           usb_endpoint_dir_in(desc)) {
+                               switch (desc->bEndpointAddress) {
+                               case STK1160_EP_AUDIO:
+                                       has_audio = true;
+                                       break;
+                               case STK1160_EP_VIDEO:
+                                       has_video = true;
+                                       max_pkt_size[i] = size;
+                                       break;
+                               }
+                       }
+               }
+       }
+
+       /* Is this even possible? */
+       if (!(has_audio || has_video)) {
+               dev_err(&udev->dev, "no audio or video endpoints found\n");
+               return -ENODEV;
+       }
+
+       switch (udev->speed) {
+       case USB_SPEED_LOW:
+               speed = "1.5";
+               break;
+       case USB_SPEED_FULL:
+               speed = "12";
+               break;
+       case USB_SPEED_HIGH:
+               speed = "480";
+               break;
+       default:
+               speed = "unknown";
+       }
+
+       dev_info(&udev->dev, "New device %s %s @ %s Mbps (%04x:%04x, interface %d, class %d)\n",
+               udev->manufacturer ? udev->manufacturer : "",
+               udev->product ? udev->product : "",
+               speed,
+               le16_to_cpu(udev->descriptor.idVendor),
+               le16_to_cpu(udev->descriptor.idProduct),
+               ifnum,
+               intf->altsetting->desc.bInterfaceNumber);
+
+       /* This should never happen, since we rejected audio interfaces */
+       if (has_audio)
+               dev_warn(&udev->dev, "audio interface %d found.\n\
+                               This is not implemented by this driver,\
+                               you should use snd-usb-audio instead\n", ifnum);
+
+       if (has_video)
+               dev_info(&udev->dev, "video interface %d found\n",
+                               ifnum);
+
+       /*
+        * Make sure we have 480 Mbps of bandwidth, otherwise things like
+        * video stream wouldn't likely work, since 12 Mbps is generally
+        * not enough even for most streams.
+        */
+       if (udev->speed != USB_SPEED_HIGH)
+               dev_warn(&udev->dev, "must be connected to a high-speed USB 2.0 port\n\
+                               You may not be able to stream video smoothly\n");
+
+       return 0;
+}
+
+static int stk1160_probe(struct usb_interface *interface,
+               const struct usb_device_id *id)
+{
+       int rc = 0;
+
+       unsigned int *alt_max_pkt_size; /* array of wMaxPacketSize */
+       struct usb_device *udev;
+       struct stk1160 *dev;
+
+       udev = interface_to_usbdev(interface);
+
+       /*
+        * Since usb audio class is supported by snd-usb-audio,
+        * we reject audio interface.
+        */
+       if (interface->altsetting[0].desc.bInterfaceClass == USB_CLASS_AUDIO)
+               return -ENODEV;
+
+       /* Alloc an array for all possible max_pkt_size */
+       alt_max_pkt_size = kmalloc(sizeof(alt_max_pkt_size[0]) *
+                       interface->num_altsetting, GFP_KERNEL);
+       if (alt_max_pkt_size == NULL)
+               return -ENOMEM;
+
+       /*
+        * Scan usb posibilities and populate alt_max_pkt_size array.
+        * Also, check if device speed is fast enough.
+        */
+       rc = stk1160_scan_usb(interface, udev, alt_max_pkt_size);
+       if (rc < 0) {
+               kfree(alt_max_pkt_size);
+               return rc;
+       }
+
+       dev = kzalloc(sizeof(struct stk1160), GFP_KERNEL);
+       if (dev == NULL) {
+               kfree(alt_max_pkt_size);
+               return -ENOMEM;
+       }
+
+       dev->alt_max_pkt_size = alt_max_pkt_size;
+       dev->udev = udev;
+       dev->num_alt = interface->num_altsetting;
+       dev->ctl_input = input;
+
+       /* We save struct device for debug purposes only */
+       dev->dev = &interface->dev;
+
+       usb_set_intfdata(interface, dev);
+
+       /* initialize videobuf2 stuff */
+       rc = stk1160_vb2_setup(dev);
+       if (rc < 0)
+               goto free_err;
+
+       /*
+        * There is no need to take any locks here in probe
+        * because we register the device node as the *last* thing.
+        */
+       spin_lock_init(&dev->buf_lock);
+       mutex_init(&dev->v4l_lock);
+       mutex_init(&dev->vb_queue_lock);
+
+       rc = v4l2_ctrl_handler_init(&dev->ctrl_handler, 0);
+       if (rc) {
+               stk1160_err("v4l2_ctrl_handler_init failed (%d)\n", rc);
+               goto free_err;
+       }
+
+       /*
+        * We obtain a v4l2_dev but defer
+        * registration of video device node as the last thing.
+        * There is no need to set the name if we give a device struct
+        */
+       dev->v4l2_dev.release = stk1160_release;
+       dev->v4l2_dev.ctrl_handler = &dev->ctrl_handler;
+       rc = v4l2_device_register(dev->dev, &dev->v4l2_dev);
+       if (rc) {
+               stk1160_err("v4l2_device_register failed (%d)\n", rc);
+               goto free_ctrl;
+       }
+
+       rc = stk1160_i2c_register(dev);
+       if (rc < 0)
+               goto unreg_v4l2;
+
+       /*
+        * To the best of my knowledge stk1160 boards only have
+        * saa7113, but it doesn't hurt to support them all.
+        */
+       dev->sd_saa7115 = v4l2_i2c_new_subdev(&dev->v4l2_dev, &dev->i2c_adap,
+               "saa7115_auto", 0, saa7113_addrs);
+
+       stk1160_info("driver ver %s successfully loaded\n",
+               STK1160_VERSION);
+
+       /* i2c reset saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, reset, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_routing,
+                               0, 0, 0);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+
+       /* reset stk1160 to default values */
+       stk1160_reg_reset(dev);
+
+       /* select default input */
+       stk1160_select_input(dev);
+
+       stk1160_ac97_register(dev);
+
+       rc = stk1160_video_register(dev);
+       if (rc < 0)
+               goto unreg_i2c;
+
+       return 0;
+
+unreg_i2c:
+       stk1160_i2c_unregister(dev);
+unreg_v4l2:
+       v4l2_device_unregister(&dev->v4l2_dev);
+free_ctrl:
+       v4l2_ctrl_handler_free(&dev->ctrl_handler);
+free_err:
+       kfree(alt_max_pkt_size);
+       kfree(dev);
+
+       return rc;
+}
+
+static void stk1160_disconnect(struct usb_interface *interface)
+{
+       struct stk1160 *dev;
+
+       dev = usb_get_intfdata(interface);
+       usb_set_intfdata(interface, NULL);
+
+       /*
+        * Wait until all current v4l2 operation are finished
+        * then deallocate resources
+        */
+       mutex_lock(&dev->vb_queue_lock);
+       mutex_lock(&dev->v4l_lock);
+
+       /* Here is the only place where isoc get released */
+       stk1160_uninit_isoc(dev);
+
+       /* ac97 unregister needs to be done before usb_device is cleared */
+       stk1160_ac97_unregister(dev);
+
+       stk1160_clear_queue(dev);
+
+       video_unregister_device(&dev->vdev);
+       v4l2_device_disconnect(&dev->v4l2_dev);
+
+       /* This way current users can detect device is gone */
+       dev->udev = NULL;
+
+       mutex_unlock(&dev->v4l_lock);
+       mutex_unlock(&dev->vb_queue_lock);
+
+       /*
+        * This calls stk1160_release if it's the last reference.
+        * therwise, release is posponed until there are no users left.
+        */
+       v4l2_device_put(&dev->v4l2_dev);
+}
+
+static struct usb_driver stk1160_usb_driver = {
+       .name = "stk1160",
+       .id_table = stk1160_id_table,
+       .probe = stk1160_probe,
+       .disconnect = stk1160_disconnect,
+};
+
+module_usb_driver(stk1160_usb_driver);
diff --git a/drivers/media/usb/stk1160/stk1160-i2c.c b/drivers/media/usb/stk1160/stk1160-i2c.c
new file mode 100644 (file)
index 0000000..176ac93
--- /dev/null
@@ -0,0 +1,294 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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/usb.h>
+#include <linux/i2c.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static unsigned int i2c_debug;
+module_param(i2c_debug, int, 0644);
+MODULE_PARM_DESC(i2c_debug, "enable debug messages [i2c]");
+
+#define dprintk_i2c(fmt, args...)                              \
+do {                                                           \
+       if (i2c_debug)                                          \
+               printk(KERN_DEBUG fmt, ##args);                 \
+} while (0)
+
+static int stk1160_i2c_busy_wait(struct stk1160 *dev, u8 wait_bit_mask)
+{
+       unsigned long end;
+       u8 flag;
+
+       /* Wait until read/write finish bit is set */
+       end = jiffies + msecs_to_jiffies(STK1160_I2C_TIMEOUT);
+       while (time_is_after_jiffies(end)) {
+
+               stk1160_read_reg(dev, STK1160_SICTL+1, &flag);
+               /* read/write done? */
+               if (flag & wait_bit_mask)
+                       goto done;
+
+               usleep_range(10 * USEC_PER_MSEC, 20 * USEC_PER_MSEC);
+       }
+
+       return -ETIMEDOUT;
+
+done:
+       return 0;
+}
+
+static int stk1160_i2c_write_reg(struct stk1160 *dev, u8 addr,
+               u8 reg, u8 value)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register sub-address */
+       rc = stk1160_write_reg(dev, STK1160_SBUSW_WA, reg);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register value */
+       rc = stk1160_write_reg(dev, STK1160_SBUSW_WD, value);
+       if (rc < 0)
+               return rc;
+
+       /* Start write now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x01);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x04);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+static int stk1160_i2c_read_reg(struct stk1160 *dev, u8 addr,
+               u8 reg, u8 *value)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set i2c device register sub-address */
+       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, reg);
+       if (rc < 0)
+               return rc;
+
+       /* Start read now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x01);
+       if (rc < 0)
+               return rc;
+
+       stk1160_read_reg(dev, STK1160_SBUSR_RD, value);
+       if (rc < 0)
+               return rc;
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_check_for_device()
+ * check if there is a i2c_device at the supplied address
+ */
+static int stk1160_i2c_check_for_device(struct stk1160 *dev,
+               unsigned char addr)
+{
+       int rc;
+
+       /* Set serial device address */
+       rc = stk1160_write_reg(dev, STK1160_SICTL_SDA, addr);
+       if (rc < 0)
+               return rc;
+
+       /* Set device sub-address, we'll chip version reg */
+       rc = stk1160_write_reg(dev, STK1160_SBUSR_RA, 0x00);
+       if (rc < 0)
+               return rc;
+
+       /* Start read now */
+       rc = stk1160_write_reg(dev, STK1160_SICTL, 0x20);
+       if (rc < 0)
+               return rc;
+
+       rc = stk1160_i2c_busy_wait(dev, 0x01);
+       if (rc < 0)
+               return -ENODEV;
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_xfer()
+ * the main i2c transfer function
+ */
+static int stk1160_i2c_xfer(struct i2c_adapter *i2c_adap,
+                          struct i2c_msg msgs[], int num)
+{
+       struct stk1160 *dev = i2c_adap->algo_data;
+       int addr, rc, i;
+
+       for (i = 0; i < num; i++) {
+               addr = msgs[i].addr << 1;
+               dprintk_i2c("%s: addr=%x", __func__, addr);
+
+               if (!msgs[i].len) {
+                       /* no len: check only for device presence */
+                       rc = stk1160_i2c_check_for_device(dev, addr);
+                       if (rc < 0) {
+                               dprintk_i2c(" no device\n");
+                               return rc;
+                       }
+
+               } else if (msgs[i].flags & I2C_M_RD) {
+                       /* read request without preceding register selection */
+                       dprintk_i2c(" subaddr not selected");
+                       rc = -EOPNOTSUPP;
+                       goto err;
+
+               } else if (i + 1 < num && msgs[i].len <= 2 &&
+                          (msgs[i + 1].flags & I2C_M_RD) &&
+                          msgs[i].addr == msgs[i + 1].addr) {
+
+                       if (msgs[i].len != 1 || msgs[i + 1].len != 1) {
+                               dprintk_i2c(" len not supported");
+                               rc = -EOPNOTSUPP;
+                               goto err;
+                       }
+
+                       dprintk_i2c(" subaddr=%x", msgs[i].buf[0]);
+
+                       rc = stk1160_i2c_read_reg(dev, addr, msgs[i].buf[0],
+                               msgs[i + 1].buf);
+
+                       dprintk_i2c(" read=%x", *msgs[i + 1].buf);
+
+                       /* consumed two msgs, so we skip one of them */
+                       i++;
+
+               } else {
+                       if (msgs[i].len != 2) {
+                               dprintk_i2c(" len not supported");
+                               rc = -EOPNOTSUPP;
+                               goto err;
+                       }
+
+                       dprintk_i2c(" subaddr=%x write=%x",
+                               msgs[i].buf[0],  msgs[i].buf[1]);
+
+                       rc = stk1160_i2c_write_reg(dev, addr, msgs[i].buf[0],
+                               msgs[i].buf[1]);
+               }
+
+               if (rc < 0)
+                       goto err;
+               dprintk_i2c(" OK\n");
+       }
+
+       return num;
+err:
+       dprintk_i2c(" ERROR: %d\n", rc);
+       return num;
+}
+
+/*
+ * functionality(), what da heck is this?
+ */
+static u32 functionality(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_SMBUS_EMUL;
+}
+
+static struct i2c_algorithm algo = {
+       .master_xfer   = stk1160_i2c_xfer,
+       .functionality = functionality,
+};
+
+static struct i2c_adapter adap_template = {
+       .owner = THIS_MODULE,
+       .name = "stk1160",
+       .algo = &algo,
+};
+
+static struct i2c_client client_template = {
+       .name = "stk1160 internal",
+};
+
+/*
+ * stk1160_i2c_register()
+ * register i2c bus
+ */
+int stk1160_i2c_register(struct stk1160 *dev)
+{
+       int rc;
+
+       dev->i2c_adap = adap_template;
+       dev->i2c_adap.dev.parent = dev->dev;
+       strcpy(dev->i2c_adap.name, "stk1160");
+       dev->i2c_adap.algo_data = dev;
+
+       i2c_set_adapdata(&dev->i2c_adap, &dev->v4l2_dev);
+
+       rc = i2c_add_adapter(&dev->i2c_adap);
+       if (rc < 0) {
+               stk1160_err("cannot add i2c adapter (%d)\n", rc);
+               return rc;
+       }
+
+       dev->i2c_client = client_template;
+       dev->i2c_client.adapter = &dev->i2c_adap;
+
+       /* Set i2c clock divider device address */
+       stk1160_write_reg(dev, STK1160_SICTL_CD,  0x0f);
+
+       /* ??? */
+       stk1160_write_reg(dev, STK1160_ASIC + 3,  0x00);
+
+       return 0;
+}
+
+/*
+ * stk1160_i2c_unregister()
+ * unregister i2c_bus
+ */
+int stk1160_i2c_unregister(struct stk1160 *dev)
+{
+       i2c_del_adapter(&dev->i2c_adap);
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-reg.h b/drivers/media/usb/stk1160/stk1160-reg.h
new file mode 100644 (file)
index 0000000..3e49da6
--- /dev/null
@@ -0,0 +1,93 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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.
+ *
+ */
+
+/* GPIO Control */
+#define STK1160_GCTRL                  0x000
+
+/* Remote Wakup Control */
+#define STK1160_RMCTL                  0x00c
+
+/*
+ * Decoder Control Register:
+ * This byte controls capture start/stop
+ * with bit #7 (0x?? OR 0x80 to activate).
+ */
+#define STK1160_DCTRL                  0x100
+
+/* Capture Frame Start Position */
+#define STK116_CFSPO                   0x110
+#define STK116_CFSPO_STX_L             0x110
+#define STK116_CFSPO_STX_H             0x111
+#define STK116_CFSPO_STY_L             0x112
+#define STK116_CFSPO_STY_H             0x113
+
+/* Capture Frame End Position */
+#define STK116_CFEPO                   0x114
+#define STK116_CFEPO_ENX_L             0x114
+#define STK116_CFEPO_ENX_H             0x115
+#define STK116_CFEPO_ENY_L             0x116
+#define STK116_CFEPO_ENY_H             0x117
+
+/* Serial Interface Control  */
+#define STK1160_SICTL                  0x200
+#define STK1160_SICTL_CD               0x202
+#define STK1160_SICTL_SDA              0x203
+
+/* Serial Bus Write */
+#define STK1160_SBUSW                  0x204
+#define STK1160_SBUSW_WA               0x204
+#define STK1160_SBUSW_WD               0x205
+
+/* Serial Bus Read */
+#define STK1160_SBUSR                  0x208
+#define STK1160_SBUSR_RA               0x208
+#define STK1160_SBUSR_RD               0x209
+
+/* Alternate Serial Inteface Control */
+#define STK1160_ASIC                   0x2fc
+
+/* PLL Select Options */
+#define STK1160_PLLSO                  0x018
+
+/* PLL Frequency Divider */
+#define STK1160_PLLFD                  0x01c
+
+/* Timing Generator */
+#define STK1160_TIGEN                  0x300
+
+/* Timing Control Parameter */
+#define STK1160_TICTL                  0x350
+
+/* AC97 Audio Control */
+#define STK1160_AC97CTL_0              0x500
+#define STK1160_AC97CTL_1              0x504
+
+/* Use [0:6] bits of register 0x504 to set codec command address */
+#define STK1160_AC97_ADDR              0x504
+/* Use [16:31] bits of register 0x500 to set codec command data */
+#define STK1160_AC97_CMD               0x502
+
+/* Audio I2S Interface */
+#define STK1160_I2SCTL                 0x50c
+
+/* EEPROM Interface */
+#define STK1160_EEPROM_SZ              0x5f0
diff --git a/drivers/media/usb/stk1160/stk1160-v4l.c b/drivers/media/usb/stk1160/stk1160-v4l.c
new file mode 100644 (file)
index 0000000..fe6e857
--- /dev/null
@@ -0,0 +1,739 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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/usb.h>
+#include <linux/mm.h>
+#include <linux/slab.h>
+
+#include <linux/videodev2.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-common.h>
+#include <media/v4l2-ioctl.h>
+#include <media/v4l2-fh.h>
+#include <media/v4l2-event.h>
+#include <media/v4l2-chip-ident.h>
+#include <media/videobuf2-vmalloc.h>
+
+#include <media/saa7115.h>
+
+#include "stk1160.h"
+#include "stk1160-reg.h"
+
+static unsigned int vidioc_debug;
+module_param(vidioc_debug, int, 0644);
+MODULE_PARM_DESC(vidioc_debug, "enable debug messages [vidioc]");
+
+static bool keep_buffers;
+module_param(keep_buffers, bool, 0644);
+MODULE_PARM_DESC(keep_buffers, "don't release buffers upon stop streaming");
+
+/* supported video standards */
+static struct stk1160_fmt format[] = {
+       {
+               .name     = "16 bpp YUY2, 4:2:2, packed",
+               .fourcc   = V4L2_PIX_FMT_UYVY,
+               .depth    = 16,
+       }
+};
+
+static void stk1160_set_std(struct stk1160 *dev)
+{
+       int i;
+
+       static struct regval std525[] = {
+
+               /* 720x480 */
+
+               /* Frame start */
+               {STK116_CFSPO_STX_L, 0x0000},
+               {STK116_CFSPO_STX_H, 0x0000},
+               {STK116_CFSPO_STY_L, 0x0003},
+               {STK116_CFSPO_STY_H, 0x0000},
+
+               /* Frame end */
+               {STK116_CFEPO_ENX_L, 0x05a0},
+               {STK116_CFEPO_ENX_H, 0x0005},
+               {STK116_CFEPO_ENY_L, 0x00f3},
+               {STK116_CFEPO_ENY_H, 0x0000},
+
+               {0xffff, 0xffff}
+       };
+
+       static struct regval std625[] = {
+
+               /* 720x576 */
+
+               /* TODO: Each line of frame has some junk at the end */
+               /* Frame start */
+               {STK116_CFSPO,   0x0000},
+               {STK116_CFSPO+1, 0x0000},
+               {STK116_CFSPO+2, 0x0001},
+               {STK116_CFSPO+3, 0x0000},
+
+               /* Frame end */
+               {STK116_CFEPO,   0x05a0},
+               {STK116_CFEPO+1, 0x0005},
+               {STK116_CFEPO+2, 0x0121},
+               {STK116_CFEPO+3, 0x0001},
+
+               {0xffff, 0xffff}
+       };
+
+       if (dev->norm & V4L2_STD_525_60) {
+               stk1160_dbg("registers to NTSC like standard\n");
+               for (i = 0; std525[i].reg != 0xffff; i++)
+                       stk1160_write_reg(dev, std525[i].reg, std525[i].val);
+       } else {
+               stk1160_dbg("registers to PAL like standard\n");
+               for (i = 0; std625[i].reg != 0xffff; i++)
+                       stk1160_write_reg(dev, std625[i].reg, std625[i].val);
+       }
+
+}
+
+/*
+ * Set a new alternate setting.
+ * Returns true is dev->max_pkt_size has changed, false otherwise.
+ */
+static bool stk1160_set_alternate(struct stk1160 *dev)
+{
+       int i, prev_alt = dev->alt;
+       unsigned int min_pkt_size;
+       bool new_pkt_size;
+
+       /*
+        * If we don't set right alternate,
+        * then we will get a green screen with junk.
+        */
+       min_pkt_size = STK1160_MIN_PKT_SIZE;
+
+       for (i = 0; i < dev->num_alt; i++) {
+               /* stop when the selected alt setting offers enough bandwidth */
+               if (dev->alt_max_pkt_size[i] >= min_pkt_size) {
+                       dev->alt = i;
+                       break;
+               /*
+                * otherwise make sure that we end up with the maximum bandwidth
+                * because the min_pkt_size equation might be wrong...
+                */
+               } else if (dev->alt_max_pkt_size[i] >
+                          dev->alt_max_pkt_size[dev->alt])
+                       dev->alt = i;
+       }
+
+       stk1160_info("setting alternate %d\n", dev->alt);
+
+       if (dev->alt != prev_alt) {
+               stk1160_dbg("minimum isoc packet size: %u (alt=%d)\n",
+                               min_pkt_size, dev->alt);
+               stk1160_dbg("setting alt %d with wMaxPacketSize=%u\n",
+                              dev->alt, dev->alt_max_pkt_size[dev->alt]);
+               usb_set_interface(dev->udev, 0, dev->alt);
+       }
+
+       new_pkt_size = dev->max_pkt_size != dev->alt_max_pkt_size[dev->alt];
+       dev->max_pkt_size = dev->alt_max_pkt_size[dev->alt];
+
+       return new_pkt_size;
+}
+
+static int stk1160_start_streaming(struct stk1160 *dev)
+{
+       bool new_pkt_size;
+       int rc = 0;
+       int i;
+
+       /* Check device presence */
+       if (!dev->udev)
+               return -ENODEV;
+
+       if (mutex_lock_interruptible(&dev->v4l_lock))
+               return -ERESTARTSYS;
+       /*
+        * For some reason it is mandatory to set alternate *first*
+        * and only *then* initialize isoc urbs.
+        * Someone please explain me why ;)
+        */
+       new_pkt_size = stk1160_set_alternate(dev);
+
+       /*
+        * We (re)allocate isoc urbs if:
+        * there is no allocated isoc urbs, OR
+        * a new dev->max_pkt_size is detected
+        */
+       if (!dev->isoc_ctl.num_bufs || new_pkt_size) {
+               rc = stk1160_alloc_isoc(dev);
+               if (rc < 0)
+                       goto out_stop_hw;
+       }
+
+       /* submit urbs and enables IRQ */
+       for (i = 0; i < dev->isoc_ctl.num_bufs; i++) {
+               rc = usb_submit_urb(dev->isoc_ctl.urb[i], GFP_KERNEL);
+               if (rc) {
+                       stk1160_err("cannot submit urb[%d] (%d)\n", i, rc);
+                       goto out_uninit;
+               }
+       }
+
+       /* Start saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 1);
+
+       /* Start stk1160 */
+       stk1160_write_reg(dev, STK1160_DCTRL, 0xb3);
+       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
+
+       stk1160_dbg("streaming started\n");
+
+       mutex_unlock(&dev->v4l_lock);
+
+       return 0;
+
+out_uninit:
+       stk1160_uninit_isoc(dev);
+out_stop_hw:
+       usb_set_interface(dev->udev, 0, 0);
+       stk1160_clear_queue(dev);
+
+       mutex_unlock(&dev->v4l_lock);
+
+       return rc;
+}
+
+/* Must be called with v4l_lock hold */
+static void stk1160_stop_hw(struct stk1160 *dev)
+{
+       /* If the device is not physically present, there is nothing to do */
+       if (!dev->udev)
+               return;
+
+       /* set alternate 0 */
+       dev->alt = 0;
+       stk1160_info("setting alternate %d\n", dev->alt);
+       usb_set_interface(dev->udev, 0, 0);
+
+       /* Stop stk1160 */
+       stk1160_write_reg(dev, STK1160_DCTRL, 0x00);
+       stk1160_write_reg(dev, STK1160_DCTRL+3, 0x00);
+
+       /* Stop saa711x */
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, s_stream, 0);
+}
+
+static int stk1160_stop_streaming(struct stk1160 *dev)
+{
+       if (mutex_lock_interruptible(&dev->v4l_lock))
+               return -ERESTARTSYS;
+
+       stk1160_cancel_isoc(dev);
+
+       /*
+        * It is possible to keep buffers around using a module parameter.
+        * This is intended to avoid memory fragmentation.
+        */
+       if (!keep_buffers)
+               stk1160_free_isoc(dev);
+
+       stk1160_stop_hw(dev);
+
+       stk1160_clear_queue(dev);
+
+       stk1160_dbg("streaming stopped\n");
+
+       mutex_unlock(&dev->v4l_lock);
+
+       return 0;
+}
+
+static struct v4l2_file_operations stk1160_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,
+};
+
+/*
+ * vidioc ioctls
+ */
+static int vidioc_querycap(struct file *file,
+               void *priv, struct v4l2_capability *cap)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       strcpy(cap->driver, "stk1160");
+       strcpy(cap->card, "stk1160");
+       usb_make_path(dev->udev, cap->bus_info, sizeof(cap->bus_info));
+       cap->device_caps =
+               V4L2_CAP_VIDEO_CAPTURE |
+               V4L2_CAP_STREAMING |
+               V4L2_CAP_READWRITE;
+       cap->capabilities = cap->device_caps | V4L2_CAP_DEVICE_CAPS;
+       return 0;
+}
+
+static int vidioc_enum_fmt_vid_cap(struct file *file, void  *priv,
+               struct v4l2_fmtdesc *f)
+{
+       if (f->index != 0)
+               return -EINVAL;
+
+       strlcpy(f->description, format[f->index].name, sizeof(f->description));
+       f->pixelformat = format[f->index].fourcc;
+       return 0;
+}
+
+static int vidioc_g_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       f->fmt.pix.pixelformat = dev->fmt->fourcc;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       return 0;
+}
+
+static int vidioc_try_fmt_vid_cap(struct file *file, void *priv,
+                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       /*
+        * User can't choose size at his own will,
+        * so we just return him the current size chosen
+        * at standard selection.
+        * TODO: Implement frame scaling?
+        */
+
+       f->fmt.pix.pixelformat = dev->fmt->fourcc;
+       f->fmt.pix.width = dev->width;
+       f->fmt.pix.height = dev->height;
+       f->fmt.pix.field = V4L2_FIELD_INTERLACED;
+       f->fmt.pix.bytesperline = dev->width * 2;
+       f->fmt.pix.sizeimage = dev->height * f->fmt.pix.bytesperline;
+       f->fmt.pix.colorspace = V4L2_COLORSPACE_SMPTE170M;
+
+       return 0;
+}
+
+static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
+                                       struct v4l2_format *f)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       struct vb2_queue *q = &dev->vb_vidq;
+
+       if (vb2_is_busy(q))
+               return -EBUSY;
+
+       vidioc_try_fmt_vid_cap(file, priv, f);
+
+       /* We don't support any format changes */
+
+       return 0;
+}
+
+static int vidioc_querystd(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       v4l2_device_call_all(&dev->v4l2_dev, 0, video, querystd, norm);
+       return 0;
+}
+
+static int vidioc_g_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       *norm = dev->norm;
+       return 0;
+}
+
+static int vidioc_s_std(struct file *file, void *priv, v4l2_std_id *norm)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       struct vb2_queue *q = &dev->vb_vidq;
+
+       if (vb2_is_busy(q))
+               return -EBUSY;
+
+       /* Check device presence */
+       if (!dev->udev)
+               return -ENODEV;
+
+       /* We need to set this now, before we call stk1160_set_std */
+       dev->norm = *norm;
+
+       /* This is taken from saa7115 video decoder */
+       if (dev->norm & V4L2_STD_525_60) {
+               dev->width = 720;
+               dev->height = 480;
+       } else if (dev->norm & V4L2_STD_625_50) {
+               dev->width = 720;
+               dev->height = 576;
+       } else {
+               stk1160_err("invalid standard\n");
+               return -EINVAL;
+       }
+
+       stk1160_set_std(dev);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                       dev->norm);
+
+       return 0;
+}
+
+
+static int vidioc_enum_input(struct file *file, void *priv,
+                               struct v4l2_input *i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       if (i->index > STK1160_MAX_INPUT)
+               return -EINVAL;
+
+       sprintf(i->name, "Composite%d", i->index);
+       i->type = V4L2_INPUT_TYPE_CAMERA;
+       i->std = dev->vdev.tvnorms;
+       return 0;
+}
+
+static int vidioc_g_input(struct file *file, void *priv, unsigned int *i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       *i = dev->ctl_input;
+       return 0;
+}
+
+static int vidioc_s_input(struct file *file, void *priv, unsigned int i)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       if (vb2_is_busy(&dev->vb_vidq))
+               return -EBUSY;
+
+       if (i > STK1160_MAX_INPUT)
+               return -EINVAL;
+
+       dev->ctl_input = i;
+
+       stk1160_select_input(dev);
+
+       return 0;
+}
+
+static int vidioc_g_chip_ident(struct file *file, void *priv,
+              struct v4l2_dbg_chip_ident *chip)
+{
+       switch (chip->match.type) {
+       case V4L2_CHIP_MATCH_HOST:
+               chip->ident = V4L2_IDENT_NONE;
+               chip->revision = 0;
+               return 0;
+       default:
+               return -EINVAL;
+       }
+}
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+static int vidioc_g_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct stk1160 *dev = video_drvdata(file);
+       int rc;
+       u8 val;
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               /* TODO: Support me please :-( */
+               return -EINVAL;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, g_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       rc = stk1160_read_reg(dev, reg->reg, &val);
+       reg->val = val;
+       reg->size = 1;
+
+       return rc;
+}
+
+static int vidioc_s_register(struct file *file, void *priv,
+                            struct v4l2_dbg_register *reg)
+{
+       struct stk1160 *dev = video_drvdata(file);
+
+       switch (reg->match.type) {
+       case V4L2_CHIP_MATCH_AC97:
+               return -EINVAL;
+       case V4L2_CHIP_MATCH_I2C_DRIVER:
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       case V4L2_CHIP_MATCH_I2C_ADDR:
+               /* TODO: is this correct? */
+               v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_register, reg);
+               return 0;
+       default:
+               if (!v4l2_chip_match_host(&reg->match))
+                       return -EINVAL;
+       }
+
+       /* Match host */
+       return stk1160_write_reg(dev, reg->reg, cpu_to_le16(reg->val));
+}
+#endif
+
+static const struct v4l2_ioctl_ops stk1160_ioctl_ops = {
+       .vidioc_querycap      = vidioc_querycap,
+       .vidioc_enum_fmt_vid_cap  = vidioc_enum_fmt_vid_cap,
+       .vidioc_g_fmt_vid_cap     = vidioc_g_fmt_vid_cap,
+       .vidioc_try_fmt_vid_cap   = vidioc_try_fmt_vid_cap,
+       .vidioc_s_fmt_vid_cap     = vidioc_s_fmt_vid_cap,
+       .vidioc_querystd      = vidioc_querystd,
+       .vidioc_g_std         = vidioc_g_std,
+       .vidioc_s_std         = vidioc_s_std,
+       .vidioc_enum_input    = vidioc_enum_input,
+       .vidioc_g_input       = vidioc_g_input,
+       .vidioc_s_input       = vidioc_s_input,
+
+       /* vb2 takes care of these */
+       .vidioc_reqbufs       = vb2_ioctl_reqbufs,
+       .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_log_status  = v4l2_ctrl_log_status,
+       .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
+       .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
+       .vidioc_g_chip_ident = vidioc_g_chip_ident,
+
+#ifdef CONFIG_VIDEO_ADV_DEBUG
+       .vidioc_g_register = vidioc_g_register,
+       .vidioc_s_register = vidioc_s_register,
+#endif
+};
+
+/********************************************************************/
+
+/*
+ * Videobuf2 operations
+ */
+static int queue_setup(struct vb2_queue *vq, const struct v4l2_format *v4l_fmt,
+                               unsigned int *nbuffers, unsigned int *nplanes,
+                               unsigned int sizes[], void *alloc_ctxs[])
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       unsigned long size;
+
+       size = dev->width * dev->height * 2;
+
+       /*
+        * Here we can change the number of buffers being requested.
+        * So, we set a minimum and a maximum like this:
+        */
+       *nbuffers = clamp_t(unsigned int, *nbuffers,
+                       STK1160_MIN_VIDEO_BUFFERS, STK1160_MAX_VIDEO_BUFFERS);
+
+       /* This means a packed colorformat */
+       *nplanes = 1;
+
+       sizes[0] = size;
+
+       stk1160_info("%s: buffer count %d, each %ld bytes\n",
+                       __func__, *nbuffers, size);
+
+       return 0;
+}
+
+static void buffer_queue(struct vb2_buffer *vb)
+{
+       unsigned long flags;
+       struct stk1160 *dev = vb2_get_drv_priv(vb->vb2_queue);
+       struct stk1160_buffer *buf =
+               container_of(vb, struct stk1160_buffer, vb);
+
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       if (!dev->udev) {
+               /*
+                * If the device is disconnected return the buffer to userspace
+                * directly. The next QBUF call will fail with -ENODEV.
+                */
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+       } else {
+
+               buf->mem = vb2_plane_vaddr(vb, 0);
+               buf->length = vb2_plane_size(vb, 0);
+               buf->bytesused = 0;
+               buf->pos = 0;
+
+               /*
+                * If buffer length is less from expected then we return
+                * the buffer to userspace directly.
+                */
+               if (buf->length < dev->width * dev->height * 2)
+                       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               else
+                       list_add_tail(&buf->list, &dev->avail_bufs);
+
+       }
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+}
+
+static int start_streaming(struct vb2_queue *vq, unsigned int count)
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       return stk1160_start_streaming(dev);
+}
+
+/* abort streaming and wait for last buffer */
+static int stop_streaming(struct vb2_queue *vq)
+{
+       struct stk1160 *dev = vb2_get_drv_priv(vq);
+       return stk1160_stop_streaming(dev);
+}
+
+static struct vb2_ops stk1160_video_qops = {
+       .queue_setup            = queue_setup,
+       .buf_queue              = buffer_queue,
+       .start_streaming        = start_streaming,
+       .stop_streaming         = stop_streaming,
+       .wait_prepare           = vb2_ops_wait_prepare,
+       .wait_finish            = vb2_ops_wait_finish,
+};
+
+static struct video_device v4l_template = {
+       .name = "stk1160",
+       .tvnorms = V4L2_STD_525_60 | V4L2_STD_625_50,
+       .fops = &stk1160_fops,
+       .ioctl_ops = &stk1160_ioctl_ops,
+       .release = video_device_release_empty,
+};
+
+/********************************************************************/
+
+/* Must be called with both v4l_lock and vb_queue_lock hold */
+void stk1160_clear_queue(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf;
+       unsigned long flags;
+
+       /* Release all active buffers */
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       while (!list_empty(&dev->avail_bufs)) {
+               buf = list_first_entry(&dev->avail_bufs,
+                       struct stk1160_buffer, list);
+               list_del(&buf->list);
+               vb2_buffer_done(&buf->vb, VB2_BUF_STATE_ERROR);
+               stk1160_info("buffer [%p/%d] aborted\n",
+                               buf, buf->vb.v4l2_buf.index);
+       }
+       /* It's important to clear current buffer */
+       dev->isoc_ctl.buf = NULL;
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+}
+
+int stk1160_vb2_setup(struct stk1160 *dev)
+{
+       int rc;
+       struct vb2_queue *q;
+
+       q = &dev->vb_vidq;
+       q->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
+       q->io_modes = VB2_READ | VB2_MMAP | VB2_USERPTR;
+       q->drv_priv = dev;
+       q->buf_struct_size = sizeof(struct stk1160_buffer);
+       q->ops = &stk1160_video_qops;
+       q->mem_ops = &vb2_vmalloc_memops;
+
+       rc = vb2_queue_init(q);
+       if (rc < 0)
+               return rc;
+
+       /* initialize video dma queue */
+       INIT_LIST_HEAD(&dev->avail_bufs);
+
+       return 0;
+}
+
+int stk1160_video_register(struct stk1160 *dev)
+{
+       int rc;
+
+       /* Initialize video_device with a template structure */
+       dev->vdev = v4l_template;
+       dev->vdev.debug = vidioc_debug;
+       dev->vdev.queue = &dev->vb_vidq;
+
+       /*
+        * Provide mutexes for v4l2 core and for videobuf2 queue.
+        * It will be used to protect *only* v4l2 ioctls.
+        */
+       dev->vdev.lock = &dev->v4l_lock;
+       dev->vdev.queue->lock = &dev->vb_queue_lock;
+
+       /* 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;
+       dev->width = 720;
+       dev->height = 480;
+
+       /* set default format */
+       dev->fmt = &format[0];
+       stk1160_set_std(dev);
+
+       v4l2_device_call_all(&dev->v4l2_dev, 0, core, s_std,
+                       dev->norm);
+
+       video_set_drvdata(&dev->vdev, dev);
+       rc = video_register_device(&dev->vdev, VFL_TYPE_GRABBER, -1);
+       if (rc < 0) {
+               stk1160_err("video_register_device failed (%d)\n", rc);
+               return rc;
+       }
+
+       v4l2_info(&dev->v4l2_dev, "V4L2 device registered as %s\n",
+                 video_device_node_name(&dev->vdev));
+
+       return 0;
+}
diff --git a/drivers/media/usb/stk1160/stk1160-video.c b/drivers/media/usb/stk1160/stk1160-video.c
new file mode 100644 (file)
index 0000000..8bdfb02
--- /dev/null
@@ -0,0 +1,522 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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/usb.h>
+#include <linux/slab.h>
+#include <linux/ratelimit.h>
+
+#include "stk1160.h"
+
+static unsigned int debug;
+module_param(debug, int, 0644);
+MODULE_PARM_DESC(debug, "enable debug messages");
+
+static inline void print_err_status(struct stk1160 *dev,
+                                    int packet, int status)
+{
+       char *errmsg = "Unknown";
+
+       switch (status) {
+       case -ENOENT:
+               errmsg = "unlinked synchronuously";
+               break;
+       case -ECONNRESET:
+               errmsg = "unlinked asynchronuously";
+               break;
+       case -ENOSR:
+               errmsg = "Buffer error (overrun)";
+               break;
+       case -EPIPE:
+               errmsg = "Stalled (device not responding)";
+               break;
+       case -EOVERFLOW:
+               errmsg = "Babble (bad cable?)";
+               break;
+       case -EPROTO:
+               errmsg = "Bit-stuff error (bad cable?)";
+               break;
+       case -EILSEQ:
+               errmsg = "CRC/Timeout (could be anything)";
+               break;
+       case -ETIME:
+               errmsg = "Device does not respond";
+               break;
+       }
+
+       if (packet < 0)
+               printk_ratelimited(KERN_WARNING "URB status %d [%s].\n",
+                               status, errmsg);
+       else
+               printk_ratelimited(KERN_INFO "URB packet %d, status %d [%s].\n",
+                              packet, status, errmsg);
+}
+
+static inline
+struct stk1160_buffer *stk1160_next_buffer(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf = NULL;
+       unsigned long flags = 0;
+
+       /* Current buffer must be NULL when this functions gets called */
+       BUG_ON(dev->isoc_ctl.buf);
+
+       spin_lock_irqsave(&dev->buf_lock, flags);
+       if (!list_empty(&dev->avail_bufs)) {
+               buf = list_first_entry(&dev->avail_bufs,
+                               struct stk1160_buffer, list);
+               list_del(&buf->list);
+       }
+       spin_unlock_irqrestore(&dev->buf_lock, flags);
+
+       return buf;
+}
+
+static inline
+void stk1160_buffer_done(struct stk1160 *dev)
+{
+       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
+
+       dev->field_count++;
+
+       buf->vb.v4l2_buf.sequence = dev->field_count >> 1;
+       buf->vb.v4l2_buf.field = V4L2_FIELD_INTERLACED;
+       buf->vb.v4l2_buf.bytesused = buf->bytesused;
+       do_gettimeofday(&buf->vb.v4l2_buf.timestamp);
+
+       vb2_set_plane_payload(&buf->vb, 0, buf->bytesused);
+       vb2_buffer_done(&buf->vb, VB2_BUF_STATE_DONE);
+
+       dev->isoc_ctl.buf = NULL;
+}
+
+static inline
+void stk1160_copy_video(struct stk1160 *dev, u8 *src, int len)
+{
+       int linesdone, lineoff, lencopy;
+       int bytesperline = dev->width * 2;
+       struct stk1160_buffer *buf = dev->isoc_ctl.buf;
+       u8 *dst = buf->mem;
+       int remain;
+
+       /*
+        * TODO: These stk1160_dbg are very spammy!
+        * We should 1) check why we are getting them
+        * and 2) add ratelimit.
+        *
+        * UPDATE: One of the reasons (the only one?) for getting these
+        * is incorrect standard (mismatch between expected and configured).
+        * So perhaps, we could add a counter for errors. When the counter
+        * reaches some value, we simply stop streaming.
+        */
+
+       len -= 4;
+       src += 4;
+
+       remain = len;
+
+       linesdone = buf->pos / bytesperline;
+       lineoff = buf->pos % bytesperline; /* offset in current line */
+
+       if (!buf->odd)
+               dst += bytesperline;
+
+       /* Multiply linesdone by two, to take account of the other field */
+       dst += linesdone * bytesperline * 2 + lineoff;
+
+       /* Copy the remaining of current line */
+       if (remain < (bytesperline - lineoff))
+               lencopy = remain;
+       else
+               lencopy = bytesperline - lineoff;
+
+       /*
+        * Check if we have enough space left in the buffer.
+        * In that case, we force loop exit after copy.
+        */
+       if (lencopy > buf->bytesused - buf->length) {
+               lencopy = buf->bytesused - buf->length;
+               remain = lencopy;
+       }
+
+       /* Check if the copy is done */
+       if (lencopy == 0 || remain == 0)
+               return;
+
+       /* Let the bug hunt begin! sanity checks! */
+       if (lencopy < 0) {
+               stk1160_dbg("copy skipped: negative lencopy\n");
+               return;
+       }
+
+       if ((unsigned long)dst + lencopy >
+               (unsigned long)buf->mem + buf->length) {
+               printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
+               return;
+       }
+
+       memcpy(dst, src, lencopy);
+
+       buf->bytesused += lencopy;
+       buf->pos += lencopy;
+       remain -= lencopy;
+
+       /* Copy current field line by line, interlacing with the other field */
+       while (remain > 0) {
+
+               dst += lencopy + bytesperline;
+               src += lencopy;
+
+               /* Copy one line at a time */
+               if (remain < bytesperline)
+                       lencopy = remain;
+               else
+                       lencopy = bytesperline;
+
+               /*
+                * Check if we have enough space left in the buffer.
+                * In that case, we force loop exit after copy.
+                */
+               if (lencopy > buf->bytesused - buf->length) {
+                       lencopy = buf->bytesused - buf->length;
+                       remain = lencopy;
+               }
+
+               /* Check if the copy is done */
+               if (lencopy == 0 || remain == 0)
+                       return;
+
+               if (lencopy < 0) {
+                       printk_ratelimited(KERN_WARNING "stk1160: negative lencopy detected\n");
+                       return;
+               }
+
+               if ((unsigned long)dst + lencopy >
+                       (unsigned long)buf->mem + buf->length) {
+                       printk_ratelimited(KERN_WARNING "stk1160: buffer overflow detected\n");
+                       return;
+               }
+
+               memcpy(dst, src, lencopy);
+               remain -= lencopy;
+
+               buf->bytesused += lencopy;
+               buf->pos += lencopy;
+       }
+}
+
+/*
+ * Controls the isoc copy of each urb packet
+ */
+static void stk1160_process_isoc(struct stk1160 *dev, struct urb *urb)
+{
+       int i, len, status;
+       u8 *p;
+
+       if (!dev) {
+               stk1160_warn("%s called with null device\n", __func__);
+               return;
+       }
+
+       if (urb->status < 0) {
+               /* Print status and drop current packet (or field?) */
+               print_err_status(dev, -1, urb->status);
+               return;
+       }
+
+       for (i = 0; i < urb->number_of_packets; i++) {
+               status = urb->iso_frame_desc[i].status;
+               if (status < 0) {
+                       print_err_status(dev, i, status);
+                       continue;
+               }
+
+               /* Get packet actual length and pointer to data */
+               p = urb->transfer_buffer + urb->iso_frame_desc[i].offset;
+               len = urb->iso_frame_desc[i].actual_length;
+
+               /* Empty packet */
+               if (len <= 4)
+                       continue;
+
+               /*
+                * An 8-byte packet sequence means end of field.
+                * So if we don't have any packet, we start receiving one now
+                * and if we do have a packet, then we are done with it.
+                *
+                * These end of field packets are always 0xc0 or 0x80,
+                * but not always 8-byte long so we don't check packet length.
+                */
+               if (p[0] == 0xc0) {
+
+                       /*
+                        * If first byte is 0xc0 then we received
+                        * second field, and frame has ended.
+                        */
+                       if (dev->isoc_ctl.buf != NULL)
+                               stk1160_buffer_done(dev);
+
+                       dev->isoc_ctl.buf = stk1160_next_buffer(dev);
+                       if (dev->isoc_ctl.buf == NULL)
+                               return;
+               }
+
+               /*
+                * If we don't have a buffer here, then it means we
+                * haven't found the start mark sequence.
+                */
+               if (dev->isoc_ctl.buf == NULL)
+                       continue;
+
+               if (p[0] == 0xc0 || p[0] == 0x80) {
+
+                       /* We set next packet parity and
+                        * continue to get next one
+                        */
+                       dev->isoc_ctl.buf->odd = *p & 0x40;
+                       dev->isoc_ctl.buf->pos = 0;
+                       continue;
+               }
+
+               stk1160_copy_video(dev, p, len);
+       }
+}
+
+
+/*
+ * IRQ callback, called by URB callback
+ */
+static void stk1160_isoc_irq(struct urb *urb)
+{
+       int i, rc;
+       struct stk1160 *dev = urb->context;
+
+       switch (urb->status) {
+       case 0:
+               break;
+       case -ECONNRESET:   /* kill */
+       case -ENOENT:
+       case -ESHUTDOWN:
+               /* TODO: check uvc driver: he frees the queue here */
+               return;
+       default:
+               stk1160_err("urb error! status %d\n", urb->status);
+               return;
+       }
+
+       stk1160_process_isoc(dev, urb);
+
+       /* Reset urb buffers */
+       for (i = 0; i < urb->number_of_packets; i++) {
+               urb->iso_frame_desc[i].status = 0;
+               urb->iso_frame_desc[i].actual_length = 0;
+       }
+
+       rc = usb_submit_urb(urb, GFP_ATOMIC);
+       if (rc)
+               stk1160_err("urb re-submit failed (%d)\n", rc);
+}
+
+/*
+ * Cancel urbs
+ * This function can't be called in atomic context
+ */
+void stk1160_cancel_isoc(struct stk1160 *dev)
+{
+       int i, num_bufs = dev->isoc_ctl.num_bufs;
+
+       /*
+        * This check is not necessary, but we add it
+        * to avoid a spurious debug message
+        */
+       if (!num_bufs)
+               return;
+
+       stk1160_dbg("killing %d urbs...\n", num_bufs);
+
+       for (i = 0; i < num_bufs; i++) {
+
+               /*
+                * To kill urbs we can't be in atomic context.
+                * We don't care for NULL pointer since
+                * usb_kill_urb allows it.
+                */
+               usb_kill_urb(dev->isoc_ctl.urb[i]);
+       }
+
+       stk1160_dbg("all urbs killed\n");
+}
+
+/*
+ * Releases urb and transfer buffers
+ * Obviusly, associated urb must be killed before releasing it.
+ */
+void stk1160_free_isoc(struct stk1160 *dev)
+{
+       struct urb *urb;
+       int i, num_bufs = dev->isoc_ctl.num_bufs;
+
+       stk1160_dbg("freeing %d urb buffers...\n", num_bufs);
+
+       for (i = 0; i < num_bufs; i++) {
+
+               urb = dev->isoc_ctl.urb[i];
+               if (urb) {
+
+                       if (dev->isoc_ctl.transfer_buffer[i]) {
+#ifndef CONFIG_DMA_NONCOHERENT
+                               usb_free_coherent(dev->udev,
+                                       urb->transfer_buffer_length,
+                                       dev->isoc_ctl.transfer_buffer[i],
+                                       urb->transfer_dma);
+#else
+                               kfree(dev->isoc_ctl.transfer_buffer[i]);
+#endif
+                       }
+                       usb_free_urb(urb);
+                       dev->isoc_ctl.urb[i] = NULL;
+               }
+               dev->isoc_ctl.transfer_buffer[i] = NULL;
+       }
+
+       kfree(dev->isoc_ctl.urb);
+       kfree(dev->isoc_ctl.transfer_buffer);
+
+       dev->isoc_ctl.urb = NULL;
+       dev->isoc_ctl.transfer_buffer = NULL;
+       dev->isoc_ctl.num_bufs = 0;
+
+       stk1160_dbg("all urb buffers freed\n");
+}
+
+/*
+ * Helper for cancelling and freeing urbs
+ * This function can't be called in atomic context
+ */
+void stk1160_uninit_isoc(struct stk1160 *dev)
+{
+       stk1160_cancel_isoc(dev);
+       stk1160_free_isoc(dev);
+}
+
+/*
+ * Allocate URBs
+ */
+int stk1160_alloc_isoc(struct stk1160 *dev)
+{
+       struct urb *urb;
+       int i, j, k, sb_size, max_packets, num_bufs;
+
+       /*
+        * It may be necessary to release isoc here,
+        * since isoc are only released on disconnection.
+        * (see new_pkt_size flag)
+        */
+       if (dev->isoc_ctl.num_bufs)
+               stk1160_uninit_isoc(dev);
+
+       stk1160_dbg("allocating urbs...\n");
+
+       num_bufs = STK1160_NUM_BUFS;
+       max_packets = STK1160_NUM_PACKETS;
+       sb_size = max_packets * dev->max_pkt_size;
+
+       dev->isoc_ctl.buf = NULL;
+       dev->isoc_ctl.max_pkt_size = dev->max_pkt_size;
+       dev->isoc_ctl.urb = kzalloc(sizeof(void *)*num_bufs, GFP_KERNEL);
+       if (!dev->isoc_ctl.urb) {
+               stk1160_err("out of memory for urb array\n");
+               return -ENOMEM;
+       }
+
+       dev->isoc_ctl.transfer_buffer = kzalloc(sizeof(void *)*num_bufs,
+                                             GFP_KERNEL);
+       if (!dev->isoc_ctl.transfer_buffer) {
+               stk1160_err("out of memory for usb transfers\n");
+               kfree(dev->isoc_ctl.urb);
+               return -ENOMEM;
+       }
+
+       /* allocate urbs and transfer buffers */
+       for (i = 0; i < num_bufs; i++) {
+
+               urb = usb_alloc_urb(max_packets, GFP_KERNEL);
+               if (!urb) {
+                       stk1160_err("cannot alloc urb[%d]\n", i);
+                       goto free_i_bufs;
+               }
+               dev->isoc_ctl.urb[i] = urb;
+
+#ifndef CONFIG_DMA_NONCOHERENT
+               dev->isoc_ctl.transfer_buffer[i] = usb_alloc_coherent(dev->udev,
+                       sb_size, GFP_KERNEL, &urb->transfer_dma);
+#else
+               dev->isoc_ctl.transfer_buffer[i] = kmalloc(sb_size, GFP_KERNEL);
+#endif
+               if (!dev->isoc_ctl.transfer_buffer[i]) {
+                       stk1160_err("cannot alloc %d bytes for tx[%d] buffer\n",
+                               sb_size, i);
+                       goto free_i_bufs;
+               }
+               memset(dev->isoc_ctl.transfer_buffer[i], 0, sb_size);
+
+               /*
+                * FIXME: Where can I get the endpoint?
+                */
+               urb->dev = dev->udev;
+               urb->pipe = usb_rcvisocpipe(dev->udev, STK1160_EP_VIDEO);
+               urb->transfer_buffer = dev->isoc_ctl.transfer_buffer[i];
+               urb->transfer_buffer_length = sb_size;
+               urb->complete = stk1160_isoc_irq;
+               urb->context = dev;
+               urb->interval = 1;
+               urb->start_frame = 0;
+               urb->number_of_packets = max_packets;
+#ifndef CONFIG_DMA_NONCOHERENT
+               urb->transfer_flags = URB_ISO_ASAP | URB_NO_TRANSFER_DMA_MAP;
+#else
+               urb->transfer_flags = URB_ISO_ASAP;
+#endif
+
+               k = 0;
+               for (j = 0; j < max_packets; j++) {
+                       urb->iso_frame_desc[j].offset = k;
+                       urb->iso_frame_desc[j].length =
+                                       dev->isoc_ctl.max_pkt_size;
+                       k += dev->isoc_ctl.max_pkt_size;
+               }
+       }
+
+       stk1160_dbg("urbs allocated\n");
+
+       /* At last we can say we have some buffers */
+       dev->isoc_ctl.num_bufs = num_bufs;
+
+       return 0;
+
+free_i_bufs:
+       /* Save the allocated buffers so far, so we can properly free them */
+       dev->isoc_ctl.num_bufs = i+1;
+       stk1160_free_isoc(dev);
+       return -ENOMEM;
+}
+
diff --git a/drivers/media/usb/stk1160/stk1160.h b/drivers/media/usb/stk1160/stk1160.h
new file mode 100644 (file)
index 0000000..3feba00
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * STK1160 driver
+ *
+ * Copyright (C) 2012 Ezequiel Garcia
+ * <elezegarcia--a.t--gmail.com>
+ *
+ * Based on Easycap driver by R.M. Thomas
+ *     Copyright (C) 2010 R.M. Thomas
+ *     <rmthomas--a.t--sciolus.org>
+ *
+ * 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/i2c.h>
+#include <sound/core.h>
+#include <sound/ac97_codec.h>
+#include <media/videobuf2-core.h>
+#include <media/v4l2-device.h>
+#include <media/v4l2-ctrls.h>
+
+#define STK1160_VERSION                "0.9.5"
+#define STK1160_VERSION_NUM    0x000905
+
+/* TODO: Decide on number of packets for each buffer */
+#define STK1160_NUM_PACKETS 64
+
+/* Number of buffers for isoc transfers */
+#define STK1160_NUM_BUFS 16 /* TODO */
+
+/* TODO: This endpoint address should be retrieved */
+#define STK1160_EP_VIDEO 0x82
+#define STK1160_EP_AUDIO 0x81
+
+/* Max and min video buffers */
+#define STK1160_MIN_VIDEO_BUFFERS 8
+#define STK1160_MAX_VIDEO_BUFFERS 32
+
+#define STK1160_MIN_PKT_SIZE 3072
+
+#define STK1160_MAX_INPUT 3
+
+#define STK1160_I2C_TIMEOUT 100
+
+/* TODO: Print helpers
+ * I could use dev_xxx, pr_xxx, v4l2_xxx or printk.
+ * However, there isn't a solid consensus on which
+ * new drivers should use.
+ *
+ */
+#define DEBUG
+#ifdef DEBUG
+#define stk1160_dbg(fmt, args...) \
+       printk(KERN_DEBUG "stk1160: " fmt,  ## args)
+#else
+#define stk1160_dbg(fmt, args...)
+#endif
+
+#define stk1160_info(fmt, args...) \
+       pr_info("stk1160: " fmt, ## args)
+
+#define stk1160_warn(fmt, args...) \
+       pr_warn("stk1160: " fmt, ## args)
+
+#define stk1160_err(fmt, args...) \
+       pr_err("stk1160: " fmt, ## args)
+
+/* Buffer for one video frame */
+struct stk1160_buffer {
+       /* common v4l buffer stuff -- must be first */
+       struct vb2_buffer vb;
+       struct list_head list;
+
+       void *mem;
+       unsigned int length;            /* buffer length */
+       unsigned int bytesused;         /* bytes written */
+       int odd;                        /* current oddity */
+
+       /*
+        * Since we interlace two fields per frame,
+        * this is different from bytesused.
+        */
+       unsigned int pos;               /* current pos inside buffer */
+};
+
+struct stk1160_isoc_ctl {
+       /* max packet size of isoc transaction */
+       int max_pkt_size;
+
+       /* number of allocated urbs */
+       int num_bufs;
+
+       /* urb for isoc transfers */
+       struct urb **urb;
+
+       /* transfer buffers for isoc transfer */
+       char **transfer_buffer;
+
+       /* current buffer */
+       struct stk1160_buffer *buf;
+};
+
+struct stk1160_fmt {
+       char  *name;
+       u32   fourcc;          /* v4l2 format id */
+       int   depth;
+};
+
+struct stk1160 {
+       struct v4l2_device v4l2_dev;
+       struct video_device vdev;
+       struct v4l2_ctrl_handler ctrl_handler;
+
+       struct device *dev;
+       struct usb_device *udev;
+
+       /* saa7115 subdev */
+       struct v4l2_subdev *sd_saa7115;
+
+       /* isoc control struct */
+       struct list_head avail_bufs;
+
+       /* video capture */
+       struct vb2_queue vb_vidq;
+
+       /* max packet size of isoc transaction */
+       int max_pkt_size;
+       /* array of wMaxPacketSize */
+       unsigned int *alt_max_pkt_size;
+       /* alternate */
+       int alt;
+       /* Number of alternative settings */
+       int num_alt;
+
+       struct stk1160_isoc_ctl isoc_ctl;
+       char urb_buf[255];       /* urb control msg buffer */
+
+       /* frame properties */
+       int width;                /* current frame width */
+       int height;               /* current frame height */
+       unsigned int ctl_input;   /* selected input */
+       v4l2_std_id norm;         /* current norm */
+       struct stk1160_fmt *fmt;  /* selected format */
+
+       unsigned int field_count; /* not sure ??? */
+       enum v4l2_field field;    /* also not sure :/ */
+
+       /* i2c i/o */
+       struct i2c_adapter i2c_adap;
+       struct i2c_client i2c_client;
+
+       struct mutex v4l_lock;
+       struct mutex vb_queue_lock;
+       spinlock_t buf_lock;
+
+       struct file *fh_owner;  /* filehandle ownership */
+
+       /* EXPERIMENTAL */
+       struct snd_card *snd_card;
+};
+
+struct regval {
+       u16 reg;
+       u16 val;
+};
+
+/* Provided by stk1160-v4l.c */
+int stk1160_vb2_setup(struct stk1160 *dev);
+int stk1160_video_register(struct stk1160 *dev);
+void stk1160_video_unregister(struct stk1160 *dev);
+void stk1160_clear_queue(struct stk1160 *dev);
+
+/* Provided by stk1160-video.c */
+int stk1160_alloc_isoc(struct stk1160 *dev);
+void stk1160_free_isoc(struct stk1160 *dev);
+void stk1160_cancel_isoc(struct stk1160 *dev);
+void stk1160_uninit_isoc(struct stk1160 *dev);
+
+/* Provided by stk1160-i2c.c */
+int stk1160_i2c_register(struct stk1160 *dev);
+int stk1160_i2c_unregister(struct stk1160 *dev);
+
+/* Provided by stk1160-core.c */
+int stk1160_read_reg(struct stk1160 *dev, u16 reg, u8 *value);
+int stk1160_write_reg(struct stk1160 *dev, u16 reg, u16 value);
+int stk1160_write_regs_req(struct stk1160 *dev, u8 req, u16 reg,
+               char *buf, int len);
+int stk1160_read_reg_req_len(struct stk1160 *dev, u8 req, u16 reg,
+               char *buf, int len);
+void stk1160_select_input(struct stk1160 *dev);
+
+/* Provided by stk1160-ac97.c */
+#ifdef CONFIG_VIDEO_STK1160_AC97
+int stk1160_ac97_register(struct stk1160 *dev);
+int stk1160_ac97_unregister(struct stk1160 *dev);
+#else
+static inline int stk1160_ac97_register(struct stk1160 *dev) { return 0; }
+static inline int stk1160_ac97_unregister(struct stk1160 *dev) { return 0; }
+#endif
+
diff --git a/drivers/media/usb/stkwebcam/Kconfig b/drivers/media/usb/stkwebcam/Kconfig
new file mode 100644 (file)
index 0000000..a6a00aa
--- /dev/null
@@ -0,0 +1,13 @@
+config USB_STKWEBCAM
+       tristate "USB Syntek DC1125 Camera support"
+       depends on VIDEO_V4L2
+       ---help---
+         Say Y here if you want to use this type of camera.
+         Supported devices are typically found in some Asus laptops,
+         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
+         may be supported by the stk11xx driver, from which this is
+         derived, see <http://sourceforge.net/projects/syntekdriver/>
+
+         To compile this driver as a module, choose M here: the
+         module will be called stkwebcam.
+
diff --git a/drivers/media/usb/stkwebcam/Makefile b/drivers/media/usb/stkwebcam/Makefile
new file mode 100644 (file)
index 0000000..20ef8a4
--- /dev/null
@@ -0,0 +1,4 @@
+stkwebcam-objs :=      stk-webcam.o stk-sensor.o
+
+obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
+
diff --git a/drivers/media/usb/tlg2300/Makefile b/drivers/media/usb/tlg2300/Makefile
new file mode 100644 (file)
index 0000000..137f8e3
--- /dev/null
@@ -0,0 +1,9 @@
+poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
+
+obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
+
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+
similarity index 99%
rename from drivers/media/video/tlg2300/pd-alsa.c
rename to drivers/media/usb/tlg2300/pd-alsa.c
index 9f8b7da56b671fe2eeee8f942e490dbb8b65c154..3f3e141f70fb963547074f47a867e79ff4664e49 100644 (file)
@@ -305,6 +305,10 @@ int poseidon_audio_init(struct poseidon *p)
                return ret;
 
        ret = snd_pcm_new(card, "poseidon audio", 0, 0, 1, &pcm);
+       if (ret < 0) {
+               snd_card_free(card);
+               return ret;
+       }
        snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &pcm_capture_ops);
        pcm->info_flags   = 0;
        pcm->private_data = p;
similarity index 99%
rename from drivers/media/video/tlg2300/pd-radio.c
rename to drivers/media/usb/tlg2300/pd-radio.c
index 4fad1dfb92cf00818bf3ee2c769d0dc59eb7b4dc..25eeb166aa0be81f399e312b28dfab14d10ee5b2 100644 (file)
@@ -348,7 +348,7 @@ static int vidioc_s_tuner(struct file *file, void *priv, struct v4l2_tuner *vt)
 {
        return vt->index > 0 ? -EINVAL : 0;
 }
-static int vidioc_s_audio(struct file *file, void *priv, struct v4l2_audio *va)
+static int vidioc_s_audio(struct file *file, void *priv, const struct v4l2_audio *va)
 {
        return (va->index != 0) ? -EINVAL : 0;
 }
similarity index 99%
rename from drivers/media/video/tlg2300/pd-video.c
rename to drivers/media/usb/tlg2300/pd-video.c
index bfbf9e56b0a4e6c86e752b0515a4688986e53713..1f448ac7a496c160d567b1b6c2eeb5b4eabff288 100644 (file)
@@ -1029,7 +1029,7 @@ static int vidioc_g_audio(struct file *file, void *fh, struct v4l2_audio *a)
        return 0;
 }
 
-static int vidioc_s_audio(struct file *file, void *fh, struct v4l2_audio *a)
+static int vidioc_s_audio(struct file *file, void *fh, const struct v4l2_audio *a)
 {
        return (0 == a->index) ? 0 : -EINVAL;
 }
similarity index 62%
rename from drivers/media/video/tm6000/Makefile
rename to drivers/media/usb/tm6000/Makefile
index 395515b4a888af254cfdd9020f8127ef3045de13..f2644933b8d1afc8709e137a1207f856dcbf964b 100644 (file)
@@ -9,7 +9,7 @@ obj-$(CONFIG_VIDEO_TM6000) += tm6000.o
 obj-$(CONFIG_VIDEO_TM6000_ALSA) += tm6000-alsa.o
 obj-$(CONFIG_VIDEO_TM6000_DVB) += tm6000-dvb.o
 
-ccflags-y := -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
+ccflags-y += -Idrivers/media/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
similarity index 99%
rename from drivers/media/video/tm6000/tm6000-alsa.c
rename to drivers/media/usb/tm6000/tm6000-alsa.c
index bd07ec707956d377eae03f3278fa8972e8cf4972..813c1ec5360884274f5d3e31e66f9d38d91d0753 100644 (file)
@@ -487,10 +487,11 @@ error:
 
 static int tm6000_audio_fini(struct tm6000_core *dev)
 {
-       struct snd_tm6000_card  *chip = dev->adev;
+       struct snd_tm6000_card *chip;
 
        if (!dev)
                return 0;
+       chip = dev->adev;
 
        if (!chip)
                return 0;
similarity index 99%
rename from drivers/media/video/tm6000/tm6000-input.c
rename to drivers/media/usb/tm6000/tm6000-input.c
index e80b7e190471293082b3470c6be8156a73d108f8..dffbd4bd47b15d92ffff672189aa2f18e90be4f0 100644 (file)
@@ -319,12 +319,13 @@ static int tm6000_ir_change_protocol(struct rc_dev *rc, u64 rc_type)
 static int __tm6000_ir_int_start(struct rc_dev *rc)
 {
        struct tm6000_IR *ir = rc->priv;
-       struct tm6000_core *dev = ir->dev;
+       struct tm6000_core *dev;
        int pipe, size;
        int err = -ENOMEM;
 
        if (!ir)
                return -ENODEV;
+       dev = ir->dev;
 
        dprintk(2, "%s\n",__func__);
 
similarity index 97%
rename from drivers/media/video/tm6000/tm6000-video.c
rename to drivers/media/usb/tm6000/tm6000-video.c
index f7034df94e0a6640a77c0bf0090ab08baeaf1e47..4342cd4f5c8a7ad76cef1730348fb9ece2b1ada0 100644 (file)
@@ -1401,7 +1401,7 @@ static int radio_g_audio(struct file *file, void *priv,
 }
 
 static int radio_s_audio(struct file *file, void *priv,
-                                       struct v4l2_audio *a)
+                                       const struct v4l2_audio *a)
 {
        return 0;
 }
@@ -1448,7 +1448,7 @@ static int radio_queryctrl(struct file *file, void *priv,
        File operations for the device
    ------------------------------------------------------------------*/
 
-static int tm6000_open(struct file *file)
+static int __tm6000_open(struct file *file)
 {
        struct video_device *vdev = video_devdata(file);
        struct tm6000_core *dev = video_drvdata(file);
@@ -1540,23 +1540,41 @@ static int tm6000_open(struct file *file)
        return 0;
 }
 
+static int tm6000_open(struct file *file)
+{
+       struct video_device *vdev = video_devdata(file);
+       int res;
+
+       mutex_lock(vdev->lock);
+       res = __tm6000_open(file);
+       mutex_unlock(vdev->lock);
+       return res;
+}
+
 static ssize_t
 tm6000_read(struct file *file, char __user *data, size_t count, loff_t *pos)
 {
-       struct tm6000_fh        *fh = file->private_data;
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
 
        if (fh->type == V4L2_BUF_TYPE_VIDEO_CAPTURE) {
+               int res;
+
                if (!res_get(fh->dev, fh, true))
                        return -EBUSY;
 
-               return videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
+               if (mutex_lock_interruptible(&dev->lock))
+                       return -ERESTARTSYS;
+               res = videobuf_read_stream(&fh->vb_vidq, data, count, pos, 0,
                                        file->f_flags & O_NONBLOCK);
+               mutex_unlock(&dev->lock);
+               return res;
        }
        return 0;
 }
 
 static unsigned int
-tm6000_poll(struct file *file, struct poll_table_struct *wait)
+__tm6000_poll(struct file *file, struct poll_table_struct *wait)
 {
        struct tm6000_fh        *fh = file->private_data;
        struct tm6000_buffer    *buf;
@@ -1583,6 +1601,18 @@ tm6000_poll(struct file *file, struct poll_table_struct *wait)
        return 0;
 }
 
+static unsigned int tm6000_poll(struct file *file, struct poll_table_struct *wait)
+{
+       struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+       unsigned int res;
+
+       mutex_lock(&dev->lock);
+       res = __tm6000_poll(file, wait);
+       mutex_unlock(&dev->lock);
+       return res;
+}
+
 static int tm6000_release(struct file *file)
 {
        struct tm6000_fh         *fh = file->private_data;
@@ -1592,6 +1622,7 @@ static int tm6000_release(struct file *file)
        dprintk(dev, V4L2_DEBUG_OPEN, "tm6000: close called (dev=%s, users=%d)\n",
                video_device_node_name(vdev), dev->users);
 
+       mutex_lock(&dev->lock);
        dev->users--;
 
        res_free(dev, fh);
@@ -1619,6 +1650,7 @@ static int tm6000_release(struct file *file)
        }
 
        kfree(fh);
+       mutex_unlock(&dev->lock);
 
        return 0;
 }
@@ -1626,8 +1658,14 @@ static int tm6000_release(struct file *file)
 static int tm6000_mmap(struct file *file, struct vm_area_struct * vma)
 {
        struct tm6000_fh *fh = file->private_data;
+       struct tm6000_core *dev = fh->dev;
+       int res;
 
-       return videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       if (mutex_lock_interruptible(&dev->lock))
+               return -ERESTARTSYS;
+       res = videobuf_mmap_mapper(&fh->vb_vidq, vma);
+       mutex_unlock(&dev->lock);
+       return res;
 }
 
 static struct v4l2_file_operations tm6000_fops = {
@@ -1724,10 +1762,6 @@ static struct video_device *vdev_init(struct tm6000_core *dev,
        vfd->release = video_device_release;
        vfd->debug = tm6000_debug;
        vfd->lock = &dev->lock;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vfd->flags);
 
        snprintf(vfd->name, sizeof(vfd->name), "%s %s", dev->name, type_name);
 
similarity index 56%
rename from drivers/media/dvb/ttusb-budget/Kconfig
rename to drivers/media/usb/ttusb-budget/Kconfig
index 2663ae39b88692f5eada3b73730b68fc756e7db9..97bad7da689cafccb3a7bd08b5bf6958d400bd12 100644 (file)
@@ -1,13 +1,13 @@
 config DVB_TTUSB_BUDGET
        tristate "Technotrend/Hauppauge Nova-USB devices"
        depends on DVB_CORE && USB && I2C && PCI
-       select DVB_CX22700 if !DVB_FE_CUSTOMISE
-       select DVB_TDA1004X if !DVB_FE_CUSTOMISE
-       select DVB_VES1820 if !DVB_FE_CUSTOMISE
-       select DVB_TDA8083 if !DVB_FE_CUSTOMISE
-       select DVB_STV0299 if !DVB_FE_CUSTOMISE
-       select DVB_STV0297 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
+       select DVB_CX22700 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA1004X if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_VES1820 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_TDA8083 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0299 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_STV0297 if MEDIA_SUBDRV_AUTOSELECT
+       select DVB_LNBP21 if MEDIA_SUBDRV_AUTOSELECT
        help
          Support for external USB adapters designed by Technotrend and
          produced by Hauppauge, shipped under the brand name 'Nova-USB'.
diff --git a/drivers/media/usb/ttusb-budget/Makefile b/drivers/media/usb/ttusb-budget/Makefile
new file mode 100644 (file)
index 0000000..f47bbf6
--- /dev/null
@@ -0,0 +1,3 @@
+obj-$(CONFIG_DVB_TTUSB_BUDGET) += dvb-ttusb-budget.o
+
+ccflags-y += -Idrivers/media/dvb-core/ -Idrivers/media/dvb-frontends
similarity index 57%
rename from drivers/media/dvb/ttusb-dec/Makefile
rename to drivers/media/usb/ttusb-dec/Makefile
index ed28b5384d20c190b78c3ab66d83119d1288e41b..5352740d2353c92eb0949000bddffb7a77a4d8c7 100644 (file)
@@ -1,3 +1,3 @@
 obj-$(CONFIG_DVB_TTUSB_DEC) += ttusb_dec.o ttusbdecfe.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/
+ccflags-y += -Idrivers/media/dvb-core/
similarity index 88%
rename from drivers/media/video/usbvision/Kconfig
rename to drivers/media/usb/usbvision/Kconfig
index fc24ef05b3f31cf527b6fc850423cae317ad224b..6b6afc5d8f7e8d3a373cc623382e48ff7e54f27a 100644 (file)
@@ -2,7 +2,7 @@ config VIDEO_USBVISION
        tristate "USB video devices based on Nogatech NT1003/1004/1005"
        depends on I2C && VIDEO_V4L2
        select VIDEO_TUNER
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
+       select VIDEO_SAA711X if MEDIA_SUBDRV_AUTOSELECT
        ---help---
          There are more than 50 different USB video devices based on
          NT1003/1004/1005 USB Bridges. This driver enables using those
similarity index 63%
rename from drivers/media/video/usbvision/Makefile
rename to drivers/media/usb/usbvision/Makefile
index aea1e3b5f06b7c1b1b9c7687a3f0a52f02a29bf0..9b3a5581df4205f240143bbabf64dec4c60ad5ab 100644 (file)
@@ -2,5 +2,5 @@ usbvision-objs  := usbvision-core.o usbvision-video.o usbvision-i2c.o usbvision-
 
 obj-$(CONFIG_VIDEO_USBVISION) += usbvision.o
 
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
+ccflags-y += -Idrivers/media/i2c
+ccflags-y += -Idrivers/media/tuners
similarity index 97%
rename from drivers/media/video/usbvision/usbvision-video.c
rename to drivers/media/usb/usbvision/usbvision-video.c
index 9bd8f084f3489671143d879218d29495d66753c0..f67018ed3795a349b95ceb8efbc22689f62c204d 100644 (file)
@@ -349,6 +349,8 @@ static int usbvision_v4l2_open(struct file *file)
 
        PDEBUG(DBG_IO, "open");
 
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
        usbvision_reset_power_off_timer(usbvision);
 
        if (usbvision->user)
@@ -402,6 +404,7 @@ static int usbvision_v4l2_open(struct file *file)
 
        /* prepare queues */
        usbvision_empty_framequeues(usbvision);
+       mutex_unlock(&usbvision->v4l2_lock);
 
        PDEBUG(DBG_IO, "success");
        return err_code;
@@ -421,6 +424,7 @@ static int usbvision_v4l2_close(struct file *file)
 
        PDEBUG(DBG_IO, "close");
 
+       mutex_lock(&usbvision->v4l2_lock);
        usbvision_audio_off(usbvision);
        usbvision_restart_isoc(usbvision);
        usbvision_stop_isoc(usbvision);
@@ -443,6 +447,7 @@ static int usbvision_v4l2_close(struct file *file)
                printk(KERN_INFO "%s: Final disconnect\n", __func__);
                usbvision_release(usbvision);
        }
+       mutex_unlock(&usbvision->v4l2_lock);
 
        PDEBUG(DBG_IO, "success");
        return 0;
@@ -679,7 +684,7 @@ static int vidioc_g_audio(struct file *file, void *priv, struct v4l2_audio *a)
 }
 
 static int vidioc_s_audio(struct file *file, void *fh,
-                         struct v4l2_audio *a)
+                         const struct v4l2_audio *a)
 {
        if (a->index)
                return -EINVAL;
@@ -956,7 +961,7 @@ static int vidioc_s_fmt_vid_cap(struct file *file, void *priv,
        return 0;
 }
 
-static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+static ssize_t usbvision_read(struct file *file, char __user *buf,
                      size_t count, loff_t *ppos)
 {
        struct usb_usbvision *usbvision = video_drvdata(file);
@@ -1060,7 +1065,20 @@ static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
        return count;
 }
 
-static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+static ssize_t usbvision_v4l2_read(struct file *file, char __user *buf,
+                     size_t count, loff_t *ppos)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int res;
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       res = usbvision_read(file, buf, count, ppos);
+       mutex_unlock(&usbvision->v4l2_lock);
+       return res;
+}
+
+static int usbvision_mmap(struct file *file, struct vm_area_struct *vma)
 {
        unsigned long size = vma->vm_end - vma->vm_start,
                start = vma->vm_start;
@@ -1107,6 +1125,17 @@ static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
        return 0;
 }
 
+static int usbvision_v4l2_mmap(struct file *file, struct vm_area_struct *vma)
+{
+       struct usb_usbvision *usbvision = video_drvdata(file);
+       int res;
+
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
+       res = usbvision_mmap(file, vma);
+       mutex_unlock(&usbvision->v4l2_lock);
+       return res;
+}
 
 /*
  * Here comes the stuff for radio on usbvision based devices
@@ -1119,6 +1148,8 @@ static int usbvision_radio_open(struct file *file)
 
        PDEBUG(DBG_IO, "%s:", __func__);
 
+       if (mutex_lock_interruptible(&usbvision->v4l2_lock))
+               return -ERESTARTSYS;
        if (usbvision->user) {
                dev_err(&usbvision->rdev->dev,
                        "%s: Someone tried to open an already opened USBVision Radio!\n",
@@ -1156,6 +1187,7 @@ static int usbvision_radio_open(struct file *file)
                }
        }
 out:
+       mutex_unlock(&usbvision->v4l2_lock);
        return err_code;
 }
 
@@ -1167,6 +1199,7 @@ static int usbvision_radio_close(struct file *file)
 
        PDEBUG(DBG_IO, "");
 
+       mutex_lock(&usbvision->v4l2_lock);
        /* Set packet size to 0 */
        usbvision->iface_alt = 0;
        err_code = usb_set_interface(usbvision->dev, usbvision->iface,
@@ -1186,6 +1219,7 @@ static int usbvision_radio_close(struct file *file)
                usbvision_release(usbvision);
        }
 
+       mutex_unlock(&usbvision->v4l2_lock);
        PDEBUG(DBG_IO, "success");
        return err_code;
 }
@@ -1296,10 +1330,6 @@ static struct video_device *usbvision_vdev_init(struct usb_usbvision *usbvision,
        if (NULL == vdev)
                return NULL;
        *vdev = *vdev_template;
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
        vdev->lock = &usbvision->v4l2_lock;
        vdev->v4l2_dev = &usbvision->v4l2_dev;
        snprintf(vdev->name, sizeof(vdev->name), "%s", name);
similarity index 98%
rename from drivers/media/video/uvc/uvc_driver.c
rename to drivers/media/usb/uvc/uvc_driver.c
index 1d131720b6d71c5ea56b34fb598223ca468f9348..5967081747ceb974814a5818ad8cccb43aacf64a 100644 (file)
  *
  */
 
-/*
- * This driver aims to support video input and ouput devices compliant with the
- * 'USB Video Class' specification.
- *
- * The driver doesn't support the deprecated v4l1 interface. It implements the
- * mmap capture method only, and doesn't do any image format conversion in
- * software. If your user-space application doesn't support YUYV or MJPEG, fix
- * it :-). Please note that the MJPEG data have been stripped from their
- * Huffman tables (DHT marker), you will need to add it back if your JPEG
- * codec can't handle MJPEG data.
- */
-
 #include <linux/atomic.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
@@ -95,12 +83,27 @@ static struct uvc_format_desc uvc_fmts[] = {
                .fcc            = V4L2_PIX_FMT_UYVY,
        },
        {
-               .name           = "Greyscale (8-bit)",
+               .name           = "Greyscale 8-bit (Y800)",
                .guid           = UVC_GUID_FORMAT_Y800,
                .fcc            = V4L2_PIX_FMT_GREY,
        },
        {
-               .name           = "Greyscale (16-bit)",
+               .name           = "Greyscale 8-bit (Y8  )",
+               .guid           = UVC_GUID_FORMAT_Y8,
+               .fcc            = V4L2_PIX_FMT_GREY,
+       },
+       {
+               .name           = "Greyscale 10-bit (Y10 )",
+               .guid           = UVC_GUID_FORMAT_Y10,
+               .fcc            = V4L2_PIX_FMT_Y10,
+       },
+       {
+               .name           = "Greyscale 12-bit (Y12 )",
+               .guid           = UVC_GUID_FORMAT_Y12,
+               .fcc            = V4L2_PIX_FMT_Y12,
+       },
+       {
+               .name           = "Greyscale 16-bit (Y16 )",
                .guid           = UVC_GUID_FORMAT_Y16,
                .fcc            = V4L2_PIX_FMT_Y16,
        },
@@ -1719,6 +1722,8 @@ static int uvc_register_video(struct uvc_device *dev,
        vdev->v4l2_dev = &dev->vdev;
        vdev->fops = &uvc_fops;
        vdev->release = uvc_release;
+       if (stream->type == V4L2_BUF_TYPE_VIDEO_OUTPUT)
+               vdev->vfl_dir = VFL_DIR_TX;
        strlcpy(vdev->name, dev->name, sizeof vdev->name);
 
        /* Set the driver data before calling video_register_device, otherwise
@@ -2212,6 +2217,15 @@ static struct usb_device_id uvc_ids[] = {
          .bInterfaceSubClass   = 1,
          .bInterfaceProtocol   = 0,
          .driver_info          = UVC_QUIRK_FIX_BANDWIDTH },
+       /* Ophir Optronics - SPCAM 620U */
+       { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
+                               | USB_DEVICE_ID_MATCH_INT_INFO,
+         .idVendor             = 0x0bd3,
+         .idProduct            = 0x0555,
+         .bInterfaceClass      = USB_CLASS_VIDEO,
+         .bInterfaceSubClass   = 1,
+         .bInterfaceProtocol   = 0,
+         .driver_info          = UVC_QUIRK_PROBE_MINMAX },
        /* MT6227 */
        { .match_flags          = USB_DEVICE_ID_MATCH_DEVICE
                                | USB_DEVICE_ID_MATCH_INT_INFO,
similarity index 98%
rename from drivers/media/video/uvc/uvc_video.c
rename to drivers/media/usb/uvc/uvc_video.c
index 7ac4347ca09e72dc4bb2abb751779f3053a338c7..1c15b4227bdbd3886ff0e2db32ad00d73b10524e 100644 (file)
@@ -1438,6 +1438,26 @@ static void uvc_uninit_video(struct uvc_streaming *stream, int free_buffers)
                uvc_free_urb_buffers(stream);
 }
 
+/*
+ * Compute the maximum number of bytes per interval for an endpoint.
+ */
+static unsigned int uvc_endpoint_max_bpi(struct usb_device *dev,
+                                        struct usb_host_endpoint *ep)
+{
+       u16 psize;
+
+       switch (dev->speed) {
+       case USB_SPEED_SUPER:
+               return ep->ss_ep_comp.wBytesPerInterval;
+       case USB_SPEED_HIGH:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+       default:
+               psize = usb_endpoint_maxp(&ep->desc);
+               return psize & 0x07ff;
+       }
+}
+
 /*
  * Initialize isochronous URBs and allocate transfer buffers. The packet size
  * is given by the endpoint.
@@ -1450,8 +1470,7 @@ static int uvc_init_video_isoc(struct uvc_streaming *stream,
        u16 psize;
        u32 size;
 
-       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
        size = stream->ctrl.dwMaxVideoFrameSize;
 
        npackets = uvc_alloc_urb_buffers(stream, size, psize, gfp_flags);
@@ -1506,7 +1525,7 @@ static int uvc_init_video_bulk(struct uvc_streaming *stream,
        u16 psize;
        u32 size;
 
-       psize = le16_to_cpu(ep->desc.wMaxPacketSize) & 0x07ff;
+       psize = usb_endpoint_maxp(&ep->desc) & 0x7ff;
        size = stream->ctrl.dwMaxPayloadTransferSize;
        stream->bulk.max_payload_size = size;
 
@@ -1567,7 +1586,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
 
        if (intf->num_altsetting > 1) {
                struct usb_host_endpoint *best_ep = NULL;
-               unsigned int best_psize = 3 * 1024;
+               unsigned int best_psize = UINT_MAX;
                unsigned int bandwidth;
                unsigned int uninitialized_var(altsetting);
                int intfnum = stream->intfnum;
@@ -1595,8 +1614,7 @@ static int uvc_init_video(struct uvc_streaming *stream, gfp_t gfp_flags)
                                continue;
 
                        /* Check if the bandwidth is high enough. */
-                       psize = le16_to_cpu(ep->desc.wMaxPacketSize);
-                       psize = (psize & 0x07ff) * (1 + ((psize >> 11) & 3));
+                       psize = uvc_endpoint_max_bpi(stream->dev->udev, ep);
                        if (psize >= bandwidth && psize <= best_psize) {
                                altsetting = alts->desc.bAlternateSetting;
                                best_psize = psize;
similarity index 98%
rename from drivers/media/video/uvc/uvcvideo.h
rename to drivers/media/usb/uvc/uvcvideo.h
index 7c3d082505b78b6fc189fc631ee11cacab603447..3764040475bbe75647cd7b14f3a66f1e6383aef7 100644 (file)
 #define UVC_GUID_FORMAT_Y800 \
        { 'Y',  '8',  '0',  '0', 0x00, 0x00, 0x10, 0x00, \
         0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y8 \
+       { 'Y',  '8',  ' ',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y10 \
+       { 'Y',  '1',  '0',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
+#define UVC_GUID_FORMAT_Y12 \
+       { 'Y',  '1',  '2',  ' ', 0x00, 0x00, 0x10, 0x00, \
+        0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
 #define UVC_GUID_FORMAT_Y16 \
        { 'Y',  '1',  '6',  ' ', 0x00, 0x00, 0x10, 0x00, \
         0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71}
diff --git a/drivers/media/usb/zr364xx/Kconfig b/drivers/media/usb/zr364xx/Kconfig
new file mode 100644 (file)
index 0000000..0f58566
--- /dev/null
@@ -0,0 +1,14 @@
+config USB_ZR364XX
+       tristate "USB ZR364XX Camera support"
+       depends on VIDEO_V4L2
+       select VIDEOBUF_GEN
+       select VIDEOBUF_VMALLOC
+       ---help---
+         Say Y here if you want to connect this type of camera to your
+         computer's USB port.
+         See <file:Documentation/video4linux/zr364xx.txt> for more info
+         and list of supported cameras.
+
+         To compile this driver as a module, choose M here: the
+         module will be called zr364xx.
+
diff --git a/drivers/media/usb/zr364xx/Makefile b/drivers/media/usb/zr364xx/Makefile
new file mode 100644 (file)
index 0000000..a577788
--- /dev/null
@@ -0,0 +1,2 @@
+obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
+
diff --git a/drivers/media/v4l2-core/Kconfig b/drivers/media/v4l2-core/Kconfig
new file mode 100644 (file)
index 0000000..0c54e19
--- /dev/null
@@ -0,0 +1,81 @@
+#
+# Generic video config states
+#
+
+# Enable the V4L2 core and API
+config VIDEO_V4L2
+       tristate
+       depends on (I2C || I2C=n) && VIDEO_DEV
+       default (I2C || I2C=n) && VIDEO_DEV
+
+config VIDEO_ADV_DEBUG
+       bool "Enable advanced debug functionality on V4L2 drivers"
+       default n
+       ---help---
+         Say Y here to enable advanced debugging functionality on some
+         V4L devices.
+         In doubt, say N.
+
+config VIDEO_FIXED_MINOR_RANGES
+       bool "Enable old-style fixed minor ranges on drivers/video devices"
+       default n
+       ---help---
+         Say Y here to enable the old-style fixed-range minor assignments.
+         Only useful if you rely on the old behavior and use mknod instead of udev.
+
+         When in doubt, say N.
+
+# Used by drivers that need tuner.ko
+config VIDEO_TUNER
+       tristate
+       depends on MEDIA_TUNER
+
+# Used by drivers that need v4l2-mem2mem.ko
+config V4L2_MEM2MEM_DEV
+        tristate
+        depends on VIDEOBUF2_CORE
+
+# Used by drivers that need Videobuf modules
+config VIDEOBUF_GEN
+       tristate
+
+config VIDEOBUF_DMA_SG
+       tristate
+       depends on HAS_DMA
+       select VIDEOBUF_GEN
+
+config VIDEOBUF_VMALLOC
+       tristate
+       select VIDEOBUF_GEN
+
+config VIDEOBUF_DMA_CONTIG
+       tristate
+       depends on HAS_DMA
+       select VIDEOBUF_GEN
+
+config VIDEOBUF_DVB
+       tristate
+       select VIDEOBUF_GEN
+
+# Used by drivers that need Videobuf2 modules
+config VIDEOBUF2_CORE
+       tristate
+
+config VIDEOBUF2_MEMOPS
+       tristate
+
+config VIDEOBUF2_DMA_CONTIG
+       tristate
+       select VIDEOBUF2_CORE
+       select VIDEOBUF2_MEMOPS
+
+config VIDEOBUF2_VMALLOC
+       tristate
+       select VIDEOBUF2_CORE
+       select VIDEOBUF2_MEMOPS
+
+config VIDEOBUF2_DMA_SG
+       tristate
+       #depends on HAS_DMA
+       select VIDEOBUF2_CORE
+       select VIDEOBUF2_MEMOPS
diff --git a/drivers/media/v4l2-core/Makefile b/drivers/media/v4l2-core/Makefile
new file mode 100644 (file)
index 0000000..c2d61d4
--- /dev/null
@@ -0,0 +1,35 @@
+#
+# Makefile for the V4L2 core
+#
+
+tuner-objs     :=      tuner-core.o
+
+videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
+                       v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
+ifeq ($(CONFIG_COMPAT),y)
+  videodev-objs += v4l2-compat-ioctl32.o
+endif
+
+obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
+obj-$(CONFIG_VIDEO_V4L2) += v4l2-common.o
+
+obj-$(CONFIG_VIDEO_TUNER) += tuner.o
+
+obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
+
+obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
+obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
+obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
+obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
+obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
+
+obj-$(CONFIG_VIDEOBUF2_CORE) += videobuf2-core.o
+obj-$(CONFIG_VIDEOBUF2_MEMOPS) += videobuf2-memops.o
+obj-$(CONFIG_VIDEOBUF2_VMALLOC) += videobuf2-vmalloc.o
+obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG) += videobuf2-dma-contig.o
+obj-$(CONFIG_VIDEOBUF2_DMA_SG) += videobuf2-dma-sg.o
+
+ccflags-y += -I$(srctree)/drivers/media/dvb-core
+ccflags-y += -I$(srctree)/drivers/media/dvb-frontends
+ccflags-y += -I$(srctree)/drivers/media/tuners
+
similarity index 62%
rename from drivers/media/video/v4l2-common.c
rename to drivers/media/v4l2-core/v4l2-common.c
index 1baec8393306de0c1c781c88987615a24701c91f..f995dd31151d0cc36bce91110e8ca3c0443c0138 100644 (file)
@@ -418,7 +418,7 @@ EXPORT_SYMBOL_GPL(v4l2_i2c_tuner_addrs);
 
 #if defined(CONFIG_SPI)
 
-/* Load a spi sub-device. */
+/* Load an spi sub-device. */
 
 void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
                const struct v4l2_subdev_ops *ops)
@@ -443,7 +443,7 @@ struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
 
        BUG_ON(!v4l2_dev);
 
-       if (info->modalias)
+       if (info->modalias[0])
                request_module(info->modalias);
 
        spi = spi_new_device(master, info);
@@ -597,6 +597,364 @@ int v4l_fill_dv_preset_info(u32 preset, struct v4l2_dv_enum_preset *info)
 }
 EXPORT_SYMBOL_GPL(v4l_fill_dv_preset_info);
 
+/**
+ * v4l_match_dv_timings - check if two timings match
+ * @t1 - compare this v4l2_dv_timings struct...
+ * @t2 - with this struct.
+ * @pclock_delta - the allowed pixelclock deviation.
+ *
+ * Compare t1 with t2 with a given margin of error for the pixelclock.
+ */
+bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1,
+                         const struct v4l2_dv_timings *t2,
+                         unsigned pclock_delta)
+{
+       if (t1->type != t2->type || t1->type != V4L2_DV_BT_656_1120)
+               return false;
+       if (t1->bt.width == t2->bt.width &&
+           t1->bt.height == t2->bt.height &&
+           t1->bt.interlaced == t2->bt.interlaced &&
+           t1->bt.polarities == t2->bt.polarities &&
+           t1->bt.pixelclock >= t2->bt.pixelclock - pclock_delta &&
+           t1->bt.pixelclock <= t2->bt.pixelclock + pclock_delta &&
+           t1->bt.hfrontporch == t2->bt.hfrontporch &&
+           t1->bt.vfrontporch == t2->bt.vfrontporch &&
+           t1->bt.vsync == t2->bt.vsync &&
+           t1->bt.vbackporch == t2->bt.vbackporch &&
+           (!t1->bt.interlaced ||
+               (t1->bt.il_vfrontporch == t2->bt.il_vfrontporch &&
+                t1->bt.il_vsync == t2->bt.il_vsync &&
+                t1->bt.il_vbackporch == t2->bt.il_vbackporch)))
+               return true;
+       return false;
+}
+EXPORT_SYMBOL_GPL(v4l_match_dv_timings);
+
+/*
+ * CVT defines
+ * Based on Coordinated Video Timings Standard
+ * version 1.1 September 10, 2003
+ */
+
+#define CVT_PXL_CLK_GRAN       250000  /* pixel clock granularity */
+
+/* Normal blanking */
+#define CVT_MIN_V_BPORCH       7       /* lines */
+#define CVT_MIN_V_PORCH_RND    3       /* lines */
+#define CVT_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
+
+/* Normal blanking for CVT uses GTF to calculate horizontal blanking */
+#define CVT_CELL_GRAN          8       /* character cell granularity */
+#define CVT_M                  600     /* blanking formula gradient */
+#define CVT_C                  40      /* blanking formula offset */
+#define CVT_K                  128     /* blanking formula scaling factor */
+#define CVT_J                  20      /* blanking formula scaling factor */
+#define CVT_C_PRIME (((CVT_C - CVT_J) * CVT_K / 256) + CVT_J)
+#define CVT_M_PRIME (CVT_K * CVT_M / 256)
+
+/* Reduced Blanking */
+#define CVT_RB_MIN_V_BPORCH    7       /* lines  */
+#define CVT_RB_V_FPORCH        3       /* lines  */
+#define CVT_RB_MIN_V_BLANK   460     /* us     */
+#define CVT_RB_H_SYNC         32       /* pixels */
+#define CVT_RB_H_BPORCH       80       /* pixels */
+#define CVT_RB_H_BLANK       160       /* pixels */
+
+/** v4l2_detect_cvt - detect if the given timings follow the CVT standard
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid CVT format. If so, then it will return true, and fmt will be filled
+ * in with the found CVT timings.
+ */
+bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
+               u32 polarities, struct v4l2_dv_timings *fmt)
+{
+       int  v_fp, v_bp, h_fp, h_bp, hsync;
+       int  frame_width, image_height, image_width;
+       bool reduced_blanking;
+       unsigned pix_clk;
+
+       if (vsync < 4 || vsync > 7)
+               return false;
+
+       if (polarities == V4L2_DV_VSYNC_POS_POL)
+               reduced_blanking = false;
+       else if (polarities == V4L2_DV_HSYNC_POS_POL)
+               reduced_blanking = true;
+       else
+               return false;
+
+       /* Vertical */
+       if (reduced_blanking) {
+               v_fp = CVT_RB_V_FPORCH;
+               v_bp = (CVT_RB_MIN_V_BLANK * hfreq + 999999) / 1000000;
+               v_bp -= vsync + v_fp;
+
+               if (v_bp < CVT_RB_MIN_V_BPORCH)
+                       v_bp = CVT_RB_MIN_V_BPORCH;
+       } else {
+               v_fp = CVT_MIN_V_PORCH_RND;
+               v_bp = (CVT_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync;
+
+               if (v_bp < CVT_MIN_V_BPORCH)
+                       v_bp = CVT_MIN_V_BPORCH;
+       }
+       image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+
+       /* Aspect ratio based on vsync */
+       switch (vsync) {
+       case 4:
+               image_width = (image_height * 4) / 3;
+               break;
+       case 5:
+               image_width = (image_height * 16) / 9;
+               break;
+       case 6:
+               image_width = (image_height * 16) / 10;
+               break;
+       case 7:
+               /* special case */
+               if (image_height == 1024)
+                       image_width = (image_height * 5) / 4;
+               else if (image_height == 768)
+                       image_width = (image_height * 15) / 9;
+               else
+                       return false;
+               break;
+       default:
+               return false;
+       }
+
+       image_width = image_width & ~7;
+
+       /* Horizontal */
+       if (reduced_blanking) {
+               pix_clk = (image_width + CVT_RB_H_BLANK) * hfreq;
+               pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
+
+               h_bp = CVT_RB_H_BPORCH;
+               hsync = CVT_RB_H_SYNC;
+               h_fp = CVT_RB_H_BLANK - h_bp - hsync;
+
+               frame_width = image_width + CVT_RB_H_BLANK;
+       } else {
+               int h_blank;
+               unsigned ideal_duty_cycle = CVT_C_PRIME - (CVT_M_PRIME * 1000) / hfreq;
+
+               h_blank = (image_width * ideal_duty_cycle + (100 - ideal_duty_cycle) / 2) /
+                                               (100 - ideal_duty_cycle);
+               h_blank = h_blank - h_blank % (2 * CVT_CELL_GRAN);
+
+               if (h_blank * 100 / image_width < 20) {
+                       h_blank = image_width / 5;
+                       h_blank = (h_blank + 0x7) & ~0x7;
+               }
+
+               pix_clk = (image_width + h_blank) * hfreq;
+               pix_clk = (pix_clk / CVT_PXL_CLK_GRAN) * CVT_PXL_CLK_GRAN;
+
+               h_bp = h_blank / 2;
+               frame_width = image_width + h_blank;
+
+               hsync = (frame_width * 8 + 50) / 100;
+               hsync = hsync - hsync % CVT_CELL_GRAN;
+               h_fp = h_blank - hsync - h_bp;
+       }
+
+       fmt->bt.polarities = polarities;
+       fmt->bt.width = image_width;
+       fmt->bt.height = image_height;
+       fmt->bt.hfrontporch = h_fp;
+       fmt->bt.vfrontporch = v_fp;
+       fmt->bt.hsync = hsync;
+       fmt->bt.vsync = vsync;
+       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+       fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
+       fmt->bt.pixelclock = pix_clk;
+       fmt->bt.standards = V4L2_DV_BT_STD_CVT;
+       if (reduced_blanking)
+               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+       return true;
+}
+EXPORT_SYMBOL_GPL(v4l2_detect_cvt);
+
+/*
+ * GTF defines
+ * Based on Generalized Timing Formula Standard
+ * Version 1.1 September 2, 1999
+ */
+
+#define GTF_PXL_CLK_GRAN       250000  /* pixel clock granularity */
+
+#define GTF_MIN_VSYNC_BP       550     /* min time of vsync + back porch (us) */
+#define GTF_V_FP               1       /* vertical front porch (lines) */
+#define GTF_CELL_GRAN          8       /* character cell granularity */
+
+/* Default */
+#define GTF_D_M                        600     /* blanking formula gradient */
+#define GTF_D_C                        40      /* blanking formula offset */
+#define GTF_D_K                        128     /* blanking formula scaling factor */
+#define GTF_D_J                        20      /* blanking formula scaling factor */
+#define GTF_D_C_PRIME ((((GTF_D_C - GTF_D_J) * GTF_D_K) / 256) + GTF_D_J)
+#define GTF_D_M_PRIME ((GTF_D_K * GTF_D_M) / 256)
+
+/* Secondary */
+#define GTF_S_M                        3600    /* blanking formula gradient */
+#define GTF_S_C                        40      /* blanking formula offset */
+#define GTF_S_K                        128     /* blanking formula scaling factor */
+#define GTF_S_J                        35      /* blanking formula scaling factor */
+#define GTF_S_C_PRIME ((((GTF_S_C - GTF_S_J) * GTF_S_K) / 256) + GTF_S_J)
+#define GTF_S_M_PRIME ((GTF_S_K * GTF_S_M) / 256)
+
+/** v4l2_detect_gtf - detect if the given timings follow the GTF standard
+ * @frame_height - the total height of the frame (including blanking) in lines.
+ * @hfreq - the horizontal frequency in Hz.
+ * @vsync - the height of the vertical sync in lines.
+ * @polarities - the horizontal and vertical polarities (same as struct
+ *             v4l2_bt_timings polarities).
+ * @aspect - preferred aspect ratio. GTF has no method of determining the
+ *             aspect ratio in order to derive the image width from the
+ *             image height, so it has to be passed explicitly. Usually
+ *             the native screen aspect ratio is used for this. If it
+ *             is not filled in correctly, then 16:9 will be assumed.
+ * @fmt - the resulting timings.
+ *
+ * This function will attempt to detect if the given values correspond to a
+ * valid GTF format. If so, then it will return true, and fmt will be filled
+ * in with the found GTF timings.
+ */
+bool v4l2_detect_gtf(unsigned frame_height,
+               unsigned hfreq,
+               unsigned vsync,
+               u32 polarities,
+               struct v4l2_fract aspect,
+               struct v4l2_dv_timings *fmt)
+{
+       int pix_clk;
+       int  v_fp, v_bp, h_fp, h_bp, hsync;
+       int frame_width, image_height, image_width;
+       bool default_gtf;
+       int h_blank;
+
+       if (vsync != 3)
+               return false;
+
+       if (polarities == V4L2_DV_VSYNC_POS_POL)
+               default_gtf = true;
+       else if (polarities == V4L2_DV_HSYNC_POS_POL)
+               default_gtf = false;
+       else
+               return false;
+
+       /* Vertical */
+       v_fp = GTF_V_FP;
+       v_bp = (GTF_MIN_VSYNC_BP * hfreq + 999999) / 1000000 - vsync;
+       image_height = (frame_height - v_fp - vsync - v_bp + 1) & ~0x1;
+
+       if (aspect.numerator == 0 || aspect.denominator == 0) {
+               aspect.numerator = 16;
+               aspect.denominator = 9;
+       }
+       image_width = ((image_height * aspect.numerator) / aspect.denominator);
+
+       /* Horizontal */
+       if (default_gtf)
+               h_blank = ((image_width * GTF_D_C_PRIME * hfreq) -
+                                       (image_width * GTF_D_M_PRIME * 1000) +
+                       (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000) / 2) /
+                       (hfreq * (100 - GTF_D_C_PRIME) + GTF_D_M_PRIME * 1000);
+       else
+               h_blank = ((image_width * GTF_S_C_PRIME * hfreq) -
+                                       (image_width * GTF_S_M_PRIME * 1000) +
+                       (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000) / 2) /
+                       (hfreq * (100 - GTF_S_C_PRIME) + GTF_S_M_PRIME * 1000);
+
+       h_blank = h_blank - h_blank % (2 * GTF_CELL_GRAN);
+       frame_width = image_width + h_blank;
+
+       pix_clk = (image_width + h_blank) * hfreq;
+       pix_clk = pix_clk / GTF_PXL_CLK_GRAN * GTF_PXL_CLK_GRAN;
+
+       hsync = (frame_width * 8 + 50) / 100;
+       hsync = hsync - hsync % GTF_CELL_GRAN;
+
+       h_fp = h_blank / 2 - hsync;
+       h_bp = h_blank / 2;
+
+       fmt->bt.polarities = polarities;
+       fmt->bt.width = image_width;
+       fmt->bt.height = image_height;
+       fmt->bt.hfrontporch = h_fp;
+       fmt->bt.vfrontporch = v_fp;
+       fmt->bt.hsync = hsync;
+       fmt->bt.vsync = vsync;
+       fmt->bt.hbackporch = frame_width - image_width - h_fp - hsync;
+       fmt->bt.vbackporch = frame_height - image_height - v_fp - vsync;
+       fmt->bt.pixelclock = pix_clk;
+       fmt->bt.standards = V4L2_DV_BT_STD_GTF;
+       if (!default_gtf)
+               fmt->bt.flags |= V4L2_DV_FL_REDUCED_BLANKING;
+       return true;
+}
+EXPORT_SYMBOL_GPL(v4l2_detect_gtf);
+
+/** v4l2_calc_aspect_ratio - calculate the aspect ratio based on bytes
+ *     0x15 and 0x16 from the EDID.
+ * @hor_landscape - byte 0x15 from the EDID.
+ * @vert_portrait - byte 0x16 from the EDID.
+ *
+ * Determines the aspect ratio from the EDID.
+ * See VESA Enhanced EDID standard, release A, rev 2, section 3.6.2:
+ * "Horizontal and Vertical Screen Size or Aspect Ratio"
+ */
+struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait)
+{
+       struct v4l2_fract aspect = { 16, 9 };
+       u32 tmp;
+       u8 ratio;
+
+       /* Nothing filled in, fallback to 16:9 */
+       if (!hor_landscape && !vert_portrait)
+               return aspect;
+       /* Both filled in, so they are interpreted as the screen size in cm */
+       if (hor_landscape && vert_portrait) {
+               aspect.numerator = hor_landscape;
+               aspect.denominator = vert_portrait;
+               return aspect;
+       }
+       /* Only one is filled in, so interpret them as a ratio:
+          (val + 99) / 100 */
+       ratio = hor_landscape | vert_portrait;
+       /* Change some rounded values into the exact aspect ratio */
+       if (ratio == 79) {
+               aspect.numerator = 16;
+               aspect.denominator = 9;
+       } else if (ratio == 34) {
+               aspect.numerator = 4;
+               aspect.numerator = 3;
+       } else if (ratio == 68) {
+               aspect.numerator = 15;
+               aspect.numerator = 9;
+       } else {
+               aspect.numerator = hor_landscape + 99;
+               aspect.denominator = 100;
+       }
+       if (hor_landscape)
+               return aspect;
+       /* The aspect ratio is for portrait, so swap numerator and denominator */
+       tmp = aspect.denominator;
+       aspect.denominator = aspect.numerator;
+       aspect.numerator = tmp;
+       return aspect;
+}
+EXPORT_SYMBOL_GPL(v4l2_calc_aspect_ratio);
+
 const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
                const struct v4l2_discrete_probe *probe,
                s32 width, s32 height)
similarity index 94%
rename from drivers/media/video/v4l2-compat-ioctl32.c
rename to drivers/media/v4l2-core/v4l2-compat-ioctl32.c
index 9ebd5c540d10feab78df929f39b8e64b1690f17f..83ffb6436baf67e22f7308acae67966dbfef6094 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/compat.h>
 #include <linux/module.h>
 #include <linux/videodev2.h>
+#include <linux/v4l2-subdev.h>
 #include <media/v4l2-dev.h>
 #include <media/v4l2-ioctl.h>
 
@@ -194,10 +195,6 @@ static int __get_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return get_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (copy_from_user(kp, up, sizeof(kp->fmt.raw_data)))
-                       return -EFAULT;
-               return 0;
        default:
                printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
                                                                kp->type);
@@ -240,10 +237,6 @@ static int __put_v4l2_format32(struct v4l2_format *kp, struct v4l2_format32 __us
        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
                return put_v4l2_sliced_vbi_format(&kp->fmt.sliced, &up->fmt.sliced);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (copy_to_user(up, kp, sizeof(up->fmt.raw_data)))
-                       return -EFAULT;
-               return 0;
        default:
                printk(KERN_INFO "compat_ioctl32: unexpected VIDIOC_FMT type %d\n",
                                                                kp->type);
@@ -729,6 +722,44 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
        return 0;
 }
 
+struct v4l2_subdev_edid32 {
+       __u32 pad;
+       __u32 start_block;
+       __u32 blocks;
+       __u32 reserved[5];
+       compat_caddr_t edid;
+};
+
+static int get_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up)
+{
+       u32 tmp;
+
+       if (!access_ok(VERIFY_READ, up, sizeof(struct v4l2_subdev_edid32)) ||
+               get_user(kp->pad, &up->pad) ||
+               get_user(kp->start_block, &up->start_block) ||
+               get_user(kp->blocks, &up->blocks) ||
+               get_user(tmp, &up->edid) ||
+               copy_from_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+                       return -EFAULT;
+       kp->edid = compat_ptr(tmp);
+       return 0;
+}
+
+static int put_v4l2_subdev_edid32(struct v4l2_subdev_edid *kp, struct v4l2_subdev_edid32 __user *up)
+{
+       u32 tmp = (u32)((unsigned long)kp->edid);
+
+       if (!access_ok(VERIFY_WRITE, up, sizeof(struct v4l2_subdev_edid32)) ||
+               put_user(kp->pad, &up->pad) ||
+               put_user(kp->start_block, &up->start_block) ||
+               put_user(kp->blocks, &up->blocks) ||
+               put_user(tmp, &up->edid) ||
+               copy_to_user(kp->reserved, up->reserved, sizeof(kp->reserved)))
+                       return -EFAULT;
+       return 0;
+}
+
+
 #define VIDIOC_G_FMT32         _IOWR('V',  4, struct v4l2_format32)
 #define VIDIOC_S_FMT32         _IOWR('V',  5, struct v4l2_format32)
 #define VIDIOC_QUERYBUF32      _IOWR('V',  9, struct v4l2_buffer32)
@@ -738,6 +769,8 @@ static int put_v4l2_event32(struct v4l2_event *kp, struct v4l2_event32 __user *u
 #define VIDIOC_DQBUF32         _IOWR('V', 17, struct v4l2_buffer32)
 #define VIDIOC_ENUMSTD32       _IOWR('V', 25, struct v4l2_standard32)
 #define VIDIOC_ENUMINPUT32     _IOWR('V', 26, struct v4l2_input32)
+#define VIDIOC_SUBDEV_G_EDID32 _IOWR('V', 63, struct v4l2_subdev_edid32)
+#define VIDIOC_SUBDEV_S_EDID32 _IOWR('V', 64, struct v4l2_subdev_edid32)
 #define VIDIOC_TRY_FMT32       _IOWR('V', 64, struct v4l2_format32)
 #define VIDIOC_G_EXT_CTRLS32    _IOWR('V', 71, struct v4l2_ext_controls32)
 #define VIDIOC_S_EXT_CTRLS32    _IOWR('V', 72, struct v4l2_ext_controls32)
@@ -765,6 +798,7 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                struct v4l2_ext_controls v2ecs;
                struct v4l2_event v2ev;
                struct v4l2_create_buffers v2crt;
+               struct v4l2_subdev_edid v2edid;
                unsigned long vx;
                int vi;
        } karg;
@@ -797,6 +831,8 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
        case VIDIOC_S_OUTPUT32: cmd = VIDIOC_S_OUTPUT; break;
        case VIDIOC_CREATE_BUFS32: cmd = VIDIOC_CREATE_BUFS; break;
        case VIDIOC_PREPARE_BUF32: cmd = VIDIOC_PREPARE_BUF; break;
+       case VIDIOC_SUBDEV_G_EDID32: cmd = VIDIOC_SUBDEV_G_EDID; break;
+       case VIDIOC_SUBDEV_S_EDID32: cmd = VIDIOC_SUBDEV_S_EDID; break;
        }
 
        switch (cmd) {
@@ -814,6 +850,12 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                compatible_arg = 0;
                break;
 
+       case VIDIOC_SUBDEV_G_EDID:
+       case VIDIOC_SUBDEV_S_EDID:
+               err = get_v4l2_subdev_edid32(&karg.v2edid, up);
+               compatible_arg = 0;
+               break;
+
        case VIDIOC_G_FMT:
        case VIDIOC_S_FMT:
        case VIDIOC_TRY_FMT:
@@ -906,6 +948,11 @@ static long do_video_ioctl(struct file *file, unsigned int cmd, unsigned long ar
                err = put_v4l2_event32(&karg.v2ev, up);
                break;
 
+       case VIDIOC_SUBDEV_G_EDID:
+       case VIDIOC_SUBDEV_S_EDID:
+               err = put_v4l2_subdev_edid32(&karg.v2edid, up);
+               break;
+
        case VIDIOC_G_FMT:
        case VIDIOC_S_FMT:
        case VIDIOC_TRY_FMT:
@@ -1026,6 +1073,8 @@ long v4l2_compat_ioctl32(struct file *file, unsigned int cmd, unsigned long arg)
        case VIDIOC_QUERY_DV_TIMINGS:
        case VIDIOC_DV_TIMINGS_CAP:
        case VIDIOC_ENUM_FREQ_BANDS:
+       case VIDIOC_SUBDEV_G_EDID32:
+       case VIDIOC_SUBDEV_S_EDID32:
                ret = do_video_ioctl(file, cmd, arg);
                break;
 
similarity index 93%
rename from drivers/media/video/v4l2-ctrls.c
rename to drivers/media/v4l2-core/v4l2-ctrls.c
index b6a2ee71e5c300cead8a4d77cb4e627c687a476e..207bcd8dee1111a21189128ebd144378eef5cb2b 100644 (file)
@@ -425,6 +425,18 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                "Gray",
                NULL,
        };
+       static const char * const dv_tx_mode[] = {
+               "DVI-D",
+               "HDMI",
+               NULL,
+       };
+       static const char * const dv_rgb_range[] = {
+               "Automatic",
+               "RGB limited range (16-235)",
+               "RGB full range (0-255)",
+               NULL,
+       };
+
 
        switch (id) {
        case V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ:
@@ -502,6 +514,11 @@ const char * const *v4l2_ctrl_get_menu(u32 id)
                return mpeg4_profile;
        case V4L2_CID_JPEG_CHROMA_SUBSAMPLING:
                return jpeg_chroma_subsampling;
+       case V4L2_CID_DV_TX_MODE:
+               return dv_tx_mode;
+       case V4L2_CID_DV_TX_RGB_RANGE:
+       case V4L2_CID_DV_RX_RGB_RANGE:
+               return dv_rgb_range;
 
        default:
                return NULL;
@@ -732,6 +749,17 @@ const char *v4l2_ctrl_get_name(u32 id)
        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 */
+       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";
+       case V4L2_CID_DV_TX_EDID_PRESENT:       return "EDID Present";
+       case V4L2_CID_DV_TX_MODE:               return "Transmit Mode";
+       case V4L2_CID_DV_TX_RGB_RANGE:          return "Tx RGB Quantization Range";
+       case V4L2_CID_DV_RX_POWER_PRESENT:      return "Power Present";
+       case V4L2_CID_DV_RX_RGB_RANGE:          return "Rx RGB Quantization Range";
 
        default:
                return NULL;
@@ -832,6 +860,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_ISO_SENSITIVITY_AUTO:
        case V4L2_CID_EXPOSURE_METERING:
        case V4L2_CID_SCENE_MODE:
+       case V4L2_CID_DV_TX_MODE:
+       case V4L2_CID_DV_TX_RGB_RANGE:
+       case V4L2_CID_DV_RX_RGB_RANGE:
+       case V4L2_CID_TEST_PATTERN:
                *type = V4L2_CTRL_TYPE_MENU;
                break;
        case V4L2_CID_LINK_FREQ:
@@ -853,6 +885,7 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_JPEG_CLASS:
        case V4L2_CID_IMAGE_SOURCE_CLASS:
        case V4L2_CID_IMAGE_PROC_CLASS:
+       case V4L2_CID_DV_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;
@@ -869,6 +902,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_JPEG_ACTIVE_MARKER:
        case V4L2_CID_3A_LOCK:
        case V4L2_CID_AUTO_FOCUS_STATUS:
+       case V4L2_CID_DV_TX_HOTPLUG:
+       case V4L2_CID_DV_TX_RXSENSE:
+       case V4L2_CID_DV_TX_EDID_PRESENT:
+       case V4L2_CID_DV_RX_POWER_PRESENT:
                *type = V4L2_CTRL_TYPE_BITMASK;
                break;
        case V4L2_CID_MIN_BUFFERS_FOR_CAPTURE:
@@ -933,6 +970,10 @@ void v4l2_ctrl_fill(u32 id, const char **name, enum v4l2_ctrl_type *type,
        case V4L2_CID_FLASH_STROBE_STATUS:
        case V4L2_CID_AUTO_FOCUS_STATUS:
        case V4L2_CID_FLASH_READY:
+       case V4L2_CID_DV_TX_HOTPLUG:
+       case V4L2_CID_DV_TX_RXSENSE:
+       case V4L2_CID_DV_TX_EDID_PRESENT:
+       case V4L2_CID_DV_RX_POWER_PRESENT:
                *flags |= V4L2_CTRL_FLAG_READ_ONLY;
                break;
        }
@@ -1174,76 +1215,53 @@ static int cluster_changed(struct v4l2_ctrl *master)
        return diff;
 }
 
-/* Validate integer-type control */
-static int validate_new_int(const struct v4l2_ctrl *ctrl, s32 *pval)
+/* Validate a new control */
+static int validate_new(const struct v4l2_ctrl *ctrl,
+                       struct v4l2_ext_control *c)
 {
-       s32 val = *pval;
+       size_t len;
        u32 offset;
+       s32 val;
 
        switch (ctrl->type) {
        case V4L2_CTRL_TYPE_INTEGER:
                /* Round towards the closest legal value */
-               val += ctrl->step / 2;
-               if (val < ctrl->minimum)
-                       val = ctrl->minimum;
-               if (val > ctrl->maximum)
-                       val = ctrl->maximum;
+               val = c->value + ctrl->step / 2;
+               val = clamp(val, ctrl->minimum, ctrl->maximum);
                offset = val - ctrl->minimum;
                offset = ctrl->step * (offset / ctrl->step);
-               val = ctrl->minimum + offset;
-               *pval = val;
+               c->value = ctrl->minimum + offset;
                return 0;
 
        case V4L2_CTRL_TYPE_BOOLEAN:
-               *pval = !!val;
+               c->value = !!c->value;
                return 0;
 
        case V4L2_CTRL_TYPE_MENU:
        case V4L2_CTRL_TYPE_INTEGER_MENU:
-               if (val < ctrl->minimum || val > ctrl->maximum)
+               if (c->value < ctrl->minimum || c->value > ctrl->maximum)
                        return -ERANGE;
-               if (ctrl->menu_skip_mask & (1 << val))
+               if (ctrl->menu_skip_mask & (1 << c->value))
                        return -EINVAL;
                if (ctrl->type == V4L2_CTRL_TYPE_MENU &&
-                   ctrl->qmenu[val][0] == '\0')
+                   ctrl->qmenu[c->value][0] == '\0')
                        return -EINVAL;
                return 0;
 
        case V4L2_CTRL_TYPE_BITMASK:
-               *pval &= ctrl->maximum;
+               c->value &= ctrl->maximum;
                return 0;
 
        case V4L2_CTRL_TYPE_BUTTON:
        case V4L2_CTRL_TYPE_CTRL_CLASS:
-               *pval = 0;
+               c->value = 0;
                return 0;
 
-       default:
-               return -EINVAL;
-       }
-}
-
-/* Validate a new control */
-static int validate_new(const struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
-{
-       char *s = c->string;
-       size_t len;
-
-       switch (ctrl->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_BITMASK:
-       case V4L2_CTRL_TYPE_BUTTON:
-       case V4L2_CTRL_TYPE_CTRL_CLASS:
-               return validate_new_int(ctrl, &c->value);
-
        case V4L2_CTRL_TYPE_INTEGER64:
                return 0;
 
        case V4L2_CTRL_TYPE_STRING:
-               len = strlen(s);
+               len = strlen(c->string);
                if (len < ctrl->minimum)
                        return -ERANGE;
                if ((len - ctrl->minimum) % ctrl->step)
@@ -1632,6 +1650,36 @@ struct v4l2_ctrl *v4l2_ctrl_new_std_menu(struct v4l2_ctrl_handler *hdl,
 }
 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)
+{
+       enum v4l2_ctrl_type type;
+       const char *name;
+       u32 flags;
+       s32 step;
+       s32 min;
+
+       /* v4l2_ctrl_new_std_menu_items() should only be called for
+        * standard controls without a standard menu.
+        */
+       if (v4l2_ctrl_get_menu(id)) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+
+       v4l2_ctrl_fill(id, &name, &type, &min, &max, &step, &def, &flags);
+       if (type != V4L2_CTRL_TYPE_MENU || qmenu == NULL) {
+               handler_set_err(hdl, -EINVAL);
+               return NULL;
+       }
+       return v4l2_ctrl_new(hdl, ops, id, name, type, 0, max, mask, def,
+                            flags, qmenu, NULL, NULL);
+
+}
+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,
@@ -1671,7 +1719,8 @@ EXPORT_SYMBOL(v4l2_ctrl_add_ctrl);
 
 /* Add the controls from another handler to our own. */
 int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
-                         struct v4l2_ctrl_handler *add)
+                         struct v4l2_ctrl_handler *add,
+                         bool (*filter)(const struct v4l2_ctrl *ctrl))
 {
        struct v4l2_ctrl_ref *ref;
        int ret = 0;
@@ -1691,6 +1740,9 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
                /* And control classes */
                if (ctrl->type == V4L2_CTRL_TYPE_CTRL_CLASS)
                        continue;
+               /* Filter any unwanted controls */
+               if (filter && !filter(ctrl))
+                       continue;
                ret = handler_new_ref(hdl, ctrl);
                if (ret)
                        break;
@@ -1700,6 +1752,25 @@ int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
 }
 EXPORT_SYMBOL(v4l2_ctrl_add_handler);
 
+bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl)
+{
+       if (V4L2_CTRL_ID2CLASS(ctrl->id) == V4L2_CTRL_CLASS_FM_TX)
+               return true;
+       switch (ctrl->id) {
+       case V4L2_CID_AUDIO_MUTE:
+       case V4L2_CID_AUDIO_VOLUME:
+       case V4L2_CID_AUDIO_BALANCE:
+       case V4L2_CID_AUDIO_BASS:
+       case V4L2_CID_AUDIO_TREBLE:
+       case V4L2_CID_AUDIO_LOUDNESS:
+               return true;
+       default:
+               break;
+       }
+       return false;
+}
+EXPORT_SYMBOL(v4l2_ctrl_radio_filter);
+
 /* Cluster controls */
 void v4l2_ctrl_cluster(unsigned ncontrols, struct v4l2_ctrl **controls)
 {
@@ -2235,12 +2306,19 @@ int v4l2_subdev_g_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs
 EXPORT_SYMBOL(v4l2_subdev_g_ext_ctrls);
 
 /* Helper function to get a single control */
-static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
+static int get_ctrl(struct v4l2_ctrl *ctrl, struct v4l2_ext_control *c)
 {
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int ret = 0;
        int i;
 
+       /* String 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)
+               return -EINVAL;
+
        if (ctrl->flags & V4L2_CTRL_FLAG_WRITE_ONLY)
                return -EACCES;
 
@@ -2250,9 +2328,9 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
                for (i = 0; i < master->ncontrols; i++)
                        cur_to_new(master->cluster[i]);
                ret = call_op(master, g_volatile_ctrl);
-               *val = ctrl->val;
+               new_to_user(c, ctrl);
        } else {
-               *val = ctrl->cur.val;
+               cur_to_user(c, ctrl);
        }
        v4l2_ctrl_unlock(master);
        return ret;
@@ -2261,10 +2339,14 @@ static int get_ctrl(struct v4l2_ctrl *ctrl, s32 *val)
 int v4l2_g_ctrl(struct v4l2_ctrl_handler *hdl, struct v4l2_control *control)
 {
        struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
+       struct v4l2_ext_control c;
+       int ret;
 
        if (ctrl == NULL || !type_is_int(ctrl))
                return -EINVAL;
-       return get_ctrl(ctrl, &control->value);
+       ret = get_ctrl(ctrl, &c);
+       control->value = c.value;
+       return ret;
 }
 EXPORT_SYMBOL(v4l2_g_ctrl);
 
@@ -2276,15 +2358,28 @@ EXPORT_SYMBOL(v4l2_subdev_g_ctrl);
 
 s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl)
 {
-       s32 val = 0;
+       struct v4l2_ext_control c;
 
        /* It's a driver bug if this happens. */
        WARN_ON(!type_is_int(ctrl));
-       get_ctrl(ctrl, &val);
-       return val;
+       c.value = 0;
+       get_ctrl(ctrl, &c);
+       return c.value;
 }
 EXPORT_SYMBOL(v4l2_ctrl_g_ctrl);
 
+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);
+       c.value = 0;
+       get_ctrl(ctrl, &c);
+       return c.value;
+}
+EXPORT_SYMBOL(v4l2_ctrl_g_ctrl_int64);
+
 
 /* Core function that calls try/s_ctrl and ensures that the new value is
    copied to the current value on a set.
@@ -2500,13 +2595,21 @@ int v4l2_subdev_s_ext_ctrls(struct v4l2_subdev *sd, struct v4l2_ext_controls *cs
 EXPORT_SYMBOL(v4l2_subdev_s_ext_ctrls);
 
 /* Helper function for VIDIOC_S_CTRL compatibility */
-static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
+static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl,
+                   struct v4l2_ext_control *c)
 {
        struct v4l2_ctrl *master = ctrl->cluster[0];
        int ret;
        int i;
 
-       ret = validate_new_int(ctrl, val);
+       /* String 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)
+               return -EINVAL;
+
+       ret = validate_new(ctrl, c);
        if (ret)
                return ret;
 
@@ -2521,12 +2624,13 @@ static int set_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl *ctrl, s32 *val)
           manual mode we have to update the current volatile values since
           those will become the initial manual values after such a switch. */
        if (master->is_auto && master->has_volatiles && ctrl == master &&
-           !is_cur_manual(master) && *val == master->manual_mode_value)
+           !is_cur_manual(master) && c->value == master->manual_mode_value)
                update_from_auto_cluster(master);
-       ctrl->val = *val;
-       ctrl->is_new = 1;
+
+       user_to_new(c, ctrl);
        ret = try_or_set_cluster(fh, master, true);
-       *val = ctrl->cur.val;
+       cur_to_user(c, ctrl);
+
        v4l2_ctrl_unlock(ctrl);
        return ret;
 }
@@ -2535,6 +2639,8 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
                                        struct v4l2_control *control)
 {
        struct v4l2_ctrl *ctrl = v4l2_ctrl_find(hdl, control->id);
+       struct v4l2_ext_control c;
+       int ret;
 
        if (ctrl == NULL || !type_is_int(ctrl))
                return -EINVAL;
@@ -2542,7 +2648,10 @@ int v4l2_s_ctrl(struct v4l2_fh *fh, struct v4l2_ctrl_handler *hdl,
        if (ctrl->flags & V4L2_CTRL_FLAG_READ_ONLY)
                return -EACCES;
 
-       return set_ctrl(fh, ctrl, &control->value);
+       c.value = control->value;
+       ret = set_ctrl(fh, ctrl, &c);
+       control->value = c.value;
+       return ret;
 }
 EXPORT_SYMBOL(v4l2_s_ctrl);
 
@@ -2554,12 +2663,26 @@ EXPORT_SYMBOL(v4l2_subdev_s_ctrl);
 
 int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val)
 {
+       struct v4l2_ext_control c;
+
        /* It's a driver bug if this happens. */
        WARN_ON(!type_is_int(ctrl));
-       return set_ctrl(NULL, ctrl, &val);
+       c.value = val;
+       return set_ctrl(NULL, ctrl, &c);
 }
 EXPORT_SYMBOL(v4l2_ctrl_s_ctrl);
 
+int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val)
+{
+       struct v4l2_ext_control c;
+
+       /* It's a driver bug if this happens. */
+       WARN_ON(ctrl->type != V4L2_CTRL_TYPE_INTEGER64);
+       c.value64 = val;
+       return set_ctrl(NULL, ctrl, &c);
+}
+EXPORT_SYMBOL(v4l2_ctrl_s_ctrl_int64);
+
 static int v4l2_ctrl_add_event(struct v4l2_subscribed_event *sev, unsigned elems)
 {
        struct v4l2_ctrl *ctrl = v4l2_ctrl_find(sev->fh->ctrl_handler, sev->id);
@@ -2631,7 +2754,7 @@ int v4l2_ctrl_log_status(struct file *file, void *fh)
 EXPORT_SYMBOL(v4l2_ctrl_log_status);
 
 int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
-                               struct v4l2_event_subscription *sub)
+                               const struct v4l2_event_subscription *sub)
 {
        if (sub->type == V4L2_EVENT_CTRL)
                return v4l2_event_subscribe(fh, sub, 0, &v4l2_ctrl_sub_ev_ops);
similarity index 79%
rename from drivers/media/video/v4l2-dev.c
rename to drivers/media/v4l2-core/v4l2-dev.c
index 07aeafca9eaabfd0f23117168945f0d1e603533a..a2df842e5100cfbffb16a0e88d4c2400d0666765 100644 (file)
@@ -298,13 +298,8 @@ static ssize_t v4l2_read(struct file *filp, char __user *buf,
 
        if (!vdev->fops->read)
                return -EINVAL;
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
-           mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->read(filp, buf, sz, off);
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-               mutex_unlock(vdev->lock);
        if (vdev->debug)
                printk(KERN_DEBUG "%s: read: %zd (%d)\n",
                        video_device_node_name(vdev), sz, ret);
@@ -319,13 +314,8 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 
        if (!vdev->fops->write)
                return -EINVAL;
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
-           mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
        if (video_is_registered(vdev))
                ret = vdev->fops->write(filp, buf, sz, off);
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-               mutex_unlock(vdev->lock);
        if (vdev->debug)
                printk(KERN_DEBUG "%s: write: %zd (%d)\n",
                        video_device_node_name(vdev), sz, ret);
@@ -335,20 +325,16 @@ static ssize_t v4l2_write(struct file *filp, const char __user *buf,
 static unsigned int v4l2_poll(struct file *filp, struct poll_table_struct *poll)
 {
        struct video_device *vdev = video_devdata(filp);
-       int ret = POLLERR | POLLHUP;
+       unsigned int res = POLLERR | POLLHUP;
 
        if (!vdev->fops->poll)
                return DEFAULT_POLLMASK;
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-               mutex_lock(vdev->lock);
        if (video_is_registered(vdev))
-               ret = vdev->fops->poll(filp, poll);
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-               mutex_unlock(vdev->lock);
+               res = vdev->fops->poll(filp, poll);
        if (vdev->debug)
                printk(KERN_DEBUG "%s: poll: %08x\n",
-                       video_device_node_name(vdev), ret);
-       return ret;
+                       video_device_node_name(vdev), res);
+       return res;
 }
 
 static long v4l2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
@@ -432,14 +418,9 @@ static int v4l2_mmap(struct file *filp, struct vm_area_struct *vm)
        int ret = -ENODEV;
 
        if (!vdev->fops->mmap)
-               return ret;
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
-           mutex_lock_interruptible(vdev->lock))
-               return -ERESTARTSYS;
+               return -ENODEV;
        if (video_is_registered(vdev))
                ret = vdev->fops->mmap(filp, vm);
-       if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-               mutex_unlock(vdev->lock);
        if (vdev->debug)
                printk(KERN_DEBUG "%s: mmap (%d)\n",
                        video_device_node_name(vdev), ret);
@@ -464,20 +445,12 @@ static int v4l2_open(struct inode *inode, struct file *filp)
        video_get(vdev);
        mutex_unlock(&videodev_lock);
        if (vdev->fops->open) {
-               if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) &&
-                   mutex_lock_interruptible(vdev->lock)) {
-                       ret = -ERESTARTSYS;
-                       goto err;
-               }
                if (video_is_registered(vdev))
                        ret = vdev->fops->open(filp);
                else
                        ret = -ENODEV;
-               if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-                       mutex_unlock(vdev->lock);
        }
 
-err:
        if (vdev->debug)
                printk(KERN_DEBUG "%s: open (%d)\n",
                        video_device_node_name(vdev), ret);
@@ -493,16 +466,12 @@ static int v4l2_release(struct inode *inode, struct file *filp)
        struct video_device *vdev = video_devdata(filp);
        int ret = 0;
 
-       if (vdev->fops->release) {
-               if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-                       mutex_lock(vdev->lock);
-               vdev->fops->release(filp);
-               if (test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags))
-                       mutex_unlock(vdev->lock);
-       }
+       if (vdev->fops->release)
+               ret = vdev->fops->release(filp);
        if (vdev->debug)
                printk(KERN_DEBUG "%s: release\n",
                        video_device_node_name(vdev));
+
        /* decrease the refcount unconditionally since the release()
           return value is ignored. */
        video_put(vdev);
@@ -582,9 +551,16 @@ static void determine_valid_ioctls(struct video_device *vdev)
 {
        DECLARE_BITMAP(valid_ioctls, BASE_VIDIOC_PRIVATE);
        const struct v4l2_ioctl_ops *ops = vdev->ioctl_ops;
+       bool is_vid = vdev->vfl_type == VFL_TYPE_GRABBER;
+       bool is_vbi = vdev->vfl_type == VFL_TYPE_VBI;
+       bool is_radio = vdev->vfl_type == VFL_TYPE_RADIO;
+       bool is_rx = vdev->vfl_dir != VFL_DIR_TX;
+       bool is_tx = vdev->vfl_dir != VFL_DIR_RX;
 
        bitmap_zero(valid_ioctls, BASE_VIDIOC_PRIVATE);
 
+       /* 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))
@@ -592,70 +568,12 @@ static void determine_valid_ioctls(struct video_device *vdev)
        if (ops->vidioc_s_priority ||
                        test_bit(V4L2_FL_USE_FH_PRIO, &vdev->flags))
                set_bit(_IOC_NR(VIDIOC_S_PRIORITY), valid_ioctls);
-       if (ops->vidioc_enum_fmt_vid_cap ||
-           ops->vidioc_enum_fmt_vid_out ||
-           ops->vidioc_enum_fmt_vid_cap_mplane ||
-           ops->vidioc_enum_fmt_vid_out_mplane ||
-           ops->vidioc_enum_fmt_vid_overlay ||
-           ops->vidioc_enum_fmt_type_private)
-               set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
-       if (ops->vidioc_g_fmt_vid_cap ||
-           ops->vidioc_g_fmt_vid_out ||
-           ops->vidioc_g_fmt_vid_cap_mplane ||
-           ops->vidioc_g_fmt_vid_out_mplane ||
-           ops->vidioc_g_fmt_vid_overlay ||
-           ops->vidioc_g_fmt_vbi_cap ||
-           ops->vidioc_g_fmt_vid_out_overlay ||
-           ops->vidioc_g_fmt_vbi_out ||
-           ops->vidioc_g_fmt_sliced_vbi_cap ||
-           ops->vidioc_g_fmt_sliced_vbi_out ||
-           ops->vidioc_g_fmt_type_private)
-               set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
-       if (ops->vidioc_s_fmt_vid_cap ||
-           ops->vidioc_s_fmt_vid_out ||
-           ops->vidioc_s_fmt_vid_cap_mplane ||
-           ops->vidioc_s_fmt_vid_out_mplane ||
-           ops->vidioc_s_fmt_vid_overlay ||
-           ops->vidioc_s_fmt_vbi_cap ||
-           ops->vidioc_s_fmt_vid_out_overlay ||
-           ops->vidioc_s_fmt_vbi_out ||
-           ops->vidioc_s_fmt_sliced_vbi_cap ||
-           ops->vidioc_s_fmt_sliced_vbi_out ||
-           ops->vidioc_s_fmt_type_private)
-               set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
-       if (ops->vidioc_try_fmt_vid_cap ||
-           ops->vidioc_try_fmt_vid_out ||
-           ops->vidioc_try_fmt_vid_cap_mplane ||
-           ops->vidioc_try_fmt_vid_out_mplane ||
-           ops->vidioc_try_fmt_vid_overlay ||
-           ops->vidioc_try_fmt_vbi_cap ||
-           ops->vidioc_try_fmt_vid_out_overlay ||
-           ops->vidioc_try_fmt_vbi_out ||
-           ops->vidioc_try_fmt_sliced_vbi_cap ||
-           ops->vidioc_try_fmt_sliced_vbi_out ||
-           ops->vidioc_try_fmt_type_private)
-               set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
        SET_VALID_IOCTL(ops, VIDIOC_REQBUFS, vidioc_reqbufs);
        SET_VALID_IOCTL(ops, VIDIOC_QUERYBUF, vidioc_querybuf);
        SET_VALID_IOCTL(ops, VIDIOC_QBUF, vidioc_qbuf);
        SET_VALID_IOCTL(ops, VIDIOC_DQBUF, vidioc_dqbuf);
-       SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
-       SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
-       SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf);
        SET_VALID_IOCTL(ops, VIDIOC_STREAMON, vidioc_streamon);
        SET_VALID_IOCTL(ops, VIDIOC_STREAMOFF, vidioc_streamoff);
-       if (vdev->tvnorms)
-               set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
-       if (ops->vidioc_g_std || vdev->current_norm)
-               set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls);
-       SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
-       SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
-       SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
-       SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
-       SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
-       SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
        /* 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
@@ -674,56 +592,14 @@ static void determine_valid_ioctls(struct video_device *vdev)
                set_bit(_IOC_NR(VIDIOC_TRY_EXT_CTRLS), valid_ioctls);
        if (vdev->ctrl_handler || ops->vidioc_querymenu)
                set_bit(_IOC_NR(VIDIOC_QUERYMENU), valid_ioctls);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
-       SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
-       SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout);
-       SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
-       SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
-       SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
-       SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator);
-       if (ops->vidioc_g_crop || ops->vidioc_g_selection)
-               set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
-       if (ops->vidioc_s_crop || ops->vidioc_s_selection)
-               set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
-       SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
-       SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
-       if (ops->vidioc_cropcap || ops->vidioc_g_selection)
-               set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
-       SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp);
-       SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp);
-       SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index);
-       SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd);
-       SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd);
-       SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd);
-       SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
-       if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER &&
-                                       (ops->vidioc_g_std || vdev->tvnorms)))
-               set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
-       SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
-       SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner);
-       SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
        SET_VALID_IOCTL(ops, VIDIOC_G_FREQUENCY, vidioc_g_frequency);
        SET_VALID_IOCTL(ops, VIDIOC_S_FREQUENCY, vidioc_s_frequency);
-       SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
        SET_VALID_IOCTL(ops, VIDIOC_LOG_STATUS, vidioc_log_status);
 #ifdef CONFIG_VIDEO_ADV_DEBUG
        SET_VALID_IOCTL(ops, VIDIOC_DBG_G_REGISTER, vidioc_g_register);
        SET_VALID_IOCTL(ops, VIDIOC_DBG_S_REGISTER, vidioc_s_register);
 #endif
        SET_VALID_IOCTL(ops, VIDIOC_DBG_G_CHIP_IDENT, vidioc_g_chip_ident);
-       SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
-       SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
-       SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
-       SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
-       SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
-       SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
-       SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
-       SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings);
-       SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap);
        /* yes, really vidioc_subscribe_event */
        SET_VALID_IOCTL(ops, VIDIOC_DQEVENT, vidioc_subscribe_event);
        SET_VALID_IOCTL(ops, VIDIOC_SUBSCRIBE_EVENT, vidioc_subscribe_event);
@@ -732,6 +608,125 @@ static void determine_valid_ioctls(struct video_device *vdev)
        SET_VALID_IOCTL(ops, VIDIOC_PREPARE_BUF, vidioc_prepare_buf);
        if (ops->vidioc_enum_freq_bands || ops->vidioc_g_tuner || ops->vidioc_g_modulator)
                set_bit(_IOC_NR(VIDIOC_ENUM_FREQ_BANDS), valid_ioctls);
+
+       if (is_vid) {
+               /* video specific ioctls */
+               if ((is_rx && (ops->vidioc_enum_fmt_vid_cap ||
+                              ops->vidioc_enum_fmt_vid_cap_mplane ||
+                              ops->vidioc_enum_fmt_vid_overlay)) ||
+                   (is_tx && (ops->vidioc_enum_fmt_vid_out ||
+                              ops->vidioc_enum_fmt_vid_out_mplane)))
+                       set_bit(_IOC_NR(VIDIOC_ENUM_FMT), valid_ioctls);
+               if ((is_rx && (ops->vidioc_g_fmt_vid_cap ||
+                              ops->vidioc_g_fmt_vid_cap_mplane ||
+                              ops->vidioc_g_fmt_vid_overlay)) ||
+                   (is_tx && (ops->vidioc_g_fmt_vid_out ||
+                              ops->vidioc_g_fmt_vid_out_mplane ||
+                              ops->vidioc_g_fmt_vid_out_overlay)))
+                        set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+               if ((is_rx && (ops->vidioc_s_fmt_vid_cap ||
+                              ops->vidioc_s_fmt_vid_cap_mplane ||
+                              ops->vidioc_s_fmt_vid_overlay)) ||
+                   (is_tx && (ops->vidioc_s_fmt_vid_out ||
+                              ops->vidioc_s_fmt_vid_out_mplane ||
+                              ops->vidioc_s_fmt_vid_out_overlay)))
+                        set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+               if ((is_rx && (ops->vidioc_try_fmt_vid_cap ||
+                              ops->vidioc_try_fmt_vid_cap_mplane ||
+                              ops->vidioc_try_fmt_vid_overlay)) ||
+                   (is_tx && (ops->vidioc_try_fmt_vid_out ||
+                              ops->vidioc_try_fmt_vid_out_mplane ||
+                              ops->vidioc_try_fmt_vid_out_overlay)))
+                        set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_OVERLAY, vidioc_overlay);
+               SET_VALID_IOCTL(ops, VIDIOC_G_FBUF, vidioc_g_fbuf);
+               SET_VALID_IOCTL(ops, VIDIOC_S_FBUF, vidioc_s_fbuf);
+               SET_VALID_IOCTL(ops, VIDIOC_G_JPEGCOMP, vidioc_g_jpegcomp);
+               SET_VALID_IOCTL(ops, VIDIOC_S_JPEGCOMP, vidioc_s_jpegcomp);
+               SET_VALID_IOCTL(ops, VIDIOC_G_ENC_INDEX, vidioc_g_enc_index);
+               SET_VALID_IOCTL(ops, VIDIOC_ENCODER_CMD, vidioc_encoder_cmd);
+               SET_VALID_IOCTL(ops, VIDIOC_TRY_ENCODER_CMD, vidioc_try_encoder_cmd);
+               SET_VALID_IOCTL(ops, VIDIOC_DECODER_CMD, vidioc_decoder_cmd);
+               SET_VALID_IOCTL(ops, VIDIOC_TRY_DECODER_CMD, vidioc_try_decoder_cmd);
+               SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMESIZES, vidioc_enum_framesizes);
+               SET_VALID_IOCTL(ops, VIDIOC_ENUM_FRAMEINTERVALS, vidioc_enum_frameintervals);
+       } else if (is_vbi) {
+               /* vbi specific ioctls */
+               if ((is_rx && (ops->vidioc_g_fmt_vbi_cap ||
+                              ops->vidioc_g_fmt_sliced_vbi_cap)) ||
+                   (is_tx && (ops->vidioc_g_fmt_vbi_out ||
+                              ops->vidioc_g_fmt_sliced_vbi_out)))
+                       set_bit(_IOC_NR(VIDIOC_G_FMT), valid_ioctls);
+               if ((is_rx && (ops->vidioc_s_fmt_vbi_cap ||
+                              ops->vidioc_s_fmt_sliced_vbi_cap)) ||
+                   (is_tx && (ops->vidioc_s_fmt_vbi_out ||
+                              ops->vidioc_s_fmt_sliced_vbi_out)))
+                       set_bit(_IOC_NR(VIDIOC_S_FMT), valid_ioctls);
+               if ((is_rx && (ops->vidioc_try_fmt_vbi_cap ||
+                              ops->vidioc_try_fmt_sliced_vbi_cap)) ||
+                   (is_tx && (ops->vidioc_try_fmt_vbi_out ||
+                              ops->vidioc_try_fmt_sliced_vbi_out)))
+                       set_bit(_IOC_NR(VIDIOC_TRY_FMT), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_G_SLICED_VBI_CAP, vidioc_g_sliced_vbi_cap);
+       }
+       if (!is_radio) {
+               /* ioctls valid for video or vbi */
+               if (ops->vidioc_s_std)
+                       set_bit(_IOC_NR(VIDIOC_ENUMSTD), valid_ioctls);
+               if (ops->vidioc_g_std || vdev->current_norm)
+                       set_bit(_IOC_NR(VIDIOC_G_STD), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_S_STD, vidioc_s_std);
+               if (is_rx) {
+                       SET_VALID_IOCTL(ops, VIDIOC_QUERYSTD, vidioc_querystd);
+                       SET_VALID_IOCTL(ops, VIDIOC_ENUMINPUT, vidioc_enum_input);
+                       SET_VALID_IOCTL(ops, VIDIOC_G_INPUT, vidioc_g_input);
+                       SET_VALID_IOCTL(ops, VIDIOC_S_INPUT, vidioc_s_input);
+                       SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDIO, vidioc_enumaudio);
+                       SET_VALID_IOCTL(ops, VIDIOC_G_AUDIO, vidioc_g_audio);
+                       SET_VALID_IOCTL(ops, VIDIOC_S_AUDIO, vidioc_s_audio);
+                       SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_PRESET, vidioc_query_dv_preset);
+                       SET_VALID_IOCTL(ops, VIDIOC_QUERY_DV_TIMINGS, vidioc_query_dv_timings);
+               }
+               if (is_tx) {
+                       SET_VALID_IOCTL(ops, VIDIOC_ENUMOUTPUT, vidioc_enum_output);
+                       SET_VALID_IOCTL(ops, VIDIOC_G_OUTPUT, vidioc_g_output);
+                       SET_VALID_IOCTL(ops, VIDIOC_S_OUTPUT, vidioc_s_output);
+                       SET_VALID_IOCTL(ops, VIDIOC_ENUMAUDOUT, vidioc_enumaudout);
+                       SET_VALID_IOCTL(ops, VIDIOC_G_AUDOUT, vidioc_g_audout);
+                       SET_VALID_IOCTL(ops, VIDIOC_S_AUDOUT, vidioc_s_audout);
+               }
+               if (ops->vidioc_g_crop || ops->vidioc_g_selection)
+                       set_bit(_IOC_NR(VIDIOC_G_CROP), valid_ioctls);
+               if (ops->vidioc_s_crop || ops->vidioc_s_selection)
+                       set_bit(_IOC_NR(VIDIOC_S_CROP), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_G_SELECTION, vidioc_g_selection);
+               SET_VALID_IOCTL(ops, VIDIOC_S_SELECTION, vidioc_s_selection);
+               if (ops->vidioc_cropcap || ops->vidioc_g_selection)
+                       set_bit(_IOC_NR(VIDIOC_CROPCAP), valid_ioctls);
+               if (ops->vidioc_g_parm || (vdev->vfl_type == VFL_TYPE_GRABBER &&
+                                       (ops->vidioc_g_std || vdev->current_norm)))
+                       set_bit(_IOC_NR(VIDIOC_G_PARM), valid_ioctls);
+               SET_VALID_IOCTL(ops, VIDIOC_S_PARM, vidioc_s_parm);
+               SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_PRESETS, vidioc_enum_dv_presets);
+               SET_VALID_IOCTL(ops, VIDIOC_S_DV_PRESET, vidioc_s_dv_preset);
+               SET_VALID_IOCTL(ops, VIDIOC_G_DV_PRESET, vidioc_g_dv_preset);
+               SET_VALID_IOCTL(ops, VIDIOC_S_DV_TIMINGS, vidioc_s_dv_timings);
+               SET_VALID_IOCTL(ops, VIDIOC_G_DV_TIMINGS, vidioc_g_dv_timings);
+               SET_VALID_IOCTL(ops, VIDIOC_ENUM_DV_TIMINGS, vidioc_enum_dv_timings);
+               SET_VALID_IOCTL(ops, VIDIOC_DV_TIMINGS_CAP, vidioc_dv_timings_cap);
+       }
+       if (is_tx) {
+               /* transmitter only ioctls */
+               SET_VALID_IOCTL(ops, VIDIOC_G_MODULATOR, vidioc_g_modulator);
+               SET_VALID_IOCTL(ops, VIDIOC_S_MODULATOR, vidioc_s_modulator);
+       }
+       if (is_rx) {
+               /* receiver only ioctls */
+               SET_VALID_IOCTL(ops, VIDIOC_G_TUNER, vidioc_g_tuner);
+               SET_VALID_IOCTL(ops, VIDIOC_S_TUNER, vidioc_s_tuner);
+               SET_VALID_IOCTL(ops, VIDIOC_S_HW_FREQ_SEEK, vidioc_s_hw_freq_seek);
+       }
+
        bitmap_andnot(vdev->valid_ioctls, valid_ioctls, vdev->valid_ioctls,
                        BASE_VIDIOC_PRIVATE);
 }
@@ -882,10 +877,6 @@ int __video_register_device(struct video_device *vdev, int type, int nr,
        WARN_ON(video_device[vdev->minor] != NULL);
        vdev->index = get_index(vdev);
        mutex_unlock(&videodev_lock);
-       /* if no lock was passed, then make sure the LOCK_ALL_FOPS bit is
-          clear and warn if it wasn't. */
-       if (vdev->lock == NULL)
-               WARN_ON(test_and_clear_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags));
 
        if (vdev->ioctl_ops)
                determine_valid_ioctls(vdev);
similarity index 99%
rename from drivers/media/video/v4l2-device.c
rename to drivers/media/v4l2-core/v4l2-device.c
index 1f203b85a63739463a448259800b31f240359bbf..513969fa695d89f0a424b2b0456c9496e1010993 100644 (file)
@@ -166,7 +166,7 @@ int v4l2_device_register_subdev(struct v4l2_device *v4l2_dev,
        }
 
        /* This just returns 0 if either of the two args is NULL */
-       err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler);
+       err = v4l2_ctrl_add_handler(v4l2_dev->ctrl_handler, sd->ctrl_handler, NULL);
        if (err) {
                if (sd->internal_ops && sd->internal_ops->unregistered)
                        sd->internal_ops->unregistered(sd);
similarity index 98%
rename from drivers/media/video/v4l2-event.c
rename to drivers/media/v4l2-core/v4l2-event.c
index ef2a33c9404559a4d4e0f80c23de45c10e8baf0a..18a040b935a312d31abb944c50405e026a510f1b 100644 (file)
@@ -203,7 +203,7 @@ int v4l2_event_pending(struct v4l2_fh *fh)
 EXPORT_SYMBOL_GPL(v4l2_event_pending);
 
 int v4l2_event_subscribe(struct v4l2_fh *fh,
-                        struct v4l2_event_subscription *sub, unsigned elems,
+                        const struct v4l2_event_subscription *sub, unsigned elems,
                         const struct v4l2_subscribed_event_ops *ops)
 {
        struct v4l2_subscribed_event *sev, *found_ev;
@@ -278,7 +278,7 @@ void v4l2_event_unsubscribe_all(struct v4l2_fh *fh)
 EXPORT_SYMBOL_GPL(v4l2_event_unsubscribe_all);
 
 int v4l2_event_unsubscribe(struct v4l2_fh *fh,
-                          struct v4l2_event_subscription *sub)
+                          const struct v4l2_event_subscription *sub)
 {
        struct v4l2_subscribed_event *sev;
        unsigned long flags;
similarity index 92%
rename from drivers/media/video/v4l2-ioctl.c
rename to drivers/media/v4l2-core/v4l2-ioctl.c
index 6bc47fc82fe2f799bfff8a3f885fae27bf1a0aa0..16205d9bddfcf3b04ae636e9db67645e90e6c520 100644 (file)
@@ -316,9 +316,6 @@ static void v4l_print_format(const void *arg, bool write_only)
                                sliced->service_lines[0][i],
                                sliced->service_lines[1][i]);
                break;
-       case V4L2_BUF_TYPE_PRIVATE:
-               pr_cont("\n");
-               break;
        }
 }
 
@@ -879,57 +876,62 @@ static int check_ext_ctrls(struct v4l2_ext_controls *c, int allow_priv)
        return 1;
 }
 
-static int check_fmt(const struct v4l2_ioctl_ops *ops, enum v4l2_buf_type type)
+static int check_fmt(struct file *file, enum v4l2_buf_type type)
 {
+       struct video_device *vfd = video_devdata(file);
+       const struct v4l2_ioctl_ops *ops = vfd->ioctl_ops;
+       bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+       bool is_vbi = vfd->vfl_type == VFL_TYPE_VBI;
+       bool is_rx = vfd->vfl_dir != VFL_DIR_TX;
+       bool is_tx = vfd->vfl_dir != VFL_DIR_RX;
+
        if (ops == NULL)
                return -EINVAL;
 
        switch (type) {
        case V4L2_BUF_TYPE_VIDEO_CAPTURE:
-               if (ops->vidioc_g_fmt_vid_cap ||
-                               ops->vidioc_g_fmt_vid_cap_mplane)
+               if (is_vid && is_rx &&
+                   (ops->vidioc_g_fmt_vid_cap || ops->vidioc_g_fmt_vid_cap_mplane))
                        return 0;
                break;
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               if (ops->vidioc_g_fmt_vid_cap_mplane)
+               if (is_vid && is_rx && ops->vidioc_g_fmt_vid_cap_mplane)
                        return 0;
                break;
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               if (ops->vidioc_g_fmt_vid_overlay)
+               if (is_vid && is_rx && ops->vidioc_g_fmt_vid_overlay)
                        return 0;
                break;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               if (ops->vidioc_g_fmt_vid_out ||
-                               ops->vidioc_g_fmt_vid_out_mplane)
+               if (is_vid && is_tx &&
+                   (ops->vidioc_g_fmt_vid_out || ops->vidioc_g_fmt_vid_out_mplane))
                        return 0;
                break;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (ops->vidioc_g_fmt_vid_out_mplane)
+               if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_mplane)
                        return 0;
                break;
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-               if (ops->vidioc_g_fmt_vid_out_overlay)
+               if (is_vid && is_tx && ops->vidioc_g_fmt_vid_out_overlay)
                        return 0;
                break;
        case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (ops->vidioc_g_fmt_vbi_cap)
+               if (is_vbi && is_rx && ops->vidioc_g_fmt_vbi_cap)
                        return 0;
                break;
        case V4L2_BUF_TYPE_VBI_OUTPUT:
-               if (ops->vidioc_g_fmt_vbi_out)
+               if (is_vbi && is_tx && ops->vidioc_g_fmt_vbi_out)
                        return 0;
                break;
        case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               if (ops->vidioc_g_fmt_sliced_vbi_cap)
+               if (is_vbi && is_rx && ops->vidioc_g_fmt_sliced_vbi_cap)
                        return 0;
                break;
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               if (ops->vidioc_g_fmt_sliced_vbi_out)
+               if (is_vbi && is_tx && ops->vidioc_g_fmt_sliced_vbi_out)
                        return 0;
                break;
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (ops->vidioc_g_fmt_type_private)
-                       return 0;
+       default:
                break;
        }
        return -EINVAL;
@@ -989,7 +991,7 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
        struct v4l2_input *p = arg;
 
        /*
-        * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+        * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS &
         * CAP_STD here based on ioctl handler provided by the
         * driver. If the driver doesn't support these
         * for a specific input, it must override these flags.
@@ -999,7 +1001,7 @@ static int v4l_enuminput(const struct v4l2_ioctl_ops *ops,
        if (ops->vidioc_s_dv_preset)
                p->capabilities |= V4L2_IN_CAP_PRESETS;
        if (ops->vidioc_s_dv_timings)
-               p->capabilities |= V4L2_IN_CAP_CUSTOM_TIMINGS;
+               p->capabilities |= V4L2_IN_CAP_DV_TIMINGS;
 
        return ops->vidioc_enum_input(file, fh, p);
 }
@@ -1010,7 +1012,7 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
        struct v4l2_output *p = arg;
 
        /*
-        * We set the flags for CAP_PRESETS, CAP_CUSTOM_TIMINGS &
+        * We set the flags for CAP_PRESETS, CAP_DV_TIMINGS &
         * CAP_STD here based on ioctl handler provided by the
         * driver. If the driver doesn't support these
         * for a specific output, it must override these flags.
@@ -1020,7 +1022,7 @@ static int v4l_enumoutput(const struct v4l2_ioctl_ops *ops,
        if (ops->vidioc_s_dv_preset)
                p->capabilities |= V4L2_OUT_CAP_PRESETS;
        if (ops->vidioc_s_dv_timings)
-               p->capabilities |= V4L2_OUT_CAP_CUSTOM_TIMINGS;
+               p->capabilities |= V4L2_OUT_CAP_DV_TIMINGS;
 
        return ops->vidioc_enum_output(file, fh, p);
 }
@@ -1029,32 +1031,31 @@ static int v4l_enum_fmt(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_fmtdesc *p = arg;
+       struct video_device *vfd = video_devdata(file);
+       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(!ops->vidioc_enum_fmt_vid_cap))
+               if (unlikely(!is_rx || !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(!ops->vidioc_enum_fmt_vid_cap_mplane))
+               if (unlikely(!is_rx || !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(!ops->vidioc_enum_fmt_vid_overlay))
+               if (unlikely(!is_rx || !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(!ops->vidioc_enum_fmt_vid_out))
+               if (unlikely(!is_tx || !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(!ops->vidioc_enum_fmt_vid_out_mplane))
+               if (unlikely(!is_tx || !ops->vidioc_enum_fmt_vid_out_mplane))
                        break;
                return ops->vidioc_enum_fmt_vid_out_mplane(file, fh, arg);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (unlikely(!ops->vidioc_enum_fmt_type_private))
-                       break;
-               return ops->vidioc_enum_fmt_type_private(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1063,52 +1064,52 @@ static int v4l_g_fmt(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_format *p = arg;
+       struct video_device *vfd = video_devdata(file);
+       bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+       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(!ops->vidioc_g_fmt_vid_cap))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap))
                        break;
                return ops->vidioc_g_fmt_vid_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               if (unlikely(!ops->vidioc_g_fmt_vid_cap_mplane))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_cap_mplane))
                        break;
                return ops->vidioc_g_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               if (unlikely(!ops->vidioc_g_fmt_vid_overlay))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_g_fmt_vid_overlay))
                        break;
                return ops->vidioc_g_fmt_vid_overlay(file, fh, arg);
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_vbi_cap))
+                       break;
+               return ops->vidioc_g_fmt_vbi_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_cap))
+                       break;
+               return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               if (unlikely(!ops->vidioc_g_fmt_vid_out))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out))
                        break;
                return ops->vidioc_g_fmt_vid_out(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (unlikely(!ops->vidioc_g_fmt_vid_out_mplane))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_mplane))
                        break;
                return ops->vidioc_g_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-               if (unlikely(!ops->vidioc_g_fmt_vid_out_overlay))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_g_fmt_vid_out_overlay))
                        break;
                return ops->vidioc_g_fmt_vid_out_overlay(file, fh, arg);
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_g_fmt_vbi_cap))
-                       break;
-               return ops->vidioc_g_fmt_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_g_fmt_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_vbi_out))
                        break;
                return ops->vidioc_g_fmt_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_cap))
-                       break;
-               return ops->vidioc_g_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_g_fmt_sliced_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_g_fmt_sliced_vbi_out))
                        break;
                return ops->vidioc_g_fmt_sliced_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (unlikely(!ops->vidioc_g_fmt_type_private))
-                       break;
-               return ops->vidioc_g_fmt_type_private(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1117,62 +1118,62 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_format *p = arg;
+       struct video_device *vfd = video_devdata(file);
+       bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+       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(!ops->vidioc_s_fmt_vid_cap))
+               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);
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
                return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_s_fmt_vid_overlay))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.win);
                return ops->vidioc_s_fmt_vid_overlay(file, fh, arg);
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_vbi_cap))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.vbi);
+               return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_cap))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.sliced);
+               return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               if (unlikely(!ops->vidioc_s_fmt_vid_out))
+               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);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
                return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-               if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_s_fmt_vid_out_overlay))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.win);
                return ops->vidioc_s_fmt_vid_out_overlay(file, fh, arg);
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_s_fmt_vbi_cap))
-                       break;
-               CLEAR_AFTER_FIELD(p, fmt.vbi);
-               return ops->vidioc_s_fmt_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_s_fmt_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_vbi_out))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.vbi);
                return ops->vidioc_s_fmt_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_cap))
-                       break;
-               CLEAR_AFTER_FIELD(p, fmt.sliced);
-               return ops->vidioc_s_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_s_fmt_sliced_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_s_fmt_sliced_vbi_out))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.sliced);
                return ops->vidioc_s_fmt_sliced_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (unlikely(!ops->vidioc_s_fmt_type_private))
-                       break;
-               return ops->vidioc_s_fmt_type_private(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1181,62 +1182,62 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_format *p = arg;
+       struct video_device *vfd = video_devdata(file);
+       bool is_vid = vfd->vfl_type == VFL_TYPE_GRABBER;
+       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(!ops->vidioc_try_fmt_vid_cap))
+               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);
        case V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE:
-               if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
                return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
-               if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
+               if (unlikely(!is_rx || !is_vid || !ops->vidioc_try_fmt_vid_overlay))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.win);
                return ops->vidioc_try_fmt_vid_overlay(file, fh, arg);
+       case V4L2_BUF_TYPE_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_vbi_cap))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.vbi);
+               return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
+       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
+               if (unlikely(!is_rx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_cap))
+                       break;
+               CLEAR_AFTER_FIELD(p, fmt.sliced);
+               return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT:
-               if (unlikely(!ops->vidioc_try_fmt_vid_out))
+               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);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE:
-               if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp);
                return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
-               if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
+               if (unlikely(!is_tx || !is_vid || !ops->vidioc_try_fmt_vid_out_overlay))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.win);
                return ops->vidioc_try_fmt_vid_out_overlay(file, fh, arg);
-       case V4L2_BUF_TYPE_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_try_fmt_vbi_cap))
-                       break;
-               CLEAR_AFTER_FIELD(p, fmt.vbi);
-               return ops->vidioc_try_fmt_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_try_fmt_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_vbi_out))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.vbi);
                return ops->vidioc_try_fmt_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_SLICED_VBI_CAPTURE:
-               if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_cap))
-                       break;
-               CLEAR_AFTER_FIELD(p, fmt.sliced);
-               return ops->vidioc_try_fmt_sliced_vbi_cap(file, fh, arg);
        case V4L2_BUF_TYPE_SLICED_VBI_OUTPUT:
-               if (unlikely(!ops->vidioc_try_fmt_sliced_vbi_out))
+               if (unlikely(!is_tx || is_vid || !ops->vidioc_try_fmt_sliced_vbi_out))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.sliced);
                return ops->vidioc_try_fmt_sliced_vbi_out(file, fh, arg);
-       case V4L2_BUF_TYPE_PRIVATE:
-               if (unlikely(!ops->vidioc_try_fmt_type_private))
-                       break;
-               return ops->vidioc_try_fmt_type_private(file, fh, arg);
        }
        return -EINVAL;
 }
@@ -1325,6 +1326,11 @@ static int v4l_enumstd(const struct v4l2_ioctl_ops *ops,
        unsigned int index = p->index, i, j = 0;
        const char *descr = "";
 
+       /* Return -ENODATA if the tvnorms for the current input
+          or output is 0, meaning that it doesn't support this API. */
+       if (id == 0)
+               return -ENODATA;
+
        /* Return norm array in a canonical way */
        for (i = 0; i <= index && id; i++) {
                /* last std value in the standards array is 0, so this
@@ -1416,17 +1422,22 @@ static int v4l_s_hw_freq_seek(const struct v4l2_ioctl_ops *ops,
        return ops->vidioc_s_hw_freq_seek(file, fh, p);
 }
 
+static int v4l_overlay(const struct v4l2_ioctl_ops *ops,
+                               struct file *file, void *fh, void *arg)
+{
+       return ops->vidioc_overlay(file, fh, *(unsigned int *)arg);
+}
+
 static int v4l_reqbufs(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_requestbuffers *p = arg;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        if (ret)
                return ret;
 
-       if (p->type < V4L2_BUF_TYPE_PRIVATE)
-               CLEAR_AFTER_FIELD(p, memory);
+       CLEAR_AFTER_FIELD(p, memory);
 
        return ops->vidioc_reqbufs(file, fh, p);
 }
@@ -1435,7 +1446,7 @@ static int v4l_querybuf(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_buffer *p = arg;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        return ret ? ret : ops->vidioc_querybuf(file, fh, p);
 }
@@ -1444,7 +1455,7 @@ static int v4l_qbuf(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_buffer *p = arg;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        return ret ? ret : ops->vidioc_qbuf(file, fh, p);
 }
@@ -1453,7 +1464,7 @@ static int v4l_dqbuf(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_buffer *p = arg;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        return ret ? ret : ops->vidioc_dqbuf(file, fh, p);
 }
@@ -1462,7 +1473,7 @@ static int v4l_create_bufs(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_create_buffers *create = arg;
-       int ret = check_fmt(ops, create->format.type);
+       int ret = check_fmt(file, create->format.type);
 
        return ret ? ret : ops->vidioc_create_bufs(file, fh, create);
 }
@@ -1471,7 +1482,7 @@ static int v4l_prepare_buf(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_buffer *b = arg;
-       int ret = check_fmt(ops, b->type);
+       int ret = check_fmt(file, b->type);
 
        return ret ? ret : ops->vidioc_prepare_buf(file, fh, b);
 }
@@ -1482,7 +1493,7 @@ static int v4l_g_parm(const struct v4l2_ioctl_ops *ops,
        struct video_device *vfd = video_devdata(file);
        struct v4l2_streamparm *p = arg;
        v4l2_std_id std;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        if (ret)
                return ret;
@@ -1505,7 +1516,7 @@ static int v4l_s_parm(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_streamparm *p = arg;
-       int ret = check_fmt(ops, p->type);
+       int ret = check_fmt(file, p->type);
 
        return ret ? ret : ops->vidioc_s_parm(file, fh, p);
 }
@@ -1827,6 +1838,10 @@ static int v4l_g_sliced_vbi_cap(const struct v4l2_ioctl_ops *ops,
                                struct file *file, void *fh, void *arg)
 {
        struct v4l2_sliced_vbi_cap *p = arg;
+       int ret = check_fmt(file, p->type);
+
+       if (ret)
+               return ret;
 
        /* Clear up to type, everything after type is zeroed already */
        memset(p, 0, offsetof(struct v4l2_sliced_vbi_cap, type));
@@ -1944,7 +1959,7 @@ static struct v4l2_ioctl_info v4l2_ioctls[] = {
        IOCTL_INFO_FNC(VIDIOC_QUERYBUF, v4l_querybuf, v4l_print_buffer, INFO_FL_QUEUE | INFO_FL_CLEAR(v4l2_buffer, length)),
        IOCTL_INFO_STD(VIDIOC_G_FBUF, vidioc_g_fbuf, v4l_print_framebuffer, 0),
        IOCTL_INFO_STD(VIDIOC_S_FBUF, vidioc_s_fbuf, v4l_print_framebuffer, INFO_FL_PRIO),
-       IOCTL_INFO_STD(VIDIOC_OVERLAY, vidioc_overlay, v4l_print_u32, INFO_FL_PRIO),
+       IOCTL_INFO_FNC(VIDIOC_OVERLAY, v4l_overlay, v4l_print_u32, INFO_FL_PRIO),
        IOCTL_INFO_FNC(VIDIOC_QBUF, v4l_qbuf, v4l_print_buffer, INFO_FL_QUEUE),
        IOCTL_INFO_FNC(VIDIOC_DQBUF, v4l_dqbuf, v4l_print_buffer, INFO_FL_QUEUE),
        IOCTL_INFO_FNC(VIDIOC_STREAMON, v4l_streamon, v4l_print_buftype, INFO_FL_PRIO | INFO_FL_QUEUE),
@@ -2173,6 +2188,7 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
        int ret = 0;
 
        switch (cmd) {
+       case VIDIOC_PREPARE_BUF:
        case VIDIOC_QUERYBUF:
        case VIDIOC_QBUF:
        case VIDIOC_DQBUF: {
@@ -2191,6 +2207,19 @@ static int check_array_args(unsigned int cmd, void *parg, size_t *array_size,
                break;
        }
 
+       case VIDIOC_SUBDEV_G_EDID:
+       case VIDIOC_SUBDEV_S_EDID: {
+               struct v4l2_subdev_edid *edid = parg;
+
+               if (edid->blocks) {
+                       *user_ptr = (void __user *)edid->edid;
+                       *kernel_ptr = (void *)&edid->edid;
+                       *array_size = edid->blocks * 128;
+                       ret = 1;
+               }
+               break;
+       }
+
        case VIDIOC_S_EXT_CTRLS:
        case VIDIOC_G_EXT_CTRLS:
        case VIDIOC_TRY_EXT_CTRLS: {
similarity index 98%
rename from drivers/media/video/v4l2-mem2mem.c
rename to drivers/media/v4l2-core/v4l2-mem2mem.c
index 97b48318aee1826d3ad3bf5225efb93d053b02cc..3ac83583ad7ae5695e3087d2960bc88647c4e501 100644 (file)
@@ -105,7 +105,7 @@ void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx)
                return NULL;
        }
 
-       b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
+       b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list);
        spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
        return &b->vb;
 }
@@ -125,7 +125,7 @@ void *v4l2_m2m_buf_remove(struct v4l2_m2m_queue_ctx *q_ctx)
                spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
                return NULL;
        }
-       b = list_entry(q_ctx->rdy_queue.next, struct v4l2_m2m_buffer, list);
+       b = list_first_entry(&q_ctx->rdy_queue, struct v4l2_m2m_buffer, list);
        list_del(&b->list);
        q_ctx->num_rdy--;
        spin_unlock_irqrestore(&q_ctx->rdy_spinlock, flags);
@@ -178,7 +178,7 @@ static void v4l2_m2m_try_run(struct v4l2_m2m_dev *m2m_dev)
                return;
        }
 
-       m2m_dev->curr_ctx = list_entry(m2m_dev->job_queue.next,
+       m2m_dev->curr_ctx = list_first_entry(&m2m_dev->job_queue,
                                   struct v4l2_m2m_ctx, queue);
        m2m_dev->curr_ctx->job_flags |= TRANS_RUNNING;
        spin_unlock_irqrestore(&m2m_dev->job_spinlock, flags);
similarity index 98%
rename from drivers/media/video/v4l2-subdev.c
rename to drivers/media/v4l2-core/v4l2-subdev.c
index 9182f81deb5b0177ede5b1d3280c07cc02e82188..dced41c1d993d78f72c20f0ac00592154393b206 100644 (file)
@@ -348,6 +348,12 @@ static long subdev_do_ioctl(struct file *file, unsigned int cmd, void *arg)
                return v4l2_subdev_call(
                        sd, pad, set_selection, subdev_fh, sel);
        }
+
+       case VIDIOC_SUBDEV_G_EDID:
+               return v4l2_subdev_call(sd, pad, get_edid, arg);
+
+       case VIDIOC_SUBDEV_S_EDID:
+               return v4l2_subdev_call(sd, pad, set_edid, arg);
 #endif
        default:
                return v4l2_subdev_call(sd, core, ioctl, cmd, arg);
similarity index 96%
rename from drivers/media/video/videobuf-dvb.c
rename to drivers/media/v4l2-core/videobuf-dvb.c
index 94d83a41381b4b4ac3200cce96da3e471cdbd56b..b7efa4516d367944e9f44c385c725f05280daf60 100644 (file)
@@ -139,9 +139,7 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
                          struct device *device,
                          char *adapter_name,
                          short *adapter_nr,
-                         int mfe_shared,
-                         int (*fe_ioctl_override)(struct dvb_frontend *,
-                                       unsigned int, void *, unsigned int))
+                         int mfe_shared)
 {
        int result;
 
@@ -156,7 +154,6 @@ static int videobuf_dvb_register_adapter(struct videobuf_dvb_frontends *fe,
        }
        fe->adapter.priv = adapter_priv;
        fe->adapter.mfe_shared = mfe_shared;
-       fe->adapter.fe_ioctl_override = fe_ioctl_override;
 
        return result;
 }
@@ -257,9 +254,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
                          void *adapter_priv,
                          struct device *device,
                          short *adapter_nr,
-                         int mfe_shared,
-                         int (*fe_ioctl_override)(struct dvb_frontend *,
-                                       unsigned int, void *, unsigned int))
+                         int mfe_shared)
 {
        struct list_head *list, *q;
        struct videobuf_dvb_frontend *fe;
@@ -273,7 +268,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
 
        /* Bring up the adapter */
        res = videobuf_dvb_register_adapter(f, module, adapter_priv, device,
-               fe->dvb.name, adapter_nr, mfe_shared, fe_ioctl_override);
+               fe->dvb.name, adapter_nr, mfe_shared);
        if (res < 0) {
                printk(KERN_WARNING "videobuf_dvb_register_adapter failed (errno = %d)\n", res);
                return res;
similarity index 97%
rename from drivers/media/video/videobuf2-core.c
rename to drivers/media/v4l2-core/videobuf2-core.c
index 268c7dd4f8231ebc2f3ca033bfea4bbc689f07f7..432df119af278dd953a492fece76552a4c8d3e86 100644 (file)
@@ -276,6 +276,9 @@ static void __vb2_queue_free(struct vb2_queue *q, unsigned int buffers)
  */
 static int __verify_planes_array(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
+       if (!V4L2_TYPE_IS_MULTIPLANAR(b->type))
+               return 0;
+
        /* Is memory for copying plane information present? */
        if (NULL == b->m.planes) {
                dprintk(1, "Multi-planar buffer passed but "
@@ -331,10 +334,9 @@ static bool __buffers_in_use(struct vb2_queue *q)
  * __fill_v4l2_buffer() - fill in a struct v4l2_buffer with information to be
  * returned to userspace
  */
-static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
+static void __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 {
        struct vb2_queue *q = vb->vb2_queue;
-       int ret;
 
        /* Copy back data such as timestamp, flags, etc. */
        memcpy(b, &vb->v4l2_buf, offsetof(struct v4l2_buffer, m));
@@ -342,14 +344,11 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
        b->reserved = vb->v4l2_buf.reserved;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(q->type)) {
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /*
                 * Fill in plane-related data if userspace provided an array
-                * for it. The memory and size is verified above.
+                * for it. The caller has already verified memory and size.
                 */
+               b->length = vb->num_planes;
                memcpy(b->m.planes, vb->v4l2_planes,
                        b->length * sizeof(struct v4l2_plane));
        } else {
@@ -391,8 +390,6 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 
        if (__buffer_in_use(q, vb))
                b->flags |= V4L2_BUF_FLAG_MAPPED;
-
-       return 0;
 }
 
 /**
@@ -411,6 +408,7 @@ static int __fill_v4l2_buffer(struct vb2_buffer *vb, struct v4l2_buffer *b)
 int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
 {
        struct vb2_buffer *vb;
+       int ret;
 
        if (b->type != q->type) {
                dprintk(1, "querybuf: wrong buffer type\n");
@@ -422,8 +420,10 @@ int vb2_querybuf(struct vb2_queue *q, struct v4l2_buffer *b)
                return -EINVAL;
        }
        vb = q->bufs[b->index];
-
-       return __fill_v4l2_buffer(vb, b);
+       ret = __verify_planes_array(vb, b);
+       if (!ret)
+               __fill_v4l2_buffer(vb, b);
+       return ret;
 }
 EXPORT_SYMBOL(vb2_querybuf);
 
@@ -813,24 +813,16 @@ void vb2_buffer_done(struct vb2_buffer *vb, enum vb2_buffer_state state)
 EXPORT_SYMBOL_GPL(vb2_buffer_done);
 
 /**
- * __fill_vb2_buffer() - fill a vb2_buffer with information provided in
- * a v4l2_buffer by the userspace
+ * __fill_vb2_buffer() - fill a vb2_buffer with information provided in a
+ * v4l2_buffer by the userspace. The caller has already verified that struct
+ * v4l2_buffer has a valid number of planes.
  */
-static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
+static void __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
                                struct v4l2_plane *v4l2_planes)
 {
        unsigned int plane;
-       int ret;
 
        if (V4L2_TYPE_IS_MULTIPLANAR(b->type)) {
-               /*
-                * Verify that the userspace gave us a valid array for
-                * plane information.
-                */
-               ret = __verify_planes_array(vb, b);
-               if (ret)
-                       return ret;
-
                /* Fill in driver-provided information for OUTPUT types */
                if (V4L2_TYPE_IS_OUTPUT(b->type)) {
                        /*
@@ -872,8 +864,6 @@ static int __fill_vb2_buffer(struct vb2_buffer *vb, const struct v4l2_buffer *b,
        vb->v4l2_buf.field = b->field;
        vb->v4l2_buf.timestamp = b->timestamp;
        vb->v4l2_buf.flags = b->flags & ~V4L2_BUFFER_STATE_FLAGS;
-
-       return 0;
 }
 
 /**
@@ -888,10 +878,8 @@ static int __qbuf_userptr(struct vb2_buffer *vb, const struct v4l2_buffer *b)
        int ret;
        int write = !V4L2_TYPE_IS_OUTPUT(q->type);
 
-       /* Verify and copy relevant information provided by the userspace */
-       ret = __fill_vb2_buffer(vb, b, planes);
-       if (ret)
-               return ret;
+       /* Copy relevant information provided by the userspace */
+       __fill_vb2_buffer(vb, b, planes);
 
        for (plane = 0; plane < vb->num_planes; ++plane) {
                /* Skip the plane if already verified */
@@ -966,7 +954,8 @@ err:
  */
 static int __qbuf_mmap(struct vb2_buffer *vb, const struct v4l2_buffer *b)
 {
-       return __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       __fill_vb2_buffer(vb, b, vb->v4l2_planes);
+       return 0;
 }
 
 /**
@@ -1059,7 +1048,9 @@ int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b)
                dprintk(1, "%s(): invalid buffer state %d\n", __func__, vb->state);
                return -EINVAL;
        }
-
+       ret = __verify_planes_array(vb, b);
+       if (ret < 0)
+               return ret;
        ret = __buf_prepare(vb, b);
        if (ret < 0)
                return ret;
@@ -1147,6 +1138,9 @@ int vb2_qbuf(struct vb2_queue *q, struct v4l2_buffer *b)
                ret = -EINVAL;
                goto unlock;
        }
+       ret = __verify_planes_array(vb, b);
+       if (ret)
+               goto unlock;
 
        switch (vb->state) {
        case VB2_BUF_STATE_DEQUEUED:
@@ -1243,8 +1237,10 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
                 * the locks or return an error if one occurred.
                 */
                call_qop(q, wait_finish, q);
-               if (ret)
+               if (ret) {
+                       dprintk(1, "Sleep was interrupted\n");
                        return ret;
+               }
        }
        return 0;
 }
@@ -1255,7 +1251,7 @@ static int __vb2_wait_for_done_vb(struct vb2_queue *q, int nonblocking)
  * Will sleep if required for nonblocking == false.
  */
 static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
-                               int nonblocking)
+                               struct v4l2_buffer *b, int nonblocking)
 {
        unsigned long flags;
        int ret;
@@ -1273,10 +1269,16 @@ static int __vb2_get_done_vb(struct vb2_queue *q, struct vb2_buffer **vb,
         */
        spin_lock_irqsave(&q->done_lock, flags);
        *vb = list_first_entry(&q->done_list, struct vb2_buffer, done_entry);
-       list_del(&(*vb)->done_entry);
+       /*
+        * Only remove the buffer from done_list if v4l2_buffer can handle all
+        * the planes.
+        */
+       ret = __verify_planes_array(*vb, b);
+       if (!ret)
+               list_del(&(*vb)->done_entry);
        spin_unlock_irqrestore(&q->done_lock, flags);
 
-       return 0;
+       return ret;
 }
 
 /**
@@ -1335,12 +1337,9 @@ int vb2_dqbuf(struct vb2_queue *q, struct v4l2_buffer *b, bool nonblocking)
                dprintk(1, "dqbuf: invalid buffer type\n");
                return -EINVAL;
        }
-
-       ret = __vb2_get_done_vb(q, &vb, nonblocking);
-       if (ret < 0) {
-               dprintk(1, "dqbuf: error getting next done buffer\n");
+       ret = __vb2_get_done_vb(q, &vb, b, nonblocking);
+       if (ret < 0)
                return ret;
-       }
 
        ret = call_qop(q, buf_finish, vb);
        if (ret) {
@@ -1738,14 +1737,17 @@ EXPORT_SYMBOL_GPL(vb2_poll);
  */
 int vb2_queue_init(struct vb2_queue *q)
 {
-       BUG_ON(!q);
-       BUG_ON(!q->ops);
-       BUG_ON(!q->mem_ops);
-       BUG_ON(!q->type);
-       BUG_ON(!q->io_modes);
-
-       BUG_ON(!q->ops->queue_setup);
-       BUG_ON(!q->ops->buf_queue);
+       /*
+        * Sanity check
+        */
+       if (WARN_ON(!q)                   ||
+           WARN_ON(!q->ops)              ||
+           WARN_ON(!q->mem_ops)          ||
+           WARN_ON(!q->type)             ||
+           WARN_ON(!q->io_modes)         ||
+           WARN_ON(!q->ops->queue_setup) ||
+           WARN_ON(!q->ops->buf_queue))
+               return -EINVAL;
 
        INIT_LIST_HEAD(&q->queued_list);
        INIT_LIST_HEAD(&q->done_list);
@@ -2270,19 +2272,18 @@ ssize_t vb2_fop_write(struct file *file, char __user *buf,
 {
        struct video_device *vdev = video_devdata(file);
        struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-       bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && lock;
        int err = -EBUSY;
 
-       if (must_lock && mutex_lock_interruptible(lock))
+       if (lock && mutex_lock_interruptible(lock))
                return -ERESTARTSYS;
        if (vb2_queue_is_busy(vdev, file))
                goto exit;
        err = vb2_write(vdev->queue, buf, count, ppos,
                       file->f_flags & O_NONBLOCK);
-       if (err >= 0)
+       if (vdev->queue->fileio)
                vdev->queue->owner = file->private_data;
 exit:
-       if (must_lock)
+       if (lock)
                mutex_unlock(lock);
        return err;
 }
@@ -2293,19 +2294,18 @@ ssize_t vb2_fop_read(struct file *file, char __user *buf,
 {
        struct video_device *vdev = video_devdata(file);
        struct mutex *lock = vdev->queue->lock ? vdev->queue->lock : vdev->lock;
-       bool must_lock = !test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags) && vdev->lock;
        int err = -EBUSY;
 
-       if (must_lock && mutex_lock_interruptible(lock))
+       if (lock && mutex_lock_interruptible(lock))
                return -ERESTARTSYS;
        if (vb2_queue_is_busy(vdev, file))
                goto exit;
        err = vb2_read(vdev->queue, buf, count, ppos,
                       file->f_flags & O_NONBLOCK);
-       if (err >= 0)
+       if (vdev->queue->fileio)
                vdev->queue->owner = file->private_data;
 exit:
-       if (must_lock)
+       if (lock)
                mutex_unlock(lock);
        return err;
 }
@@ -2319,11 +2319,6 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
        unsigned long req_events = poll_requested_events(wait);
        unsigned res;
        void *fileio;
-       /* Yuck. We really need to get rid of this flag asap. If it is
-          set, then the core took the serialization lock before calling
-          poll(). This is being phased out, but for now we have to handle
-          this case. */
-       bool locked = test_bit(V4L2_FL_LOCK_ALL_FOPS, &vdev->flags);
        bool must_lock = false;
 
        /* Try to be smart: only lock if polling might start fileio,
@@ -2339,9 +2334,9 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
 
        /* If locking is needed, but this helper doesn't know how, then you
           shouldn't be using this helper but you should write your own. */
-       WARN_ON(must_lock && !locked && !lock);
+       WARN_ON(must_lock && !lock);
 
-       if (must_lock && !locked && lock && mutex_lock_interruptible(lock))
+       if (must_lock && lock && mutex_lock_interruptible(lock))
                return POLLERR;
 
        fileio = q->fileio;
@@ -2351,7 +2346,7 @@ unsigned int vb2_fop_poll(struct file *file, poll_table *wait)
        /* If fileio was started, then we have a new queue owner. */
        if (must_lock && !fileio && q->fileio)
                q->owner = file->private_data;
-       if (must_lock && !locked && lock)
+       if (must_lock && lock)
                mutex_unlock(lock);
        return res;
 }
similarity index 99%
rename from drivers/media/video/videobuf2-vmalloc.c
rename to drivers/media/v4l2-core/videobuf2-vmalloc.c
index 6b5ca6c70a46076b42cebdcee55613b02ebd2f0f..94efa04d8d55f3e4af400f0910cf791dbf9faf02 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/vmalloc.h>
 
 #include <media/videobuf2-core.h>
+#include <media/videobuf2-vmalloc.h>
 #include <media/videobuf2-memops.h>
 
 struct vb2_vmalloc_buf {
diff --git a/drivers/media/video/Kconfig b/drivers/media/video/Kconfig
deleted file mode 100644 (file)
index c128fac..0000000
+++ /dev/null
@@ -1,1263 +0,0 @@
-#
-# Generic video config states
-#
-
-config VIDEO_V4L2
-       tristate
-       depends on VIDEO_DEV && VIDEO_V4L2_COMMON
-       default y
-
-config VIDEOBUF_GEN
-       tristate
-
-config VIDEOBUF_DMA_SG
-       depends on HAS_DMA
-       select VIDEOBUF_GEN
-       tristate
-
-config VIDEOBUF_VMALLOC
-       select VIDEOBUF_GEN
-       tristate
-
-config VIDEOBUF_DMA_CONTIG
-       depends on HAS_DMA
-       select VIDEOBUF_GEN
-       tristate
-
-config VIDEOBUF_DVB
-       tristate
-       select VIDEOBUF_GEN
-
-config VIDEO_BTCX
-       depends on PCI
-       tristate
-
-config VIDEO_TVEEPROM
-       tristate
-       depends on I2C
-
-config VIDEO_TUNER
-       tristate
-       depends on MEDIA_TUNER
-
-config V4L2_MEM2MEM_DEV
-       tristate
-       depends on VIDEOBUF2_CORE
-
-config VIDEOBUF2_CORE
-       tristate
-
-config VIDEOBUF2_MEMOPS
-       tristate
-
-config VIDEOBUF2_DMA_CONTIG
-       select VIDEOBUF2_CORE
-       select VIDEOBUF2_MEMOPS
-       tristate
-
-config VIDEOBUF2_VMALLOC
-       select VIDEOBUF2_CORE
-       select VIDEOBUF2_MEMOPS
-       tristate
-
-
-config VIDEOBUF2_DMA_SG
-       #depends on HAS_DMA
-       select VIDEOBUF2_CORE
-       select VIDEOBUF2_MEMOPS
-       tristate
-#
-# Multimedia Video device configuration
-#
-
-menuconfig VIDEO_CAPTURE_DRIVERS
-       bool "Video capture adapters"
-       depends on VIDEO_V4L2
-       depends on MEDIA_CAMERA_SUPPORT || MEDIA_ANALOG_TV_SUPPORT
-       default y
-       ---help---
-         Say Y here to enable selecting the video adapters for
-         webcams, analog TV, and hybrid analog/digital TV.
-         Some of those devices also supports FM radio.
-
-if VIDEO_CAPTURE_DRIVERS && VIDEO_V4L2
-
-config VIDEO_ADV_DEBUG
-       bool "Enable advanced debug functionality"
-       default n
-       ---help---
-         Say Y here to enable advanced debugging functionality on some
-         V4L devices.
-         In doubt, say N.
-
-config VIDEO_FIXED_MINOR_RANGES
-       bool "Enable old-style fixed minor ranges for video devices"
-       default n
-       ---help---
-         Say Y here to enable the old-style fixed-range minor assignments.
-         Only useful if you rely on the old behavior and use mknod instead of udev.
-
-         When in doubt, say N.
-
-config VIDEO_HELPER_CHIPS_AUTO
-       bool "Autoselect pertinent encoders/decoders and other helper chips"
-       default y if !EXPERT
-       ---help---
-         Most video cards may require additional modules to encode or
-         decode audio/video standards. This option will autoselect
-         all pertinent modules to each selected video module.
-
-         Unselect this only if you know exactly what you are doing, since
-         it may break support on some boards.
-
-         In doubt, say Y.
-
-config VIDEO_IR_I2C
-       tristate "I2C module for IR" if !VIDEO_HELPER_CHIPS_AUTO
-       depends on I2C && RC_CORE
-       default y
-       ---help---
-         Most boards have an IR chip directly connected via GPIO. However,
-         some video boards have the IR connected via I2C bus.
-
-         If your board doesn't have an I2C IR chip, you may disable this
-         option.
-
-         In doubt, say Y.
-
-#
-# Encoder / Decoder module configuration
-#
-
-menu "Encoders, decoders, sensors and other helper chips"
-       visible if !VIDEO_HELPER_CHIPS_AUTO
-
-comment "Audio decoders, processors and mixers"
-
-config VIDEO_TVAUDIO
-       tristate "Simple audio decoder chips"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for several audio decoder chips found on some bt8xx boards:
-         Philips: tda9840, tda9873h, tda9874h/a, tda9850, tda985x, tea6300,
-                  tea6320, tea6420, tda8425, ta8874z.
-         Microchip: pic16c54 based design on ProVideo PV951 board.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tvaudio.
-
-config VIDEO_TDA7432
-       tristate "Philips TDA7432 audio processor"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for tda7432 audio decoder chip found on some bt8xx boards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tda7432.
-
-config VIDEO_TDA9840
-       tristate "Philips TDA9840 audio processor"
-       depends on I2C
-       ---help---
-         Support for tda9840 audio decoder chip found on some Zoran boards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tda9840.
-
-config VIDEO_TEA6415C
-       tristate "Philips TEA6415C audio processor"
-       depends on I2C
-       ---help---
-         Support for tea6415c audio decoder chip found on some bt8xx boards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tea6415c.
-
-config VIDEO_TEA6420
-       tristate "Philips TEA6420 audio processor"
-       depends on I2C
-       ---help---
-         Support for tea6420 audio decoder chip found on some bt8xx boards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tea6420.
-
-config VIDEO_MSP3400
-       tristate "Micronas MSP34xx audio decoders"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Micronas MSP34xx series of audio decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called msp3400.
-
-config VIDEO_CS5345
-       tristate "Cirrus Logic CS5345 audio ADC"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Cirrus Logic CS5345 24-bit, 192 kHz
-         stereo A/D converter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cs5345.
-
-config VIDEO_CS53L32A
-       tristate "Cirrus Logic CS53L32A audio ADC"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Cirrus Logic CS53L32A low voltage
-         stereo A/D converter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cs53l32a.
-
-config VIDEO_TLV320AIC23B
-       tristate "Texas Instruments TLV320AIC23B audio codec"
-       depends on VIDEO_V4L2 && I2C && EXPERIMENTAL
-       ---help---
-         Support for the Texas Instruments TLV320AIC23B audio codec.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tlv320aic23b.
-
-config VIDEO_WM8775
-       tristate "Wolfson Microelectronics WM8775 audio ADC with input mixer"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Wolfson Microelectronics WM8775 high
-         performance stereo A/D Converter with a 4 channel input mixer.
-
-         To compile this driver as a module, choose M here: the
-         module will be called wm8775.
-
-config VIDEO_WM8739
-       tristate "Wolfson Microelectronics WM8739 stereo audio ADC"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Wolfson Microelectronics WM8739
-         stereo A/D Converter.
-
-         To compile this driver as a module, choose M here: the
-         module will be called wm8739.
-
-config VIDEO_VP27SMPX
-       tristate "Panasonic VP27s internal MPX"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the internal MPX of the Panasonic VP27s tuner.
-
-         To compile this driver as a module, choose M here: the
-         module will be called vp27smpx.
-
-comment "RDS decoders"
-
-config VIDEO_SAA6588
-       tristate "SAA6588 Radio Chip RDS decoder support"
-       depends on VIDEO_V4L2 && I2C
-
-       help
-         Support for this Radio Data System (RDS) decoder. This allows
-         seeing radio station identification transmitted using this
-         standard.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa6588.
-
-comment "Video decoders"
-
-config VIDEO_ADV7180
-       tristate "Analog Devices ADV7180 decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Analog Devices ADV7180 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7180.
-
-config VIDEO_ADV7183
-       tristate "Analog Devices ADV7183 decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         V4l2 subdevice driver for the Analog Devices
-         ADV7183 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7183.
-
-config VIDEO_BT819
-       tristate "BT819A VideoStream decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for BT819A video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bt819.
-
-config VIDEO_BT856
-       tristate "BT856 VideoStream decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for BT856 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bt856.
-
-config VIDEO_BT866
-       tristate "BT866 VideoStream decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for BT866 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bt866.
-
-config VIDEO_KS0127
-       tristate "KS0127 video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for KS0127 video decoder.
-
-         This chip is used on AverMedia AVS6EYES Zoran-based MJPEG
-         cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called ks0127.
-
-config VIDEO_SAA7110
-       tristate "Philips SAA7110 video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7110 video decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7110.
-
-config VIDEO_SAA711X
-       tristate "Philips SAA7111/3/4/5 video decoders"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7111/3/4/5 video decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7115.
-
-config VIDEO_SAA7191
-       tristate "Philips SAA7191 video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7191 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7191.
-
-config VIDEO_TVP514X
-       tristate "Texas Instruments TVP514x video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the TI TVP5146/47
-         decoder. It is currently working with the TI OMAP3 camera
-         controller.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tvp514x.
-
-config VIDEO_TVP5150
-       tristate "Texas Instruments TVP5150 video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Texas Instruments TVP5150 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tvp5150.
-
-config VIDEO_TVP7002
-       tristate "Texas Instruments TVP7002 video decoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Texas Instruments TVP7002 video decoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called tvp7002.
-
-config VIDEO_VPX3220
-       tristate "vpx3220a, vpx3216b & vpx3214c video decoders"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for VPX322x video decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called vpx3220.
-
-comment "Video and audio decoders"
-
-config VIDEO_SAA717X
-       tristate "Philips SAA7171/3/4 audio/video decoders"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7171/3/4 audio/video decoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa717x.
-
-source "drivers/media/video/cx25840/Kconfig"
-
-comment "MPEG video encoders"
-
-config VIDEO_CX2341X
-       tristate "Conexant CX2341x MPEG encoders"
-       depends on VIDEO_V4L2 && VIDEO_V4L2_COMMON
-       ---help---
-         Support for the Conexant CX23416 MPEG encoders
-         and CX23415 MPEG encoder/decoders.
-
-         This module currently supports the encoding functions only.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx2341x.
-
-comment "Video encoders"
-
-config VIDEO_SAA7127
-       tristate "Philips SAA7127/9 digital video encoders"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7127/9 digital video encoders.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7127.
-
-config VIDEO_SAA7185
-       tristate "Philips SAA7185 video encoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Philips SAA7185 video encoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called saa7185.
-
-config VIDEO_ADV7170
-       tristate "Analog Devices ADV7170 video encoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Analog Devices ADV7170 video encoder driver
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7170.
-
-config VIDEO_ADV7175
-       tristate "Analog Devices ADV7175 video encoder"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the Analog Devices ADV7175 video encoder driver
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7175.
-
-config VIDEO_ADV7343
-       tristate "ADV7343 video encoder"
-       depends on I2C
-       help
-         Support for Analog Devices I2C bus based ADV7343 encoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7343.
-
-config VIDEO_ADV7393
-       tristate "ADV7393 video encoder"
-       depends on I2C
-       help
-         Support for Analog Devices I2C bus based ADV7393 encoder.
-
-         To compile this driver as a module, choose M here: the
-         module will be called adv7393.
-
-config VIDEO_AK881X
-       tristate "AK8813/AK8814 video encoders"
-       depends on I2C
-       help
-         Video output driver for AKM AK8813 and AK8814 TV encoders
-
-comment "Camera sensor devices"
-
-config VIDEO_APTINA_PLL
-       tristate
-
-config VIDEO_SMIAPP_PLL
-       tristate
-
-config VIDEO_OV7670
-       tristate "OmniVision OV7670 sensor support"
-       depends on I2C && VIDEO_V4L2
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the OmniVision
-         OV7670 VGA camera.  It currently only works with the M88ALP01
-         controller.
-
-config VIDEO_VS6624
-       tristate "ST VS6624 sensor support"
-       depends on VIDEO_V4L2 && I2C
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the ST VS6624
-         camera.
-
-         To compile this driver as a module, choose M here: the
-         module will be called vs6624.
-
-config VIDEO_MT9M032
-       tristate "MT9M032 camera sensor support"
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       depends on MEDIA_CAMERA_SUPPORT
-       select VIDEO_APTINA_PLL
-       ---help---
-         This driver supports MT9M032 camera sensors from Aptina, monochrome
-         models only.
-
-config VIDEO_MT9P031
-       tristate "Aptina MT9P031 support"
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       depends on MEDIA_CAMERA_SUPPORT
-       select VIDEO_APTINA_PLL
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the Aptina
-         (Micron) mt9p031 5 Mpixel camera.
-
-config VIDEO_MT9T001
-       tristate "Aptina MT9T001 support"
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the Aptina
-         (Micron) mt0t001 3 Mpixel camera.
-
-config VIDEO_MT9V011
-       tristate "Micron mt9v011 sensor support"
-       depends on I2C && VIDEO_V4L2
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the Micron
-         mt0v011 1.3 Mpixel camera.  It currently only works with the
-         em28xx driver.
-
-config VIDEO_MT9V032
-       tristate "Micron MT9V032 sensor support"
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a Video4Linux2 sensor-level driver for the Micron
-         MT9V032 752x480 CMOS sensor.
-
-config VIDEO_TCM825X
-       tristate "TCM825x camera sensor support"
-       depends on I2C && VIDEO_V4L2
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a driver for the Toshiba TCM825x VGA camera sensor.
-         It is used for example in Nokia N800.
-
-config VIDEO_SR030PC30
-       tristate "Siliconfile SR030PC30 sensor support"
-       depends on I2C && VIDEO_V4L2
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This driver supports SR030PC30 VGA camera from Siliconfile
-
-config VIDEO_NOON010PC30
-       tristate "Siliconfile NOON010PC30 sensor support"
-       depends on I2C && VIDEO_V4L2 && EXPERIMENTAL && VIDEO_V4L2_SUBDEV_API
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This driver supports NOON010PC30 CIF camera from Siliconfile
-
-source "drivers/media/video/m5mols/Kconfig"
-
-config VIDEO_S5K6AA
-       tristate "Samsung S5K6AAFX sensor support"
-       depends on MEDIA_CAMERA_SUPPORT
-       depends on I2C && VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
-       ---help---
-         This is a V4L2 sensor-level driver for Samsung S5K6AA(FX) 1.3M
-         camera sensor with an embedded SoC image signal processor.
-
-source "drivers/media/video/smiapp/Kconfig"
-
-comment "Flash devices"
-
-config VIDEO_ADP1653
-       tristate "ADP1653 flash support"
-       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a driver for the ADP1653 flash controller. It is used for
-         example in Nokia N900.
-
-config VIDEO_AS3645A
-       tristate "AS3645A flash driver support"
-       depends on I2C && VIDEO_V4L2 && MEDIA_CONTROLLER
-       depends on MEDIA_CAMERA_SUPPORT
-       ---help---
-         This is a driver for the AS3645A and LM3555 flash controllers. It has
-         build in control for flash, torch and indicator LEDs.
-
-comment "Video improvement chips"
-
-config VIDEO_UPD64031A
-       tristate "NEC Electronics uPD64031A Ghost Reduction"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the NEC Electronics uPD64031A Ghost Reduction
-         video chip. It is most often found in NTSC TV cards made for
-         Japan and is used to reduce the 'ghosting' effect that can
-         be present in analog TV broadcasts.
-
-         To compile this driver as a module, choose M here: the
-         module will be called upd64031a.
-
-config VIDEO_UPD64083
-       tristate "NEC Electronics uPD64083 3-Dimensional Y/C separation"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-         Support for the NEC Electronics uPD64083 3-Dimensional Y/C
-         separation video chip. It is used to improve the quality of
-         the colors of a composite signal.
-
-         To compile this driver as a module, choose M here: the
-         module will be called upd64083.
-
-comment "Miscelaneous helper chips"
-
-config VIDEO_THS7303
-       tristate "THS7303 Video Amplifier"
-       depends on I2C
-       help
-         Support for TI THS7303 video amplifier
-
-         To compile this driver as a module, choose M here: the
-         module will be called ths7303.
-
-config VIDEO_M52790
-       tristate "Mitsubishi M52790 A/V switch"
-       depends on VIDEO_V4L2 && I2C
-       ---help---
-        Support for the Mitsubishi M52790 A/V switch.
-
-        To compile this driver as a module, choose M here: the
-        module will be called m52790.
-
-endmenu # encoder / decoder chips
-
-config VIDEO_VIVI
-       tristate "Virtual Video Driver"
-       depends on VIDEO_DEV && VIDEO_V4L2 && !SPARC32 && !SPARC64
-       depends on FRAMEBUFFER_CONSOLE || STI_CONSOLE
-       select FONT_8x16
-       select VIDEOBUF2_VMALLOC
-       default n
-       ---help---
-         Enables a virtual video driver. This device shows a color bar
-         and a timestamp, as a real device would generate by using V4L2
-         api.
-         Say Y here if you want to test video apps or debug V4L devices.
-         In doubt, say N.
-
-#
-# USB Multimedia device configuration
-#
-
-menuconfig V4L_USB_DRIVERS
-       bool "V4L USB devices"
-       depends on USB
-       default y
-
-if V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
-
-       comment "Webcam devices"
-
-source "drivers/media/video/uvc/Kconfig"
-
-source "drivers/media/video/gspca/Kconfig"
-
-source "drivers/media/video/pwc/Kconfig"
-
-source "drivers/media/video/cpia2/Kconfig"
-
-config USB_ZR364XX
-       tristate "USB ZR364XX Camera support"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_GEN
-       select VIDEOBUF_VMALLOC
-       ---help---
-         Say Y here if you want to connect this type of camera to your
-         computer's USB port.
-         See <file:Documentation/video4linux/zr364xx.txt> for more info
-         and list of supported cameras.
-
-         To compile this driver as a module, choose M here: the
-         module will be called zr364xx.
-
-config USB_STKWEBCAM
-       tristate "USB Syntek DC1125 Camera support"
-       depends on VIDEO_V4L2 && EXPERIMENTAL
-       ---help---
-         Say Y here if you want to use this type of camera.
-         Supported devices are typically found in some Asus laptops,
-         with USB id 174f:a311 and 05e1:0501. Other Syntek cameras
-         may be supported by the stk11xx driver, from which this is
-         derived, see <http://sourceforge.net/projects/syntekdriver/>
-
-         To compile this driver as a module, choose M here: the
-         module will be called stkwebcam.
-
-config USB_S2255
-       tristate "USB Sensoray 2255 video capture device"
-       depends on VIDEO_V4L2
-       select VIDEOBUF_VMALLOC
-       default n
-       help
-         Say Y here if you want support for the Sensoray 2255 USB device.
-         This driver can be compiled as a module, called s2255drv.
-
-source "drivers/media/video/sn9c102/Kconfig"
-
-endif # V4L_USB_DRIVERS && MEDIA_CAMERA_SUPPORT
-
-if V4L_USB_DRIVERS
-
-       comment "Webcam and/or TV USB devices"
-
-source "drivers/media/video/em28xx/Kconfig"
-
-endif
-
-if V4L_USB_DRIVERS && MEDIA_ANALOG_TV_SUPPORT
-
-       comment "TV USB devices"
-
-source "drivers/media/video/au0828/Kconfig"
-
-source "drivers/media/video/pvrusb2/Kconfig"
-
-source "drivers/media/video/hdpvr/Kconfig"
-
-source "drivers/media/video/tlg2300/Kconfig"
-
-source "drivers/media/video/cx231xx/Kconfig"
-
-source "drivers/media/video/tm6000/Kconfig"
-
-source "drivers/media/video/usbvision/Kconfig"
-
-endif # V4L_USB_DRIVERS
-
-#
-# PCI drivers configuration - No devices here are for webcams
-#
-
-menuconfig V4L_PCI_DRIVERS
-       bool "V4L PCI(e) devices"
-       depends on PCI
-       depends on MEDIA_ANALOG_TV_SUPPORT
-       default y
-       ---help---
-         Say Y here to enable support for these PCI(e) drivers.
-
-if V4L_PCI_DRIVERS
-
-source "drivers/media/video/bt8xx/Kconfig"
-
-source "drivers/media/video/cx18/Kconfig"
-
-source "drivers/media/video/cx23885/Kconfig"
-
-source "drivers/media/video/cx25821/Kconfig"
-
-source "drivers/media/video/cx88/Kconfig"
-
-config VIDEO_HEXIUM_GEMINI
-       tristate "Hexium Gemini frame grabber"
-       depends on PCI && VIDEO_V4L2 && I2C
-       select VIDEO_SAA7146_VV
-       ---help---
-         This is a video4linux driver for the Hexium Gemini frame
-         grabber card by Hexium. Please note that the Gemini Dual
-         card is *not* fully supported.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hexium_gemini.
-
-config VIDEO_HEXIUM_ORION
-       tristate "Hexium HV-PCI6 and Orion frame grabber"
-       depends on PCI && VIDEO_V4L2 && I2C
-       select VIDEO_SAA7146_VV
-       ---help---
-         This is a video4linux driver for the Hexium HV-PCI6 and
-         Orion frame grabber cards by Hexium.
-
-         To compile this driver as a module, choose M here: the
-         module will be called hexium_orion.
-
-source "drivers/media/video/ivtv/Kconfig"
-
-config VIDEO_MEYE
-       tristate "Sony Vaio Picturebook Motion Eye Video For Linux"
-       depends on PCI && SONY_LAPTOP && VIDEO_V4L2
-       ---help---
-         This is the video4linux driver for the Motion Eye camera found
-         in the Vaio Picturebook laptops. Please read the material in
-         <file:Documentation/video4linux/meye.txt> for more information.
-
-         If you say Y or M here, you need to say Y or M to "Sony Laptop
-         Extras" in the misc device section.
-
-         To compile this driver as a module, choose M here: the
-         module will be called meye.
-
-config VIDEO_MXB
-       tristate "Siemens-Nixdorf 'Multimedia eXtension Board'"
-       depends on PCI && VIDEO_V4L2 && I2C
-       select VIDEO_SAA7146_VV
-       select VIDEO_TUNER
-       select VIDEO_SAA711X if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TDA9840 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TEA6415C if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TEA6420 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         This is a video4linux driver for the 'Multimedia eXtension Board'
-         TV card by Siemens-Nixdorf.
-
-         To compile this driver as a module, choose M here: the
-         module will be called mxb.
-
-source "drivers/media/video/saa7134/Kconfig"
-
-source "drivers/media/video/saa7164/Kconfig"
-
-source "drivers/media/video/zoran/Kconfig"
-
-config STA2X11_VIP
-       tristate "STA2X11 VIP Video For Linux"
-       depends on STA2X11
-       select VIDEO_ADV7180 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEOBUF_DMA_CONTIG
-       depends on PCI && VIDEO_V4L2 && VIRT_TO_BUS
-       help
-         Say Y for support for STA2X11 VIP (Video Input Port) capture
-         device.
-
-         To compile this driver as a module, choose M here: the
-         module will be called sta2x11_vip.
-
-endif # V4L_PCI_DRIVERS
-
-#
-# ISA & parallel port drivers configuration
-#      All devices here are webcam or grabber devices
-#
-
-menuconfig V4L_ISA_PARPORT_DRIVERS
-       bool "V4L ISA and parallel port devices"
-       depends on ISA || PARPORT
-       depends on MEDIA_CAMERA_SUPPORT
-       default n
-       ---help---
-         Say Y here to enable support for these ISA and parallel port drivers.
-
-if V4L_ISA_PARPORT_DRIVERS
-
-config VIDEO_BWQCAM
-       tristate "Quickcam BW Video For Linux"
-       depends on PARPORT && VIDEO_V4L2
-       help
-         Say Y have if you the black and white version of the QuickCam
-         camera. See the next option for the color version.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bw-qcam.
-
-config VIDEO_CQCAM
-       tristate "QuickCam Colour Video For Linux"
-       depends on PARPORT && VIDEO_V4L2
-       help
-         This is the video4linux driver for the colour version of the
-         Connectix QuickCam.  If you have one of these cameras, say Y here,
-         otherwise say N.  This driver does not work with the original
-         monochrome QuickCam, QuickCam VC or QuickClip.  It is also available
-         as a module (c-qcam).
-         Read <file:Documentation/video4linux/CQcam.txt> for more information.
-
-config VIDEO_PMS
-       tristate "Mediavision Pro Movie Studio Video For Linux"
-       depends on ISA && VIDEO_V4L2
-       help
-         Say Y if you have the ISA Mediavision Pro Movie Studio
-         capture card.
-
-         To compile this driver as a module, choose M here: the
-         module will be called pms.
-
-config VIDEO_W9966
-       tristate "W9966CF Webcam (FlyCam Supra and others) Video For Linux"
-       depends on PARPORT_1284 && PARPORT && VIDEO_V4L2
-       help
-         Video4linux driver for Winbond's w9966 based Webcams.
-         Currently tested with the LifeView FlyCam Supra.
-         If you have one of these cameras, say Y here
-         otherwise say N.
-         This driver is also available as a module (w9966).
-
-         Check out <file:Documentation/video4linux/w9966.txt> for more
-         information.
-
-endif # V4L_ISA_PARPORT_DRIVERS
-
-#
-# Platform drivers
-#      All drivers here are currently for webcam support
-
-menuconfig V4L_PLATFORM_DRIVERS
-       bool "V4L platform devices"
-       depends on MEDIA_CAMERA_SUPPORT
-       default n
-       ---help---
-         Say Y here to enable support for platform-specific V4L drivers.
-
-if V4L_PLATFORM_DRIVERS
-
-source "drivers/media/video/marvell-ccic/Kconfig"
-
-config VIDEO_VIA_CAMERA
-       tristate "VIAFB camera controller support"
-       depends on FB_VIA
-       select VIDEOBUF_DMA_SG
-       select VIDEO_OV7670
-       help
-          Driver support for the integrated camera controller in VIA
-          Chrome9 chipsets.  Currently only tested on OLPC xo-1.5 systems
-          with ov7670 sensors.
-
-#
-# Platform multimedia device configuration
-#
-
-source "drivers/media/video/davinci/Kconfig"
-
-source "drivers/media/video/omap/Kconfig"
-
-source "drivers/media/video/blackfin/Kconfig"
-
-config VIDEO_SH_VOU
-       tristate "SuperH VOU video output driver"
-       depends on VIDEO_DEV && ARCH_SHMOBILE
-       select VIDEOBUF_DMA_CONTIG
-       help
-         Support for the Video Output Unit (VOU) on SuperH SoCs.
-
-config VIDEO_VIU
-       tristate "Freescale VIU Video Driver"
-       depends on VIDEO_V4L2 && PPC_MPC512x
-       select VIDEOBUF_DMA_CONTIG
-       default y
-       ---help---
-         Support for Freescale VIU video driver. This device captures
-         video data, or overlays video on DIU frame buffer.
-
-         Say Y here if you want to enable VIU device on MPC5121e Rev2+.
-         In doubt, say N.
-
-config VIDEO_TIMBERDALE
-       tristate "Support for timberdale Video In/LogiWIN"
-       depends on VIDEO_V4L2 && I2C && DMADEVICES
-       select DMA_ENGINE
-       select TIMB_DMA
-       select VIDEO_ADV7180
-       select VIDEOBUF_DMA_CONTIG
-       ---help---
-         Add support for the Video In peripherial of the timberdale FPGA.
-
-config VIDEO_VINO
-       tristate "SGI Vino Video For Linux"
-       depends on I2C && SGI_IP22 && VIDEO_V4L2
-       select VIDEO_SAA7191 if VIDEO_HELPER_CHIPS_AUTO
-       help
-         Say Y here to build in support for the Vino video input system found
-         on SGI Indy machines.
-
-config VIDEO_M32R_AR
-       tristate "AR devices"
-       depends on M32R && VIDEO_V4L2
-       ---help---
-         This is a video4linux driver for the Renesas AR (Artificial Retina)
-         camera module.
-
-config VIDEO_M32R_AR_M64278
-       tristate "AR device with color module M64278(VGA)"
-       depends on PLAT_M32700UT
-       select VIDEO_M32R_AR
-       ---help---
-         This is a video4linux driver for the Renesas AR (Artificial
-         Retina) with M64278E-800 camera module.
-         This module supports VGA(640x480 pixels) resolutions.
-
-         To compile this driver as a module, choose M here: the
-         module will be called arv.
-
-config VIDEO_OMAP3
-       tristate "OMAP 3 Camera support (EXPERIMENTAL)"
-       depends on OMAP_IOVMM && VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API && ARCH_OMAP3 && EXPERIMENTAL
-       ---help---
-         Driver for an OMAP 3 camera controller.
-
-config VIDEO_OMAP3_DEBUG
-       bool "OMAP 3 Camera debug messages"
-       depends on VIDEO_OMAP3
-       ---help---
-         Enable debug messages on OMAP 3 camera controller driver.
-
-config SOC_CAMERA
-       tristate "SoC camera support"
-       depends on VIDEO_V4L2 && HAS_DMA && I2C
-       select VIDEOBUF_GEN
-       select VIDEOBUF2_CORE
-       help
-         SoC Camera is a common API to several cameras, not connecting
-         over a bus like PCI or USB. For example some i2c camera connected
-         directly to the data bus of an SoC.
-
-config SOC_CAMERA_IMX074
-       tristate "imx074 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This driver supports IMX074 cameras from Sony
-
-config SOC_CAMERA_MT9M001
-       tristate "mt9m001 support"
-       depends on SOC_CAMERA && I2C
-       select GPIO_PCA953X if MT9M001_PCA9536_SWITCH
-       help
-         This driver supports MT9M001 cameras from Micron, monochrome
-         and colour models.
-
-config SOC_CAMERA_MT9M111
-       tristate "mt9m111, mt9m112 and mt9m131 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This driver supports MT9M111, MT9M112 and MT9M131 cameras from
-         Micron/Aptina
-
-config SOC_CAMERA_MT9T031
-       tristate "mt9t031 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This driver supports MT9T031 cameras from Micron.
-
-config SOC_CAMERA_MT9T112
-       tristate "mt9t112 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This driver supports MT9T112 cameras from Aptina.
-
-config SOC_CAMERA_MT9V022
-       tristate "mt9v022 support"
-       depends on SOC_CAMERA && I2C
-       select GPIO_PCA953X if MT9V022_PCA9536_SWITCH
-       help
-         This driver supports MT9V022 cameras from Micron
-
-config SOC_CAMERA_RJ54N1
-       tristate "rj54n1cb0c support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a rj54n1cb0c video driver
-
-config SOC_CAMERA_TW9910
-       tristate "tw9910 support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a tw9910 video driver
-
-config SOC_CAMERA_PLATFORM
-       tristate "platform camera support"
-       depends on SOC_CAMERA
-       help
-         This is a generic SoC camera platform driver, useful for testing
-
-config SOC_CAMERA_OV2640
-       tristate "ov2640 camera support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a ov2640 camera driver
-
-config SOC_CAMERA_OV5642
-       tristate "ov5642 camera support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a V4L2 camera driver for the OmniVision OV5642 sensor
-
-config SOC_CAMERA_OV6650
-       tristate "ov6650 sensor support"
-       depends on SOC_CAMERA && I2C
-       ---help---
-         This is a V4L2 SoC camera driver for the OmniVision OV6650 sensor
-
-config SOC_CAMERA_OV772X
-       tristate "ov772x camera support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a ov772x camera driver
-
-config SOC_CAMERA_OV9640
-       tristate "ov9640 camera support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a ov9640 camera driver
-
-config SOC_CAMERA_OV9740
-       tristate "ov9740 camera support"
-       depends on SOC_CAMERA && I2C
-       help
-         This is a ov9740 camera driver
-
-config MX1_VIDEO
-       bool
-
-config VIDEO_MX1
-       tristate "i.MX1/i.MXL CMOS Sensor Interface driver"
-       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 MX3_VIDEO
-       bool
-
-config VIDEO_MX3
-       tristate "i.MX3x Camera Sensor Interface driver"
-       depends on VIDEO_DEV && MX3_IPU && SOC_CAMERA
-       select VIDEOBUF2_DMA_CONTIG
-       select MX3_VIDEO
-       ---help---
-         This is a v4l2 driver for the i.MX3x Camera Sensor Interface
-
-config VIDEO_PXA27x
-       tristate "PXA27x Quick Capture Interface driver"
-       depends on VIDEO_DEV && PXA27x && SOC_CAMERA
-       select VIDEOBUF_DMA_SG
-       ---help---
-         This is a v4l2 driver for the PXA27x Quick Capture Interface
-
-config VIDEO_SH_MOBILE_CSI2
-       tristate "SuperH Mobile MIPI CSI-2 Interface driver"
-       depends on VIDEO_DEV && SOC_CAMERA && HAVE_CLK
-       ---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
-       select VIDEOBUF2_DMA_CONTIG
-       ---help---
-         This is a v4l2 driver for the SuperH Mobile CEU Interface
-
-config VIDEO_OMAP1
-       tristate "OMAP1 Camera Interface driver"
-       depends on VIDEO_DEV && ARCH_OMAP1 && SOC_CAMERA
-       select VIDEOBUF_DMA_CONTIG
-       select VIDEOBUF_DMA_SG
-       ---help---
-         This is a v4l2 driver for the TI OMAP1 camera interface
-
-config VIDEO_OMAP2
-       tristate "OMAP2 Camera Capture Interface driver"
-       depends on VIDEO_DEV && ARCH_OMAP2
-       select VIDEOBUF_DMA_SG
-       ---help---
-         This is a v4l2 driver for the TI OMAP2 camera capture interface
-
-config VIDEO_MX2_HOSTSUPPORT
-       bool
-
-config VIDEO_MX2
-       tristate "i.MX27/i.MX25 Camera Sensor Interface driver"
-       depends on VIDEO_DEV && SOC_CAMERA && (MACH_MX27 || ARCH_MX25)
-       select VIDEOBUF2_DMA_CONTIG
-       select VIDEO_MX2_HOSTSUPPORT
-       ---help---
-         This is a v4l2 driver for the i.MX27 and the i.MX25 Camera Sensor
-         Interface
-
-config VIDEO_ATMEL_ISI
-       tristate "ATMEL Image Sensor Interface (ISI) support"
-       depends on VIDEO_DEV && SOC_CAMERA && ARCH_AT91
-       select VIDEOBUF2_DMA_CONTIG
-       ---help---
-         This module makes the ATMEL Image Sensor Interface available
-         as a v4l2 device.
-
-source "drivers/media/video/s5p-fimc/Kconfig"
-source "drivers/media/video/s5p-tv/Kconfig"
-
-endif # V4L_PLATFORM_DRIVERS
-endif # VIDEO_CAPTURE_DRIVERS
-
-menuconfig V4L_MEM2MEM_DRIVERS
-       bool "Memory-to-memory multimedia devices"
-       depends on VIDEO_V4L2
-       default n
-       ---help---
-         Say Y here to enable selecting drivers for V4L devices that
-         use system memory for both source and destination buffers, as opposed
-         to capture and output drivers, which use memory buffers for just
-         one of those.
-
-if V4L_MEM2MEM_DRIVERS
-
-config VIDEO_MEM2MEM_TESTDEV
-       tristate "Virtual test device for mem2mem framework"
-       depends on VIDEO_DEV && VIDEO_V4L2
-       select VIDEOBUF2_VMALLOC
-       select V4L2_MEM2MEM_DEV
-       default n
-       ---help---
-         This is a virtual test device for the memory-to-memory driver
-         framework.
-
-config VIDEO_SAMSUNG_S5P_G2D
-       tristate "Samsung S5P and EXYNOS4 G2D 2d graphics accelerator driver"
-       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       default n
-       ---help---
-         This is a v4l2 driver for Samsung S5P and EXYNOS4 G2D
-         2d graphics accelerator.
-
-config VIDEO_SAMSUNG_S5P_JPEG
-       tristate "Samsung S5P/Exynos4 JPEG codec driver (EXPERIMENTAL)"
-       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P && EXPERIMENTAL
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       ---help---
-         This is a v4l2 driver for Samsung S5P and EXYNOS4 JPEG codec
-
-config VIDEO_SAMSUNG_S5P_MFC
-       tristate "Samsung S5P MFC 5.1 Video Codec"
-       depends on VIDEO_DEV && VIDEO_V4L2 && PLAT_S5P
-       select VIDEOBUF2_DMA_CONTIG
-       default n
-       help
-           MFC 5.1 driver for V4L2.
-
-config VIDEO_MX2_EMMAPRP
-       tristate "MX2 eMMa-PrP support"
-       depends on VIDEO_DEV && VIDEO_V4L2 && SOC_IMX27
-       select VIDEOBUF2_DMA_CONTIG
-       select V4L2_MEM2MEM_DEV
-       help
-           MX2X chips have a PrP that can be used to process buffers from
-           memory to memory. Operations include resizing and format
-           conversion.
-
-endif # V4L_MEM2MEM_DRIVERS
diff --git a/drivers/media/video/Makefile b/drivers/media/video/Makefile
deleted file mode 100644 (file)
index b7da9fa..0000000
+++ /dev/null
@@ -1,218 +0,0 @@
-#
-# Makefile for the video capture/playback device drivers.
-#
-
-tuner-objs     :=      tuner-core.o
-
-msp3400-objs   :=      msp3400-driver.o msp3400-kthreads.o
-
-stkwebcam-objs :=      stk-webcam.o stk-sensor.o
-
-omap2cam-objs  :=      omap24xxcam.o omap24xxcam-dma.o
-
-videodev-objs  :=      v4l2-dev.o v4l2-ioctl.o v4l2-device.o v4l2-fh.o \
-                       v4l2-event.o v4l2-ctrls.o v4l2-subdev.o
-ifeq ($(CONFIG_COMPAT),y)
-  videodev-objs += v4l2-compat-ioctl32.o
-endif
-
-# V4L2 core modules
-
-obj-$(CONFIG_VIDEO_DEV) += videodev.o v4l2-int-device.o
-obj-$(CONFIG_VIDEO_V4L2_COMMON) += v4l2-common.o
-
-# Helper modules
-
-obj-$(CONFIG_VIDEO_APTINA_PLL) += aptina-pll.o
-
-# All i2c modules must come first:
-
-obj-$(CONFIG_VIDEO_TUNER) += tuner.o
-obj-$(CONFIG_VIDEO_TVAUDIO) += tvaudio.o
-obj-$(CONFIG_VIDEO_TDA7432) += tda7432.o
-obj-$(CONFIG_VIDEO_SAA6588) += saa6588.o
-obj-$(CONFIG_VIDEO_TDA9840) += tda9840.o
-obj-$(CONFIG_VIDEO_TEA6415C) += tea6415c.o
-obj-$(CONFIG_VIDEO_TEA6420) += tea6420.o
-obj-$(CONFIG_VIDEO_SAA7110) += saa7110.o
-obj-$(CONFIG_VIDEO_SAA711X) += saa7115.o
-obj-$(CONFIG_VIDEO_SAA717X) += saa717x.o
-obj-$(CONFIG_VIDEO_SAA7127) += saa7127.o
-obj-$(CONFIG_VIDEO_SAA7185) += saa7185.o
-obj-$(CONFIG_VIDEO_SAA7191) += saa7191.o
-obj-$(CONFIG_VIDEO_ADV7170) += adv7170.o
-obj-$(CONFIG_VIDEO_ADV7175) += adv7175.o
-obj-$(CONFIG_VIDEO_ADV7180) += adv7180.o
-obj-$(CONFIG_VIDEO_ADV7183) += adv7183.o
-obj-$(CONFIG_VIDEO_ADV7343) += adv7343.o
-obj-$(CONFIG_VIDEO_ADV7393) += adv7393.o
-obj-$(CONFIG_VIDEO_VPX3220) += vpx3220.o
-obj-$(CONFIG_VIDEO_VS6624)  += vs6624.o
-obj-$(CONFIG_VIDEO_BT819) += bt819.o
-obj-$(CONFIG_VIDEO_BT856) += bt856.o
-obj-$(CONFIG_VIDEO_BT866) += bt866.o
-obj-$(CONFIG_VIDEO_KS0127) += ks0127.o
-obj-$(CONFIG_VIDEO_THS7303) += ths7303.o
-obj-$(CONFIG_VIDEO_VINO) += indycam.o
-obj-$(CONFIG_VIDEO_TVP5150) += tvp5150.o
-obj-$(CONFIG_VIDEO_TVP514X) += tvp514x.o
-obj-$(CONFIG_VIDEO_TVP7002) += tvp7002.o
-obj-$(CONFIG_VIDEO_MSP3400) += msp3400.o
-obj-$(CONFIG_VIDEO_CS5345) += cs5345.o
-obj-$(CONFIG_VIDEO_CS53L32A) += cs53l32a.o
-obj-$(CONFIG_VIDEO_M52790) += m52790.o
-obj-$(CONFIG_VIDEO_TLV320AIC23B) += tlv320aic23b.o
-obj-$(CONFIG_VIDEO_WM8775) += wm8775.o
-obj-$(CONFIG_VIDEO_WM8739) += wm8739.o
-obj-$(CONFIG_VIDEO_VP27SMPX) += vp27smpx.o
-obj-$(CONFIG_VIDEO_CX25840) += cx25840/
-obj-$(CONFIG_VIDEO_UPD64031A) += upd64031a.o
-obj-$(CONFIG_VIDEO_UPD64083) += upd64083.o
-obj-$(CONFIG_VIDEO_OV7670)     += ov7670.o
-obj-$(CONFIG_VIDEO_TCM825X) += tcm825x.o
-obj-$(CONFIG_VIDEO_TVEEPROM) += tveeprom.o
-obj-$(CONFIG_VIDEO_MT9M032) += mt9m032.o
-obj-$(CONFIG_VIDEO_MT9P031) += mt9p031.o
-obj-$(CONFIG_VIDEO_MT9T001) += mt9t001.o
-obj-$(CONFIG_VIDEO_MT9V011) += mt9v011.o
-obj-$(CONFIG_VIDEO_MT9V032) += mt9v032.o
-obj-$(CONFIG_VIDEO_SR030PC30)  += sr030pc30.o
-obj-$(CONFIG_VIDEO_NOON010PC30)        += noon010pc30.o
-obj-$(CONFIG_VIDEO_M5MOLS)     += m5mols/
-obj-$(CONFIG_VIDEO_S5K6AA)     += s5k6aa.o
-obj-$(CONFIG_VIDEO_SMIAPP)     += smiapp/
-obj-$(CONFIG_VIDEO_ADP1653)    += adp1653.o
-obj-$(CONFIG_VIDEO_AS3645A)    += as3645a.o
-
-obj-$(CONFIG_VIDEO_SMIAPP_PLL) += smiapp-pll.o
-
-obj-$(CONFIG_SOC_CAMERA_IMX074)                += imx074.o
-obj-$(CONFIG_SOC_CAMERA_MT9M001)       += mt9m001.o
-obj-$(CONFIG_SOC_CAMERA_MT9M111)       += mt9m111.o
-obj-$(CONFIG_SOC_CAMERA_MT9T031)       += mt9t031.o
-obj-$(CONFIG_SOC_CAMERA_MT9T112)       += mt9t112.o
-obj-$(CONFIG_SOC_CAMERA_MT9V022)       += mt9v022.o
-obj-$(CONFIG_SOC_CAMERA_OV2640)                += ov2640.o
-obj-$(CONFIG_SOC_CAMERA_OV5642)                += ov5642.o
-obj-$(CONFIG_SOC_CAMERA_OV6650)                += ov6650.o
-obj-$(CONFIG_SOC_CAMERA_OV772X)                += ov772x.o
-obj-$(CONFIG_SOC_CAMERA_OV9640)                += ov9640.o
-obj-$(CONFIG_SOC_CAMERA_OV9740)                += ov9740.o
-obj-$(CONFIG_SOC_CAMERA_RJ54N1)                += rj54n1cb0c.o
-obj-$(CONFIG_SOC_CAMERA_TW9910)                += tw9910.o
-
-# And now the v4l2 drivers:
-
-obj-$(CONFIG_VIDEO_BT848) += bt8xx/
-obj-$(CONFIG_VIDEO_ZORAN) += zoran/
-obj-$(CONFIG_VIDEO_CQCAM) += c-qcam.o
-obj-$(CONFIG_VIDEO_BWQCAM) += bw-qcam.o
-obj-$(CONFIG_VIDEO_W9966) += w9966.o
-obj-$(CONFIG_VIDEO_PMS) += pms.o
-obj-$(CONFIG_VIDEO_VINO) += vino.o
-obj-$(CONFIG_VIDEO_MEYE) += meye.o
-obj-$(CONFIG_VIDEO_SAA7134) += saa7134/
-obj-$(CONFIG_VIDEO_CX88) += cx88/
-obj-$(CONFIG_VIDEO_EM28XX) += em28xx/
-obj-$(CONFIG_VIDEO_TLG2300) += tlg2300/
-obj-$(CONFIG_VIDEO_CX231XX) += cx231xx/
-obj-$(CONFIG_VIDEO_CX25821) += cx25821/
-obj-$(CONFIG_VIDEO_USBVISION) += usbvision/
-obj-$(CONFIG_VIDEO_PVRUSB2) += pvrusb2/
-obj-$(CONFIG_VIDEO_CPIA2) += cpia2/
-obj-$(CONFIG_VIDEO_TM6000) += tm6000/
-obj-$(CONFIG_VIDEO_MXB) += mxb.o
-obj-$(CONFIG_VIDEO_HEXIUM_ORION) += hexium_orion.o
-obj-$(CONFIG_VIDEO_HEXIUM_GEMINI) += hexium_gemini.o
-obj-$(CONFIG_STA2X11_VIP) += sta2x11_vip.o
-obj-$(CONFIG_VIDEO_TIMBERDALE) += timblogiw.o
-
-obj-$(CONFIG_VIDEOBUF_GEN) += videobuf-core.o
-obj-$(CONFIG_VIDEOBUF_DMA_SG) += videobuf-dma-sg.o
-obj-$(CONFIG_VIDEOBUF_DMA_CONTIG) += videobuf-dma-contig.o
-obj-$(CONFIG_VIDEOBUF_VMALLOC) += videobuf-vmalloc.o
-obj-$(CONFIG_VIDEOBUF_DVB) += videobuf-dvb.o
-obj-$(CONFIG_VIDEO_BTCX)  += btcx-risc.o
-
-obj-$(CONFIG_VIDEOBUF2_CORE)           += videobuf2-core.o
-obj-$(CONFIG_VIDEOBUF2_MEMOPS)         += videobuf2-memops.o
-obj-$(CONFIG_VIDEOBUF2_VMALLOC)                += videobuf2-vmalloc.o
-obj-$(CONFIG_VIDEOBUF2_DMA_CONTIG)     += videobuf2-dma-contig.o
-obj-$(CONFIG_VIDEOBUF2_DMA_SG)         += videobuf2-dma-sg.o
-
-obj-$(CONFIG_V4L2_MEM2MEM_DEV) += v4l2-mem2mem.o
-
-obj-$(CONFIG_VIDEO_M32R_AR_M64278) += arv.o
-
-obj-$(CONFIG_VIDEO_CX2341X) += cx2341x.o
-
-obj-$(CONFIG_VIDEO_CAFE_CCIC) += marvell-ccic/
-obj-$(CONFIG_VIDEO_MMP_CAMERA) += marvell-ccic/
-
-obj-$(CONFIG_VIDEO_VIA_CAMERA) += via-camera.o
-
-obj-$(CONFIG_VIDEO_OMAP3)      += omap3isp/
-
-obj-$(CONFIG_USB_ZR364XX)       += zr364xx.o
-obj-$(CONFIG_USB_STKWEBCAM)     += stkwebcam.o
-
-obj-$(CONFIG_USB_SN9C102)       += sn9c102/
-obj-$(CONFIG_USB_PWC)           += pwc/
-obj-$(CONFIG_USB_GSPCA)         += gspca/
-
-obj-$(CONFIG_VIDEO_HDPVR)      += hdpvr/
-
-obj-$(CONFIG_USB_S2255)                += s2255drv.o
-
-obj-$(CONFIG_VIDEO_IVTV) += ivtv/
-obj-$(CONFIG_VIDEO_CX18) += cx18/
-
-obj-$(CONFIG_VIDEO_VIU) += fsl-viu.o
-obj-$(CONFIG_VIDEO_VIVI) += vivi.o
-obj-$(CONFIG_VIDEO_MEM2MEM_TESTDEV) += mem2mem_testdev.o
-obj-$(CONFIG_VIDEO_CX23885) += cx23885/
-
-obj-$(CONFIG_VIDEO_AK881X)             += ak881x.o
-
-obj-$(CONFIG_VIDEO_OMAP2)              += omap2cam.o
-obj-$(CONFIG_SOC_CAMERA)               += soc_camera.o soc_mediabus.o
-obj-$(CONFIG_SOC_CAMERA_PLATFORM)      += soc_camera_platform.o
-# soc-camera host drivers have to be linked after camera drivers
-obj-$(CONFIG_VIDEO_MX1)                        += mx1_camera.o
-obj-$(CONFIG_VIDEO_MX2)                        += mx2_camera.o
-obj-$(CONFIG_VIDEO_MX3)                        += mx3_camera.o
-obj-$(CONFIG_VIDEO_PXA27x)             += pxa_camera.o
-obj-$(CONFIG_VIDEO_SH_MOBILE_CSI2)     += sh_mobile_csi2.o
-obj-$(CONFIG_VIDEO_SH_MOBILE_CEU)      += sh_mobile_ceu_camera.o
-obj-$(CONFIG_VIDEO_OMAP1)              += omap1_camera.o
-obj-$(CONFIG_VIDEO_ATMEL_ISI)          += atmel-isi.o
-
-obj-$(CONFIG_VIDEO_MX2_EMMAPRP)                += mx2_emmaprp.o
-
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_FIMC)   += s5p-fimc/
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_JPEG)   += s5p-jpeg/
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_MFC)    += s5p-mfc/
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_TV)     += s5p-tv/
-
-obj-$(CONFIG_VIDEO_SAMSUNG_S5P_G2D)    += s5p-g2d/
-
-obj-$(CONFIG_BLACKFIN)                  += blackfin/
-
-obj-$(CONFIG_ARCH_DAVINCI)             += davinci/
-
-obj-$(CONFIG_VIDEO_SH_VOU)             += sh_vou.o
-
-obj-$(CONFIG_VIDEO_AU0828) += au0828/
-
-obj-$(CONFIG_USB_VIDEO_CLASS)  += uvc/
-obj-$(CONFIG_VIDEO_SAA7164)     += saa7164/
-
-obj-$(CONFIG_VIDEO_IR_I2C)  += ir-kbd-i2c.o
-
-obj-y  += davinci/
-
-obj-$(CONFIG_ARCH_OMAP)        += omap/
-
-ccflags-y += -I$(srctree)/drivers/media/dvb/dvb-core
-ccflags-y += -I$(srctree)/drivers/media/dvb/frontends
-ccflags-y += -I$(srctree)/drivers/media/common/tuners
diff --git a/drivers/media/video/bt8xx/Kconfig b/drivers/media/video/bt8xx/Kconfig
deleted file mode 100644 (file)
index 7da5c2e..0000000
+++ /dev/null
@@ -1,27 +0,0 @@
-config VIDEO_BT848
-       tristate "BT848 Video For Linux"
-       depends on VIDEO_DEV && PCI && I2C && VIDEO_V4L2
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEOBUF_DMA_SG
-       depends on RC_CORE
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       select VIDEO_MSP3400 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TVAUDIO if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_TDA7432 if VIDEO_HELPER_CHIPS_AUTO
-       select VIDEO_SAA6588 if VIDEO_HELPER_CHIPS_AUTO
-       ---help---
-         Support for BT848 based frame grabber/overlay boards. This includes
-         the Miro, Hauppauge and STB boards. Please read the material in
-         <file:Documentation/video4linux/bttv/> for more information.
-
-         To compile this driver as a module, choose M here: the
-         module will be called bttv.
-
-config VIDEO_BT848_DVB
-       bool "DVB/ATSC Support for bt878 based TV cards"
-       depends on VIDEO_BT848 && DVB_CORE
-       select DVB_BT8XX
-       ---help---
-         This adds support for DVB/ATSC cards based on the BT878 chip.
diff --git a/drivers/media/video/bt8xx/Makefile b/drivers/media/video/bt8xx/Makefile
deleted file mode 100644 (file)
index 3f9a2b2..0000000
+++ /dev/null
@@ -1,13 +0,0 @@
-#
-# Makefile for the video capture/playback device drivers.
-#
-
-bttv-objs      :=      bttv-driver.o bttv-cards.o bttv-if.o \
-                      bttv-risc.o bttv-vbi.o bttv-i2c.o bttv-gpio.o \
-                      bttv-input.o bttv-audio-hook.o
-
-obj-$(CONFIG_VIDEO_BT848) += bttv.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
diff --git a/drivers/media/video/cx23885/Kconfig b/drivers/media/video/cx23885/Kconfig
deleted file mode 100644 (file)
index b391e9b..0000000
+++ /dev/null
@@ -1,46 +0,0 @@
-config VIDEO_CX23885
-       tristate "Conexant cx23885 (2388x successor) support"
-       depends on DVB_CORE && VIDEO_DEV && PCI && I2C && INPUT && SND
-       select SND_PCM
-       select I2C_ALGOBIT
-       select VIDEO_BTCX
-       select VIDEO_TUNER
-       select VIDEO_TVEEPROM
-       depends on RC_CORE
-       select VIDEOBUF_DVB
-       select VIDEOBUF_DMA_SG
-       select VIDEO_CX25840
-       select VIDEO_CX2341X
-       select DVB_DIB7000P if !DVB_FE_CUSTOMISE
-       select DVB_S5H1409 if !DVB_FE_CUSTOMISE
-       select DVB_S5H1411 if !DVB_FE_CUSTOMISE
-       select DVB_LGDT330X if !DVB_FE_CUSTOMISE
-       select DVB_ZL10353 if !DVB_FE_CUSTOMISE
-       select DVB_TDA10048 if !DVB_FE_CUSTOMISE
-       select DVB_LNBP21 if !DVB_FE_CUSTOMISE
-       select DVB_STV6110 if !DVB_FE_CUSTOMISE
-       select DVB_CX24116 if !DVB_FE_CUSTOMISE
-       select DVB_STV0900 if !DVB_FE_CUSTOMISE
-       select DVB_DS3000 if !DVB_FE_CUSTOMISE
-       select DVB_STV0367 if !DVB_FE_CUSTOMISE
-       select MEDIA_TUNER_MT2131 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC2028 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA8290 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_TDA18271 if !MEDIA_TUNER_CUSTOMISE
-       select MEDIA_TUNER_XC5000 if !MEDIA_TUNER_CUSTOMISE
-       ---help---
-         This is a video4linux driver for Conexant 23885 based
-         TV cards.
-
-         To compile this driver as a module, choose M here: the
-         module will be called cx23885
-
-config MEDIA_ALTERA_CI
-       tristate "Altera FPGA based CI module"
-       depends on VIDEO_CX23885 && DVB_CORE
-       select ALTERA_STAPL
-       ---help---
-         An Altera FPGA CI module for NetUP Dual DVB-T/C RF CI card.
-
-         To compile this driver as a module, choose M here: the
-         module will be called altera-ci
diff --git a/drivers/media/video/tlg2300/Makefile b/drivers/media/video/tlg2300/Makefile
deleted file mode 100644 (file)
index ea09b9a..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-poseidon-objs := pd-video.o pd-alsa.o pd-dvb.o pd-radio.o pd-main.o
-
-obj-$(CONFIG_VIDEO_TLG2300) += poseidon.o
-
-ccflags-y += -Idrivers/media/video
-ccflags-y += -Idrivers/media/common/tuners
-ccflags-y += -Idrivers/media/dvb/dvb-core
-ccflags-y += -Idrivers/media/dvb/frontends
-
index b67a3018b13645f2e15f9c773f92d6f9e5acba06..ce229ea933d1388467aed017b9f65d4a2f9ef3a1 100644 (file)
@@ -470,7 +470,8 @@ static int __devinit device_800_init(struct pm80x_chip *chip,
 
        ret =
            mfd_add_devices(chip->dev, 0, &onkey_devs[0],
-                           ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0);
+                           ARRAY_SIZE(onkey_devs), &onkey_resources[0], 0,
+                           NULL);
        if (ret < 0) {
                dev_err(chip->dev, "Failed to add onkey subdev\n");
                goto out_dev;
@@ -481,7 +482,7 @@ static int __devinit device_800_init(struct pm80x_chip *chip,
                rtc_devs[0].platform_data = pdata->rtc;
                rtc_devs[0].pdata_size = sizeof(struct pm80x_rtc_pdata);
                ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
-                                     ARRAY_SIZE(rtc_devs), NULL, 0);
+                                     ARRAY_SIZE(rtc_devs), NULL, 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add rtc subdev\n");
                        goto out_dev;
index 6146583589f61b53af6918db338861f116596a5b..c20a31136f045ccd57c0c19ec62ceb6b229bc861 100644 (file)
@@ -216,7 +216,8 @@ static int __devinit device_805_init(struct pm80x_chip *chip)
        }
 
        ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
-                             ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+                             ARRAY_SIZE(codec_devs), &codec_resources[0], 0,
+                             NULL);
        if (ret < 0) {
                dev_err(chip->dev, "Failed to add codec subdev\n");
                goto out_codec;
index d09918cf1b1556a74edb622e0174d3ceffdf7ca6..b73f033b2c602fadce09dd97d0c7623581962e12 100644 (file)
@@ -637,7 +637,7 @@ static void __devinit device_bk_init(struct pm860x_chip *chip,
                        bk_devs[i].resources = &bk_resources[j];
                        ret = mfd_add_devices(chip->dev, 0,
                                              &bk_devs[i], 1,
-                                             &bk_resources[j], 0);
+                                             &bk_resources[j], 0, NULL);
                        if (ret < 0) {
                                dev_err(chip->dev, "Failed to add "
                                        "backlight subdev\n");
@@ -672,7 +672,7 @@ static void __devinit device_led_init(struct pm860x_chip *chip,
                        led_devs[i].resources = &led_resources[j],
                        ret = mfd_add_devices(chip->dev, 0,
                                              &led_devs[i], 1,
-                                             &led_resources[j], 0);
+                                             &led_resources[j], 0, NULL);
                        if (ret < 0) {
                                dev_err(chip->dev, "Failed to add "
                                        "led subdev\n");
@@ -709,7 +709,7 @@ static void __devinit device_regulator_init(struct pm860x_chip *chip,
                regulator_devs[i].resources = &regulator_resources[seq];
 
                ret = mfd_add_devices(chip->dev, 0, &regulator_devs[i], 1,
-                                     &regulator_resources[seq], 0);
+                                     &regulator_resources[seq], 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add regulator subdev\n");
                        goto out;
@@ -733,7 +733,7 @@ static void __devinit device_rtc_init(struct pm860x_chip *chip,
        rtc_devs[0].resources = &rtc_resources[0];
        ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
                              ARRAY_SIZE(rtc_devs), &rtc_resources[0],
-                             chip->irq_base);
+                             chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add rtc subdev\n");
 }
@@ -752,7 +752,7 @@ static void __devinit device_touch_init(struct pm860x_chip *chip,
        touch_devs[0].resources = &touch_resources[0];
        ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
                              ARRAY_SIZE(touch_devs), &touch_resources[0],
-                             chip->irq_base);
+                             chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add touch subdev\n");
 }
@@ -770,7 +770,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
        power_devs[0].num_resources = ARRAY_SIZE(battery_resources);
        power_devs[0].resources = &battery_resources[0],
        ret = mfd_add_devices(chip->dev, 0, &power_devs[0], 1,
-                             &battery_resources[0], chip->irq_base);
+                             &battery_resources[0], chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add battery subdev\n");
 
@@ -779,7 +779,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
        power_devs[1].num_resources = ARRAY_SIZE(charger_resources);
        power_devs[1].resources = &charger_resources[0],
        ret = mfd_add_devices(chip->dev, 0, &power_devs[1], 1,
-                             &charger_resources[0], chip->irq_base);
+                             &charger_resources[0], chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add charger subdev\n");
 
@@ -788,7 +788,7 @@ static void __devinit device_power_init(struct pm860x_chip *chip,
        power_devs[2].num_resources = ARRAY_SIZE(preg_resources);
        power_devs[2].resources = &preg_resources[0],
        ret = mfd_add_devices(chip->dev, 0, &power_devs[2], 1,
-                             &preg_resources[0], chip->irq_base);
+                             &preg_resources[0], chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add preg subdev\n");
 }
@@ -802,7 +802,7 @@ static void __devinit device_onkey_init(struct pm860x_chip *chip,
        onkey_devs[0].resources = &onkey_resources[0],
        ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
                              ARRAY_SIZE(onkey_devs), &onkey_resources[0],
-                             chip->irq_base);
+                             chip->irq_base, NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add onkey subdev\n");
 }
@@ -815,7 +815,8 @@ static void __devinit device_codec_init(struct pm860x_chip *chip,
        codec_devs[0].num_resources = ARRAY_SIZE(codec_resources);
        codec_devs[0].resources = &codec_resources[0],
        ret = mfd_add_devices(chip->dev, 0, &codec_devs[0],
-                             ARRAY_SIZE(codec_devs), &codec_resources[0], 0);
+                             ARRAY_SIZE(codec_devs), &codec_resources[0], 0,
+                             NULL);
        if (ret < 0)
                dev_err(chip->dev, "Failed to add codec subdev\n");
 }
index 44a3fdbadef40df1e09b12884f44caa46b76f0ac..f1beb4971f87f580090df39b38dbdc5e9937140e 100644 (file)
@@ -424,7 +424,7 @@ static int aat2870_i2c_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(aat2870->dev, 0, aat2870_devs,
-                             ARRAY_SIZE(aat2870_devs), NULL, 0);
+                             ARRAY_SIZE(aat2870_devs), NULL, 0, NULL);
        if (ret != 0) {
                dev_err(aat2870->dev, "Failed to add subdev: %d\n", ret);
                goto out_disable;
index 78fca2902c8da38fd07660e381e8ed55c0d78c2d..01781ae5d0d7f3de38c811dad727ecc179c94be7 100644 (file)
@@ -946,7 +946,7 @@ static int __devinit ab3100_probe(struct i2c_client *client,
        }
 
        err = mfd_add_devices(&client->dev, 0, ab3100_devs,
-               ARRAY_SIZE(ab3100_devs), NULL, 0);
+                             ARRAY_SIZE(ab3100_devs), NULL, 0, NULL);
 
        ab3100_setup_debugfs(ab3100);
 
index 626b4ecaf64761fdd3cd43ac3f02986d6830e467..47adf800024e01f8cdf05856eb3b356226c527f3 100644 (file)
@@ -1418,25 +1418,25 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
 
        ret = mfd_add_devices(ab8500->dev, 0, abx500_common_devs,
                        ARRAY_SIZE(abx500_common_devs), NULL,
-                       ab8500->irq_base);
+                       ab8500->irq_base, ab8500->domain);
        if (ret)
                goto out_freeirq;
 
        if (is_ab9540(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_devs,
                                ARRAY_SIZE(ab9540_devs), NULL,
-                               ab8500->irq_base);
+                               ab8500->irq_base, ab8500->domain);
        else
                ret = mfd_add_devices(ab8500->dev, 0, ab8500_devs,
                                ARRAY_SIZE(ab8500_devs), NULL,
-                               ab8500->irq_base);
+                               ab8500->irq_base, ab8500->domain);
        if (ret)
                goto out_freeirq;
 
        if (is_ab9540(ab8500) || is_ab8505(ab8500))
                ret = mfd_add_devices(ab8500->dev, 0, ab9540_ab8505_devs,
                                ARRAY_SIZE(ab9540_ab8505_devs), NULL,
-                               ab8500->irq_base);
+                               ab8500->irq_base, ab8500->domain);
        if (ret)
                goto out_freeirq;
 
@@ -1444,7 +1444,7 @@ static int __devinit ab8500_probe(struct platform_device *pdev)
                /* Add battery management devices */
                ret = mfd_add_devices(ab8500->dev, 0, ab8500_bm_devs,
                                      ARRAY_SIZE(ab8500_bm_devs), NULL,
-                                     ab8500->irq_base);
+                                     ab8500->irq_base, ab8500->domain);
                if (ret)
                        dev_err(ab8500->dev, "error adding bm devices\n");
        }
index c7983e862549a0b79775cae3e76c7cf0c867ad83..1b48f2094806c75fa8914657978f1b7bf814ae93 100644 (file)
@@ -316,7 +316,7 @@ int __devinit arizona_dev_init(struct arizona *arizona)
        }
 
        ret = mfd_add_devices(arizona->dev, -1, early_devs,
-                             ARRAY_SIZE(early_devs), NULL, 0);
+                             ARRAY_SIZE(early_devs), NULL, 0, NULL);
        if (ret != 0) {
                dev_err(dev, "Failed to add early children: %d\n", ret);
                return ret;
@@ -516,11 +516,11 @@ int __devinit arizona_dev_init(struct arizona *arizona)
        switch (arizona->type) {
        case WM5102:
                ret = mfd_add_devices(arizona->dev, -1, wm5102_devs,
-                                     ARRAY_SIZE(wm5102_devs), NULL, 0);
+                                     ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
                break;
        case WM5110:
                ret = mfd_add_devices(arizona->dev, -1, wm5110_devs,
-                                     ARRAY_SIZE(wm5102_devs), NULL, 0);
+                                     ARRAY_SIZE(wm5102_devs), NULL, 0, NULL);
                break;
        }
 
index 683e18a23329802875d03f92d53e354a6474ad9d..62f0883a7630c360ab9e52f9fa11f306d1a3efee 100644 (file)
@@ -913,14 +913,14 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
        if (pdata->clock_rate) {
                ds1wm_pdata.clock_rate = pdata->clock_rate;
                ret = mfd_add_devices(&pdev->dev, pdev->id,
-                       &asic3_cell_ds1wm, 1, mem, asic->irq_base);
+                       &asic3_cell_ds1wm, 1, mem, asic->irq_base, NULL);
                if (ret < 0)
                        goto out;
        }
 
        if (mem_sdio && (irq >= 0)) {
                ret = mfd_add_devices(&pdev->dev, pdev->id,
-                       &asic3_cell_mmc, 1, mem_sdio, irq);
+                       &asic3_cell_mmc, 1, mem_sdio, irq, NULL);
                if (ret < 0)
                        goto out;
        }
@@ -934,7 +934,7 @@ static int __init asic3_mfd_probe(struct platform_device *pdev,
                        asic3_cell_leds[i].pdata_size = sizeof(pdata->leds[i]);
                }
                ret = mfd_add_devices(&pdev->dev, 0,
-                       asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0);
+                       asic3_cell_leds, ASIC3_NUM_LEDS, NULL, 0, NULL);
        }
 
  out:
index 3419e726de478cb330801d1dfb1db42d2a5d1748..2b282133c725b1b6fbb9c0f10442760640bfcd47 100644 (file)
@@ -149,7 +149,7 @@ static int __devinit cs5535_mfd_probe(struct pci_dev *pdev,
        }
 
        err = mfd_add_devices(&pdev->dev, -1, cs5535_mfd_cells,
-                       ARRAY_SIZE(cs5535_mfd_cells), NULL, 0);
+                             ARRAY_SIZE(cs5535_mfd_cells), NULL, 0, NULL);
        if (err) {
                dev_err(&pdev->dev, "MFD add devices failed: %d\n", err);
                goto err_disable;
index 2544910e1fd604f5f6184009a1a208fa5f838cf2..a0a62b24621b831cb0c7c43e62692bd061eb7163 100644 (file)
@@ -803,7 +803,7 @@ int __devinit da9052_device_init(struct da9052 *da9052, u8 chip_id)
                dev_err(da9052->dev, "DA9052 ADC IRQ failed ret=%d\n", ret);
 
        ret = mfd_add_devices(da9052->dev, -1, da9052_subdev_info,
-                             ARRAY_SIZE(da9052_subdev_info), NULL, 0);
+                             ARRAY_SIZE(da9052_subdev_info), NULL, 0, NULL);
        if (ret)
                goto err;
 
index 4e2af2cb2d26a76534c884c3cc57fe97f3c30d52..45e83a68641b81d0a5f7605b19027e2cd5b1aec0 100644 (file)
@@ -129,7 +129,7 @@ static int __init davinci_vc_probe(struct platform_device *pdev)
        cell->pdata_size = sizeof(*davinci_vc);
 
        ret = mfd_add_devices(&pdev->dev, pdev->id, davinci_vc->cells,
-                             DAVINCI_VC_CELLS, NULL, 0);
+                             DAVINCI_VC_CELLS, NULL, 0, NULL);
        if (ret != 0) {
                dev_err(&pdev->dev, "fail to register client devices\n");
                goto fail4;
index 7040a0081130c93ce6b73145355abec0a8c571b8..0e63cdd9b52abc44666c57994623e120f11644b2 100644 (file)
@@ -3010,7 +3010,7 @@ static int __devinit db8500_prcmu_probe(struct platform_device *pdev)
                prcmu_config_esram0_deep_sleep(ESRAM0_DEEP_SLEEP_STATE_RET);
 
        err = mfd_add_devices(&pdev->dev, 0, db8500_prcmu_devs,
-                       ARRAY_SIZE(db8500_prcmu_devs), NULL, 0);
+                             ARRAY_SIZE(db8500_prcmu_devs), NULL, 0, NULL);
        if (err) {
                pr_err("prcmu: Failed to add subdevices\n");
                return err;
index 04c7093d6499cb88f330b2f768713e49e58c9ffc..9e5453d21a6806263d17bc6ada0c07a3a2a7013a 100644 (file)
@@ -168,7 +168,7 @@ static int __init pasic3_probe(struct platform_device *pdev)
                /* the first 5 PASIC3 registers control the DS1WM */
                ds1wm_resources[0].end = (5 << asic->bus_shift) - 1;
                ret = mfd_add_devices(&pdev->dev, pdev->id,
-                               &ds1wm_cell, 1, r, irq);
+                                     &ds1wm_cell, 1, r, irq, NULL);
                if (ret < 0)
                        dev_warn(dev, "failed to register DS1WM\n");
        }
@@ -176,7 +176,8 @@ static int __init pasic3_probe(struct platform_device *pdev)
        if (pdata && pdata->led_pdata) {
                led_cell.platform_data = pdata->led_pdata;
                led_cell.pdata_size = sizeof(struct pasic3_leds_machinfo);
-               ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r, 0);
+               ret = mfd_add_devices(&pdev->dev, pdev->id, &led_cell, 1, r,
+                                     0, NULL);
                if (ret < 0)
                        dev_warn(dev, "failed to register LED device\n");
        }
index 59df5584cb58f54a25a424ca2551417a231fcb4d..266bdc5bd96d17ea1bc05967d911aa4b9b7fc8bb 100644 (file)
@@ -344,13 +344,13 @@ static int __devinit intel_msic_init_devices(struct intel_msic *msic)
                        continue;
 
                ret = mfd_add_devices(&pdev->dev, -1, &msic_devs[i], 1, NULL,
-                                     pdata->irq[i]);
+                                     pdata->irq[i], NULL);
                if (ret)
                        goto fail;
        }
 
        ret = mfd_add_devices(&pdev->dev, 0, msic_other_devs,
-                             ARRAY_SIZE(msic_other_devs), NULL, 0);
+                             ARRAY_SIZE(msic_other_devs), NULL, 0, NULL);
        if (ret)
                goto fail;
 
index 2ea99989551af85a4796c69e5fc2b65ba7a951e9..965c4801df8a1765e069ecb8707df451984b080a 100644 (file)
@@ -147,7 +147,7 @@ static int __devinit cmodio_probe_submodules(struct cmodio_device *priv)
        }
 
        return mfd_add_devices(&pdev->dev, 0, priv->cells,
-                              num_probed, NULL, pdev->irq);
+                              num_probed, NULL, pdev->irq, NULL);
 }
 
 /*
index 87662a17dec62d527a3af1b8b7fb8c782c85dd92..c6b6d7dda517528081a9e3f7e96d96458846ef67 100644 (file)
@@ -287,7 +287,8 @@ static int __devinit jz4740_adc_probe(struct platform_device *pdev)
        writeb(0xff, adc->base + JZ_REG_ADC_CTRL);
 
        ret = mfd_add_devices(&pdev->dev, 0, jz4740_adc_cells,
-               ARRAY_SIZE(jz4740_adc_cells), mem_base, irq_base);
+                             ARRAY_SIZE(jz4740_adc_cells), mem_base,
+                             irq_base, NULL);
        if (ret < 0)
                goto err_clk_put;
 
index 0b2879b87fd999f537bbfc652da9a29c90eb1042..24212f45b201458961373df48c08d9a1f7f9536d 100644 (file)
@@ -393,7 +393,8 @@ static int __devinit lm3533_device_als_init(struct lm3533 *lm3533)
        lm3533_als_devs[0].platform_data = pdata->als;
        lm3533_als_devs[0].pdata_size = sizeof(*pdata->als);
 
-       ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL, 0);
+       ret = mfd_add_devices(lm3533->dev, 0, lm3533_als_devs, 1, NULL,
+                             0, NULL);
        if (ret) {
                dev_err(lm3533->dev, "failed to add ALS device\n");
                return ret;
@@ -422,7 +423,7 @@ static int __devinit lm3533_device_bl_init(struct lm3533 *lm3533)
        }
 
        ret = mfd_add_devices(lm3533->dev, 0, lm3533_bl_devs,
-                                       pdata->num_backlights, NULL, 0);
+                             pdata->num_backlights, NULL, 0, NULL);
        if (ret) {
                dev_err(lm3533->dev, "failed to add backlight devices\n");
                return ret;
@@ -451,7 +452,7 @@ static int __devinit lm3533_device_led_init(struct lm3533 *lm3533)
        }
 
        ret = mfd_add_devices(lm3533->dev, 0, lm3533_led_devs,
-                                               pdata->num_leds, NULL, 0);
+                             pdata->num_leds, NULL, 0, NULL);
        if (ret) {
                dev_err(lm3533->dev, "failed to add LED devices\n");
                return ret;
index 027cc8f861324de8f10bc7e9a1aa66af9e6ef093..092ad4b44b6d67b9b4ee039fccc73da1748d3a2c 100644 (file)
@@ -750,7 +750,7 @@ gpe0_done:
 
        lpc_ich_finalize_cell(&lpc_ich_cells[LPC_GPIO], id);
        ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_GPIO],
-                               1, NULL, 0);
+                             1, NULL, 0, NULL);
 
 gpio_done:
        if (acpi_conflict)
@@ -765,7 +765,6 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
        u32 base_addr_cfg;
        u32 base_addr;
        int ret;
-       bool acpi_conflict = false;
        struct resource *res;
 
        /* Setup power management base register */
@@ -780,20 +779,11 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
        res = wdt_io_res(ICH_RES_IO_TCO);
        res->start = base_addr + ACPIBASE_TCO_OFF;
        res->end = base_addr + ACPIBASE_TCO_END;
-       ret = acpi_check_resource_conflict(res);
-       if (ret) {
-               acpi_conflict = true;
-               goto wdt_done;
-       }
 
        res = wdt_io_res(ICH_RES_IO_SMI);
        res->start = base_addr + ACPIBASE_SMI_OFF;
        res->end = base_addr + ACPIBASE_SMI_END;
-       ret = acpi_check_resource_conflict(res);
-       if (ret) {
-               acpi_conflict = true;
-               goto wdt_done;
-       }
+
        lpc_ich_enable_acpi_space(dev);
 
        /*
@@ -813,21 +803,13 @@ static int __devinit lpc_ich_init_wdt(struct pci_dev *dev,
                res = wdt_mem_res(ICH_RES_MEM_GCS);
                res->start = base_addr + ACPIBASE_GCS_OFF;
                res->end = base_addr + ACPIBASE_GCS_END;
-               ret = acpi_check_resource_conflict(res);
-               if (ret) {
-                       acpi_conflict = true;
-                       goto wdt_done;
-               }
        }
 
        lpc_ich_finalize_cell(&lpc_ich_cells[LPC_WDT], id);
        ret = mfd_add_devices(&dev->dev, -1, &lpc_ich_cells[LPC_WDT],
-                               1, NULL, 0);
+                             1, NULL, 0, NULL);
 
 wdt_done:
-       if (acpi_conflict)
-               pr_warn("Resource conflict(s) found affecting %s\n",
-                               lpc_ich_cells[LPC_WDT].name);
        return ret;
 }
 
index 9f20abc5e3937065238ff1f3240c27cde9cbb4f6..f6b9c5c96b24f7d68e80b9ca2db8f202c2e3dd91 100644 (file)
@@ -127,7 +127,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
                lpc_sch_cells[i].id = id->device;
 
        ret = mfd_add_devices(&dev->dev, 0,
-                       lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL, 0);
+                             lpc_sch_cells, ARRAY_SIZE(lpc_sch_cells), NULL,
+                             0, NULL);
        if (ret)
                goto out_dev;
 
@@ -153,7 +154,8 @@ static int __devinit lpc_sch_probe(struct pci_dev *dev,
                        tunnelcreek_cells[i].id = id->device;
 
                ret = mfd_add_devices(&dev->dev, 0, tunnelcreek_cells,
-                       ARRAY_SIZE(tunnelcreek_cells), NULL, 0);
+                                     ARRAY_SIZE(tunnelcreek_cells), NULL,
+                                     0, NULL);
        }
 
        return ret;
index c03e12b51924060704641c0152ad6e629d167a72..d9e24c849a00a3f21aad864442293aa2db0ca64d 100644 (file)
@@ -126,7 +126,7 @@ static int max77686_i2c_probe(struct i2c_client *i2c,
        max77686_irq_init(max77686);
 
        ret = mfd_add_devices(max77686->dev, -1, max77686_devs,
-                             ARRAY_SIZE(max77686_devs), NULL, 0);
+                             ARRAY_SIZE(max77686_devs), NULL, 0, NULL);
 
        if (ret < 0)
                goto err_mfd;
index 2b403569e0a6411a92c0e7cb66c7d703d60cc0cf..1029d018c73921828f34740b4034c0cd7df5c3bd 100644 (file)
@@ -137,6 +137,9 @@ static void max77693_irq_mask(struct irq_data *data)
        const struct max77693_irq_data *irq_data =
                                irq_to_max77693_irq(max77693, data->irq);
 
+       if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
+               return;
+
        if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
                max77693->irq_masks_cur[irq_data->group] &= ~irq_data->mask;
        else
@@ -149,6 +152,9 @@ static void max77693_irq_unmask(struct irq_data *data)
        const struct max77693_irq_data *irq_data =
            irq_to_max77693_irq(max77693, data->irq);
 
+       if (irq_data->group >= MAX77693_IRQ_GROUP_NR)
+               return;
+
        if (irq_data->group >= MUIC_INT1 && irq_data->group <= MUIC_INT3)
                max77693->irq_masks_cur[irq_data->group] |= irq_data->mask;
        else
@@ -200,7 +206,7 @@ static irqreturn_t max77693_irq_thread(int irq, void *data)
 
        if (irq_src & MAX77693_IRQSRC_MUIC)
                /* MUIC INT1 ~ INT3 */
-               max77693_bulk_read(max77693->regmap, MAX77693_MUIC_REG_INT1,
+               max77693_bulk_read(max77693->regmap_muic, MAX77693_MUIC_REG_INT1,
                        MAX77693_NUM_IRQ_MUIC_REGS, &irq_reg[MUIC_INT1]);
 
        /* Apply masking */
@@ -255,7 +261,8 @@ int max77693_irq_init(struct max77693_dev *max77693)
 {
        struct irq_domain *domain;
        int i;
-       int ret;
+       int ret = 0;
+       u8 intsrc_mask;
 
        mutex_init(&max77693->irqlock);
 
@@ -287,19 +294,38 @@ int max77693_irq_init(struct max77693_dev *max77693)
                                        &max77693_irq_domain_ops, max77693);
        if (!domain) {
                dev_err(max77693->dev, "could not create irq domain\n");
-               return -ENODEV;
+               ret = -ENODEV;
+               goto err_irq;
        }
        max77693->irq_domain = domain;
 
+       /* Unmask max77693 interrupt */
+       ret = max77693_read_reg(max77693->regmap,
+                       MAX77693_PMIC_REG_INTSRC_MASK, &intsrc_mask);
+       if (ret < 0) {
+               dev_err(max77693->dev, "fail to read PMIC register\n");
+               goto err_irq;
+       }
+
+       intsrc_mask &= ~(MAX77693_IRQSRC_CHG);
+       intsrc_mask &= ~(MAX77693_IRQSRC_FLASH);
+       intsrc_mask &= ~(MAX77693_IRQSRC_MUIC);
+       ret = max77693_write_reg(max77693->regmap,
+                       MAX77693_PMIC_REG_INTSRC_MASK, intsrc_mask);
+       if (ret < 0) {
+               dev_err(max77693->dev, "fail to write PMIC register\n");
+               goto err_irq;
+       }
+
        ret = request_threaded_irq(max77693->irq, NULL, max77693_irq_thread,
                                   IRQF_TRIGGER_FALLING | IRQF_ONESHOT,
                                   "max77693-irq", max77693);
-
        if (ret)
                dev_err(max77693->dev, "Failed to request IRQ %d: %d\n",
                        max77693->irq, ret);
 
-       return 0;
+err_irq:
+       return ret;
 }
 
 void max77693_irq_exit(struct max77693_dev *max77693)
index a1811cb50ec75fc7c1dffd02aca98f132d7e4810..cc5155e20494726c2ae6954e64128f61973ebafd 100644 (file)
@@ -152,6 +152,20 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
        max77693->haptic = i2c_new_dummy(i2c->adapter, I2C_ADDR_HAPTIC);
        i2c_set_clientdata(max77693->haptic, max77693);
 
+       /*
+        * Initialize register map for MUIC device because use regmap-muic
+        * instance of MUIC device when irq of max77693 is initialized
+        * before call max77693-muic probe() function.
+        */
+       max77693->regmap_muic = devm_regmap_init_i2c(max77693->muic,
+                                        &max77693_regmap_config);
+       if (IS_ERR(max77693->regmap_muic)) {
+               ret = PTR_ERR(max77693->regmap_muic);
+               dev_err(max77693->dev,
+                       "failed to allocate register map: %d\n", ret);
+               goto err_regmap;
+       }
+
        ret = max77693_irq_init(max77693);
        if (ret < 0)
                goto err_irq;
@@ -159,7 +173,7 @@ static int max77693_i2c_probe(struct i2c_client *i2c,
        pm_runtime_set_active(max77693->dev);
 
        ret = mfd_add_devices(max77693->dev, -1, max77693_devs,
-                       ARRAY_SIZE(max77693_devs), NULL, 0);
+                             ARRAY_SIZE(max77693_devs), NULL, 0, NULL);
        if (ret < 0)
                goto err_mfd;
 
index 825a7f06d9ba5ade6281810bec19c209187561b2..ee53757beca7e8344c15a66bbe5d51bcce7b9da1 100644 (file)
@@ -598,7 +598,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
 
        ret = mfd_add_devices(chip->dev, 0, &rtc_devs[0],
                              ARRAY_SIZE(rtc_devs),
-                             &rtc_resources[0], chip->irq_base);
+                             &rtc_resources[0], chip->irq_base, NULL);
        if (ret < 0) {
                dev_err(chip->dev, "Failed to add rtc subdev\n");
                goto out;
@@ -606,7 +606,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
 
        ret = mfd_add_devices(chip->dev, 0, &onkey_devs[0],
                              ARRAY_SIZE(onkey_devs),
-                             &onkey_resources[0], 0);
+                             &onkey_resources[0], 0, NULL);
        if (ret < 0) {
                dev_err(chip->dev, "Failed to add onkey subdev\n");
                goto out_dev;
@@ -615,7 +615,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
        if (pdata) {
                ret = mfd_add_devices(chip->dev, 0, &regulator_devs[0],
                                      ARRAY_SIZE(regulator_devs),
-                                     &regulator_resources[0], 0);
+                                     &regulator_resources[0], 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add regulator subdev\n");
                        goto out_dev;
@@ -625,7 +625,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
        if (pdata && pdata->backlight) {
                ret = mfd_add_devices(chip->dev, 0, &backlight_devs[0],
                                      ARRAY_SIZE(backlight_devs),
-                                     &backlight_resources[0], 0);
+                                     &backlight_resources[0], 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add backlight subdev\n");
                        goto out_dev;
@@ -635,7 +635,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
        if (pdata && pdata->power) {
                ret = mfd_add_devices(chip->dev, 0, &power_devs[0],
                                        ARRAY_SIZE(power_devs),
-                                       &power_supply_resources[0], 0);
+                                     &power_supply_resources[0], 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add power supply "
                                "subdev\n");
@@ -646,7 +646,7 @@ int __devinit max8925_device_init(struct max8925_chip *chip,
        if (pdata && pdata->touch) {
                ret = mfd_add_devices(chip->dev, 0, &touch_devs[0],
                                      ARRAY_SIZE(touch_devs),
-                                     &touch_resources[0], 0);
+                                     &touch_resources[0], 0, NULL);
                if (ret < 0) {
                        dev_err(chip->dev, "Failed to add touch subdev\n");
                        goto out_dev;
index 10b629c245b6770d304dde9bf978891c2a5ac800..f123517065ec911ff6e4154aa25a3f8e1dd0bd98 100644 (file)
@@ -160,7 +160,7 @@ static int max8997_i2c_probe(struct i2c_client *i2c,
 
        mfd_add_devices(max8997->dev, -1, max8997_devs,
                        ARRAY_SIZE(max8997_devs),
-                       NULL, 0);
+                       NULL, 0, NULL);
 
        /*
         * TODO: enable others (flash, muic, rtc, battery, ...) and
index 6ef56d28c05686bf298f589cebf91c43fcc707b8..d7218cc90945a643ee03cc670852d42078131503 100644 (file)
@@ -161,13 +161,13 @@ static int max8998_i2c_probe(struct i2c_client *i2c,
        switch (id->driver_data) {
        case TYPE_LP3974:
                ret = mfd_add_devices(max8998->dev, -1,
-                               lp3974_devs, ARRAY_SIZE(lp3974_devs),
-                               NULL, 0);
+                                     lp3974_devs, ARRAY_SIZE(lp3974_devs),
+                                     NULL, 0, NULL);
                break;
        case TYPE_MAX8998:
                ret = mfd_add_devices(max8998->dev, -1,
-                               max8998_devs, ARRAY_SIZE(max8998_devs),
-                               NULL, 0);
+                                     max8998_devs, ARRAY_SIZE(max8998_devs),
+                                     NULL, 0, NULL);
                break;
        default:
                ret = -EINVAL;
index b801dc72f041a125fcf9a52e25e6d594ee052d92..1ec79b54bd2f12f304c57f92633cc8c125a0d389 100644 (file)
@@ -612,7 +612,7 @@ static int mc13xxx_add_subdevice_pdata(struct mc13xxx *mc13xxx,
        if (!cell.name)
                return -ENOMEM;
 
-       return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0);
+       return mfd_add_devices(mc13xxx->dev, -1, &cell, 1, NULL, 0, NULL);
 }
 
 static int mc13xxx_add_subdevice(struct mc13xxx *mc13xxx, const char *format)
index 0c3a01cde2f7615960fb2c9cc20ba7489bf00fbd..f8b77711ad2da4c26acade369d0bc6443631427b 100644 (file)
@@ -74,12 +74,11 @@ static int mfd_platform_add_cell(struct platform_device *pdev,
 static int mfd_add_device(struct device *parent, int id,
                          const struct mfd_cell *cell,
                          struct resource *mem_base,
-                         int irq_base)
+                         int irq_base, struct irq_domain *domain)
 {
        struct resource *res;
        struct platform_device *pdev;
        struct device_node *np = NULL;
-       struct irq_domain *domain = NULL;
        int ret = -ENOMEM;
        int r;
 
@@ -97,7 +96,6 @@ static int mfd_add_device(struct device *parent, int id,
                for_each_child_of_node(parent->of_node, np) {
                        if (of_device_is_compatible(np, cell->of_compatible)) {
                                pdev->dev.of_node = np;
-                               domain = irq_find_host(parent->of_node);
                                break;
                        }
                }
@@ -177,7 +175,7 @@ fail_alloc:
 int mfd_add_devices(struct device *parent, int id,
                    struct mfd_cell *cells, int n_devs,
                    struct resource *mem_base,
-                   int irq_base)
+                   int irq_base, struct irq_domain *domain)
 {
        int i;
        int ret = 0;
@@ -191,7 +189,8 @@ int mfd_add_devices(struct device *parent, int id,
        for (i = 0; i < n_devs; i++) {
                atomic_set(&cnts[i], 0);
                cells[i].usage_count = &cnts[i];
-               ret = mfd_add_device(parent, id, cells + i, mem_base, irq_base);
+               ret = mfd_add_device(parent, id, cells + i, mem_base,
+                                    irq_base, domain);
                if (ret)
                        break;
        }
@@ -247,7 +246,8 @@ int mfd_clone_cell(const char *cell, const char **clones, size_t n_clones)
        for (i = 0; i < n_clones; i++) {
                cell_entry.name = clones[i];
                /* don't give up if a single call fails; just report error */
-               if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0))
+               if (mfd_add_device(pdev->dev.parent, -1, &cell_entry, NULL, 0,
+                                  NULL))
                        dev_err(dev, "failed to create platform device '%s'\n",
                                        clones[i]);
        }
index c4a69f193a1df1985abfbaeeffb8e39cda933493..a345f9bb7b4758765725cf2c056303950ecc1c02 100644 (file)
@@ -453,7 +453,8 @@ static int __devinit palmas_i2c_probe(struct i2c_client *i2c,
 
        ret = mfd_add_devices(palmas->dev, -1,
                              children, ARRAY_SIZE(palmas_children),
-                             NULL, regmap_irq_chip_get_base(palmas->irq_data));
+                             NULL, regmap_irq_chip_get_base(palmas->irq_data),
+                             NULL);
        kfree(children);
 
        if (ret < 0)
index cdc1df7fa0e94d10a26059c18dd347c045dcf2cd..3a8fa88567b18385461fbed0bbc9ff30e8d0fffc 100644 (file)
@@ -289,7 +289,7 @@ static int __devinit rc5t583_i2c_probe(struct i2c_client *i2c,
        }
 
        ret = mfd_add_devices(rc5t583->dev, -1, rc5t583_subdevs,
-                       ARRAY_SIZE(rc5t583_subdevs), NULL, 0);
+                             ARRAY_SIZE(rc5t583_subdevs), NULL, 0, NULL);
        if (ret) {
                dev_err(&i2c->dev, "add mfd devices failed: %d\n", ret);
                goto err_add_devs;
index 685d61e431adfa4f8b733a13bd5c93cfb71c9a44..0f70dce611605fb5e92419c5ac393c2079b74833 100644 (file)
@@ -87,7 +87,8 @@ static int __devinit rdc321x_sb_probe(struct pci_dev *pdev,
        rdc321x_wdt_pdata.sb_pdev = pdev;
 
        return mfd_add_devices(&pdev->dev, -1,
-               rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells), NULL, 0);
+                              rdc321x_sb_cells, ARRAY_SIZE(rdc321x_sb_cells),
+                              NULL, 0, NULL);
 }
 
 static void __devexit rdc321x_sb_remove(struct pci_dev *pdev)
index 2988efde11ebc60b6a714044f79d6a7cd9a44dba..49d361a618d06f5f26d17c49a8c9d48e20547caf 100644 (file)
@@ -141,19 +141,19 @@ static int sec_pmic_probe(struct i2c_client *i2c,
        switch (sec_pmic->device_type) {
        case S5M8751X:
                ret = mfd_add_devices(sec_pmic->dev, -1, s5m8751_devs,
-                                       ARRAY_SIZE(s5m8751_devs), NULL, 0);
+                                     ARRAY_SIZE(s5m8751_devs), NULL, 0, NULL);
                break;
        case S5M8763X:
                ret = mfd_add_devices(sec_pmic->dev, -1, s5m8763_devs,
-                                       ARRAY_SIZE(s5m8763_devs), NULL, 0);
+                                     ARRAY_SIZE(s5m8763_devs), NULL, 0, NULL);
                break;
        case S5M8767X:
                ret = mfd_add_devices(sec_pmic->dev, -1, s5m8767_devs,
-                                       ARRAY_SIZE(s5m8767_devs), NULL, 0);
+                                     ARRAY_SIZE(s5m8767_devs), NULL, 0, NULL);
                break;
        case S2MPS11X:
                ret = mfd_add_devices(sec_pmic->dev, -1, s2mps11_devs,
-                                       ARRAY_SIZE(s2mps11_devs), NULL, 0);
+                                     ARRAY_SIZE(s2mps11_devs), NULL, 0, NULL);
                break;
        default:
                /* If this happens the probe function is problem */
index d31fed07aefbc51bfb620c492a2f05197886eb36..d35da6820beae8ee2c7e01e1faf51cc48c96972b 100644 (file)
@@ -407,7 +407,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
                              sta2x11_mfd_bar0,
                              ARRAY_SIZE(sta2x11_mfd_bar0),
                              &pdev->resource[0],
-                             0);
+                             0, NULL);
        if (err) {
                dev_err(&pdev->dev, "mfd_add_devices[0] failed: %d\n", err);
                goto err_disable;
@@ -417,7 +417,7 @@ static int __devinit sta2x11_mfd_probe(struct pci_dev *pdev,
                              sta2x11_mfd_bar1,
                              ARRAY_SIZE(sta2x11_mfd_bar1),
                              &pdev->resource[1],
-                             0);
+                             0, NULL);
        if (err) {
                dev_err(&pdev->dev, "mfd_add_devices[1] failed: %d\n", err);
                goto err_disable;
index 2dd8d49cb30bc7d63d14250e673b2c12eb4cef3f..c94f521f392cb0b5214385ff57ac6e18e8762907 100644 (file)
@@ -962,7 +962,7 @@ static int __devinit stmpe_add_device(struct stmpe *stmpe,
                                      struct mfd_cell *cell, int irq)
 {
        return mfd_add_devices(stmpe->dev, stmpe->pdata->id, cell, 1,
-                              NULL, stmpe->irq_base + irq);
+                              NULL, stmpe->irq_base + irq, NULL);
 }
 
 static int __devinit stmpe_devices_init(struct stmpe *stmpe)
index 2d9e8799e733c6644c18aa9335e9796ef0c0709f..b32940ec903425d37010b79eed9a16e4b3c20761 100644 (file)
@@ -388,7 +388,7 @@ static int t7l66xb_probe(struct platform_device *dev)
 
        ret = mfd_add_devices(&dev->dev, dev->id,
                              t7l66xb_cells, ARRAY_SIZE(t7l66xb_cells),
-                             iomem, t7l66xb->irq_base);
+                             iomem, t7l66xb->irq_base, NULL);
 
        if (!ret)
                return 0;
index 048bf0532a095014e03358b01af1f4cd58585b97..b56ba6b43294b77e536b12247c0e8b1d18085701 100644 (file)
@@ -262,8 +262,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
 
        if (blocks & TC3589x_BLOCK_GPIO) {
                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_gpio,
-                               ARRAY_SIZE(tc3589x_dev_gpio), NULL,
-                               tc3589x->irq_base);
+                                     ARRAY_SIZE(tc3589x_dev_gpio), NULL,
+                                     tc3589x->irq_base, NULL);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to add gpio child\n");
                        return ret;
@@ -273,8 +273,8 @@ static int __devinit tc3589x_device_init(struct tc3589x *tc3589x)
 
        if (blocks & TC3589x_BLOCK_KEYPAD) {
                ret = mfd_add_devices(tc3589x->dev, -1, tc3589x_dev_keypad,
-                               ARRAY_SIZE(tc3589x_dev_keypad), NULL,
-                               tc3589x->irq_base);
+                                     ARRAY_SIZE(tc3589x_dev_keypad), NULL,
+                                     tc3589x->irq_base, NULL);
                if (ret) {
                        dev_err(tc3589x->dev, "failed to keypad child\n");
                        return ret;
index d20a284ad4baca528c36eb351200ff16fdd5282e..413c891102f867d32b3bd62b25bb02120fe0159e 100644 (file)
@@ -192,7 +192,7 @@ static int __devinit tc6387xb_probe(struct platform_device *dev)
        printk(KERN_INFO "Toshiba tc6387xb initialised\n");
 
        ret = mfd_add_devices(&dev->dev, dev->id, tc6387xb_cells,
-                             ARRAY_SIZE(tc6387xb_cells), iomem, irq);
+                             ARRAY_SIZE(tc6387xb_cells), iomem, irq, NULL);
 
        if (!ret)
                return 0;
index 9612264f0e6dcf7832ebf2f4736815b4eabc6a4b..dcab026fcbb25070a7c79c8e2601b3b911079367 100644 (file)
@@ -700,8 +700,8 @@ static int __devinit tc6393xb_probe(struct platform_device *dev)
        tc6393xb_cells[TC6393XB_CELL_FB].pdata_size = sizeof(*tcpd->fb_data);
 
        ret = mfd_add_devices(&dev->dev, dev->id,
-                       tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
-                       iomem, tcpd->irq_base);
+                             tc6393xb_cells, ARRAY_SIZE(tc6393xb_cells),
+                             iomem, tcpd->irq_base, NULL);
 
        if (!ret)
                return 0;
index 4fb0e6c8e8fe0fbfee94299b7c0de45920621a25..7c3675a74f93414c806543f4c50bc44cbb8ad46f 100644 (file)
@@ -412,7 +412,7 @@ static int __devinit ti_ssp_probe(struct platform_device *pdev)
                cells[id].data_size     = data->pdata_size;
        }
 
-       error = mfd_add_devices(dev, 0, cells, 2, NULL, 0);
+       error = mfd_add_devices(dev, 0, cells, 2, NULL, 0, NULL);
        if (error < 0) {
                dev_err(dev, "cannot add mfd cells\n");
                goto error_enable;
index a447f4ec11fb757ee38755aa44da467f83229d1f..cccc626c83c80c2bf79cf03c89936d5249a44714 100644 (file)
@@ -757,25 +757,25 @@ static int __devinit timb_probe(struct pci_dev *dev,
                err = mfd_add_devices(&dev->dev, -1,
                        timberdale_cells_bar0_cfg0,
                        ARRAY_SIZE(timberdale_cells_bar0_cfg0),
-                       &dev->resource[0], msix_entries[0].vector);
+                       &dev->resource[0], msix_entries[0].vector, NULL);
                break;
        case TIMB_HW_VER1:
                err = mfd_add_devices(&dev->dev, -1,
                        timberdale_cells_bar0_cfg1,
                        ARRAY_SIZE(timberdale_cells_bar0_cfg1),
-                       &dev->resource[0], msix_entries[0].vector);
+                       &dev->resource[0], msix_entries[0].vector, NULL);
                break;
        case TIMB_HW_VER2:
                err = mfd_add_devices(&dev->dev, -1,
                        timberdale_cells_bar0_cfg2,
                        ARRAY_SIZE(timberdale_cells_bar0_cfg2),
-                       &dev->resource[0], msix_entries[0].vector);
+                       &dev->resource[0], msix_entries[0].vector, NULL);
                break;
        case TIMB_HW_VER3:
                err = mfd_add_devices(&dev->dev, -1,
                        timberdale_cells_bar0_cfg3,
                        ARRAY_SIZE(timberdale_cells_bar0_cfg3),
-                       &dev->resource[0], msix_entries[0].vector);
+                       &dev->resource[0], msix_entries[0].vector, NULL);
                break;
        default:
                dev_err(&dev->dev, "Uknown IP setup: %d.%d.%d\n",
@@ -792,7 +792,7 @@ static int __devinit timb_probe(struct pci_dev *dev,
 
        err = mfd_add_devices(&dev->dev, 0,
                timberdale_cells_bar1, ARRAY_SIZE(timberdale_cells_bar1),
-               &dev->resource[1], msix_entries[0].vector);
+               &dev->resource[1], msix_entries[0].vector, NULL);
        if (err) {
                dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
                goto err_mfd2;
@@ -803,7 +803,7 @@ static int __devinit timb_probe(struct pci_dev *dev,
                ((priv->fw.config & TIMB_HW_VER_MASK) == TIMB_HW_VER3)) {
                err = mfd_add_devices(&dev->dev, 1, timberdale_cells_bar2,
                        ARRAY_SIZE(timberdale_cells_bar2),
-                       &dev->resource[2], msix_entries[0].vector);
+                       &dev->resource[2], msix_entries[0].vector, NULL);
                if (err) {
                        dev_err(&dev->dev, "mfd_add_devices failed: %d\n", err);
                        goto err_mfd2;
index a293b978e27ce19b116025e3ab4e87be6ae0dd74..14051bdc714b80197f258c14afd9cf629667e765 100644 (file)
@@ -188,7 +188,7 @@ static int __devinit tps6105x_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(&client->dev, 0, tps6105x_cells,
-               ARRAY_SIZE(tps6105x_cells), NULL, 0);
+                             ARRAY_SIZE(tps6105x_cells), NULL, 0, NULL);
        if (ret)
                goto fail;
 
index 33ba7723c967435b67c49a6f3f78212a63204b4e..1b203499c74402c59c19bf29a8ce6aa7b51a058b 100644 (file)
@@ -100,7 +100,7 @@ static int tps6507x_i2c_probe(struct i2c_client *i2c,
 
        ret = mfd_add_devices(tps6507x->dev, -1,
                              tps6507x_devs, ARRAY_SIZE(tps6507x_devs),
-                             NULL, 0);
+                             NULL, 0, NULL);
 
        if (ret < 0)
                goto err;
index 80e24f4b47bffce67679b7e637627e9e7c769466..50fd87c87a1cca64e21104401c1adbff1b4cf45c 100644 (file)
@@ -292,7 +292,7 @@ static int __devinit tps65090_i2c_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(tps65090->dev, -1, tps65090s,
-               ARRAY_SIZE(tps65090s), NULL, 0);
+                             ARRAY_SIZE(tps65090s), NULL, 0, NULL);
        if (ret) {
                dev_err(&client->dev, "add mfd devices failed with err: %d\n",
                        ret);
index 61c097a98f5de7eb45fd0ccb8fdc44dd53c869fa..a95e9421b73580df95402f718a4166898a1c41dd 100644 (file)
 #include <linux/slab.h>
 #include <linux/regmap.h>
 #include <linux/err.h>
-#include <linux/regulator/of_regulator.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
 
 #include <linux/mfd/core.h>
 #include <linux/mfd/tps65217.h>
 
+static struct mfd_cell tps65217s[] = {
+       {
+               .name = "tps65217-pmic",
+       },
+};
+
 /**
  * tps65217_reg_read: Read a single tps65217 register.
  *
@@ -133,83 +140,48 @@ int tps65217_clear_bits(struct tps65217 *tps, unsigned int reg,
 }
 EXPORT_SYMBOL_GPL(tps65217_clear_bits);
 
-#ifdef CONFIG_OF
-static struct of_regulator_match reg_matches[] = {
-       { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
-       { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
-       { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
-       { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
-       { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
-       { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
-       { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
-};
-
-static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
-{
-       struct device_node *node = client->dev.of_node;
-       struct tps65217_board *pdata;
-       struct device_node *regs;
-       int count = ARRAY_SIZE(reg_matches);
-       int ret, i;
-
-       regs = of_find_node_by_name(node, "regulators");
-       if (!regs)
-               return NULL;
-
-       ret = of_regulator_match(&client->dev, regs, reg_matches, count);
-       of_node_put(regs);
-       if ((ret < 0) || (ret > count))
-               return NULL;
-
-       count = ret;
-       pdata = devm_kzalloc(&client->dev, count * sizeof(*pdata), GFP_KERNEL);
-       if (!pdata)
-               return NULL;
-
-       for (i = 0; i < count; i++) {
-               if (!reg_matches[i].init_data || !reg_matches[i].of_node)
-                       continue;
-
-               pdata->tps65217_init_data[i] = reg_matches[i].init_data;
-               pdata->of_node[i] = reg_matches[i].of_node;
-       }
-
-       return pdata;
-}
-
-static struct of_device_id tps65217_of_match[] = {
-       { .compatible = "ti,tps65217", },
-       { },
-};
-#else
-static struct tps65217_board *tps65217_parse_dt(struct i2c_client *client)
-{
-       return NULL;
-}
-#endif
-
 static struct regmap_config tps65217_regmap_config = {
        .reg_bits = 8,
        .val_bits = 8,
 };
 
+static const struct of_device_id tps65217_of_match[] = {
+       { .compatible = "ti,tps65217", .data = (void *)TPS65217 },
+       { /* sentinel */ },
+};
+
 static int __devinit tps65217_probe(struct i2c_client *client,
                                const struct i2c_device_id *ids)
 {
        struct tps65217 *tps;
-       struct regulator_init_data *reg_data;
-       struct tps65217_board *pdata = client->dev.platform_data;
-       int i, ret;
        unsigned int version;
+       unsigned int chip_id = ids->driver_data;
+       const struct of_device_id *match;
+       int ret;
 
-       if (!pdata && client->dev.of_node)
-               pdata = tps65217_parse_dt(client);
+       if (client->dev.of_node) {
+               match = of_match_device(tps65217_of_match, &client->dev);
+               if (!match) {
+                       dev_err(&client->dev,
+                               "Failed to find matching dt id\n");
+                       return -EINVAL;
+               }
+               chip_id = (unsigned int)match->data;
+       }
+
+       if (!chip_id) {
+               dev_err(&client->dev, "id is null.\n");
+               return -ENODEV;
+       }
 
        tps = devm_kzalloc(&client->dev, sizeof(*tps), GFP_KERNEL);
        if (!tps)
                return -ENOMEM;
 
-       tps->pdata = pdata;
+       i2c_set_clientdata(client, tps);
+       tps->dev = &client->dev;
+       tps->id = chip_id;
+
        tps->regmap = devm_regmap_init_i2c(client, &tps65217_regmap_config);
        if (IS_ERR(tps->regmap)) {
                ret = PTR_ERR(tps->regmap);
@@ -218,8 +190,12 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                return ret;
        }
 
-       i2c_set_clientdata(client, tps);
-       tps->dev = &client->dev;
+       ret = mfd_add_devices(tps->dev, -1, tps65217s,
+                             ARRAY_SIZE(tps65217s), NULL, 0, NULL);
+       if (ret < 0) {
+               dev_err(tps->dev, "mfd_add_devices failed: %d\n", ret);
+               return ret;
+       }
 
        ret = tps65217_reg_read(tps, TPS65217_REG_CHIPID, &version);
        if (ret < 0) {
@@ -232,41 +208,21 @@ static int __devinit tps65217_probe(struct i2c_client *client,
                        (version & TPS65217_CHIPID_CHIP_MASK) >> 4,
                        version & TPS65217_CHIPID_REV_MASK);
 
-       for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
-               struct platform_device *pdev;
-
-               pdev = platform_device_alloc("tps65217-pmic", i);
-               if (!pdev) {
-                       dev_err(tps->dev, "Cannot create regulator %d\n", i);
-                       continue;
-               }
-
-               pdev->dev.parent = tps->dev;
-               pdev->dev.of_node = pdata->of_node[i];
-               reg_data = pdata->tps65217_init_data[i];
-               platform_device_add_data(pdev, reg_data, sizeof(*reg_data));
-               tps->regulator_pdev[i] = pdev;
-
-               platform_device_add(pdev);
-       }
-
        return 0;
 }
 
 static int __devexit tps65217_remove(struct i2c_client *client)
 {
        struct tps65217 *tps = i2c_get_clientdata(client);
-       int i;
 
-       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
-               platform_device_unregister(tps->regulator_pdev[i]);
+       mfd_remove_devices(tps->dev);
 
        return 0;
 }
 
 static const struct i2c_device_id tps65217_id_table[] = {
-       {"tps65217", 0xF0},
-       {/* end of list */}
+       {"tps65217", TPS65217},
+       { /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(i2c, tps65217_id_table);
 
index 353c34812120fc46e37140c0b6a04babdd5cb080..5f58370ccf5502b1d6a729f2daa0db411a6e3e1d 100644 (file)
@@ -493,7 +493,8 @@ static int __devinit tps6586x_i2c_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(tps6586x->dev, -1,
-                       tps6586x_cell, ARRAY_SIZE(tps6586x_cell), NULL, 0);
+                             tps6586x_cell, ARRAY_SIZE(tps6586x_cell),
+                             NULL, 0, NULL);
        if (ret < 0) {
                dev_err(&client->dev, "mfd_add_devices failed: %d\n", ret);
                goto err_mfd_add;
index 1c563792c777ba8f04c194a2a99c39159d8871f7..d3ce4d569deb57c2b707dc73d6cb7cf600962cab 100644 (file)
@@ -254,7 +254,7 @@ static __devinit int tps65910_i2c_probe(struct i2c_client *i2c,
 
        ret = mfd_add_devices(tps65910->dev, -1,
                              tps65910s, ARRAY_SIZE(tps65910s),
-                             NULL, 0);
+                             NULL, 0, NULL);
        if (ret < 0) {
                dev_err(&i2c->dev, "mfd_add_devices failed: %d\n", ret);
                return ret;
index 74fd8cb5f37224e576f58398c20fda9f4884d9e7..4658b5bdcd84488d3379a2ef4f33e334eb96ea2f 100644 (file)
@@ -146,7 +146,7 @@ int tps65912_device_init(struct tps65912 *tps65912)
 
        ret = mfd_add_devices(tps65912->dev, -1,
                              tps65912s, ARRAY_SIZE(tps65912s),
-                             NULL, 0);
+                             NULL, 0, NULL);
        if (ret < 0)
                goto err;
 
index 838ce4eb444e24ce44bd3b120fe21a9f977d6e75..77c9acb145831c5b03fd04cbc08d0f6e0bfd47ec 100644 (file)
@@ -223,7 +223,7 @@ static int __devinit twl4030_audio_probe(struct platform_device *pdev)
 
        if (childs)
                ret = mfd_add_devices(&pdev->dev, pdev->id, audio->cells,
-                                     childs, NULL, 0);
+                                     childs, NULL, 0, NULL);
        else {
                dev_err(&pdev->dev, "No platform data found for childs\n");
                ret = -ENODEV;
index b0fad0ffca560b0714a9574b42d4c87c89ea3e4d..3dca5c195a200505c3796c488b34b65f8a32b7e6 100644 (file)
@@ -632,7 +632,7 @@ static int __devinit twl6040_probe(struct i2c_client *client,
        }
 
        ret = mfd_add_devices(&client->dev, -1, twl6040->cells, children,
-                             NULL, 0);
+                             NULL, 0, NULL);
        if (ret)
                goto mfd_err;
 
index 872aff21e4be6fa682eb01aad72b04492efd622e..b9a636d44c7f95979adcd17172e9d7803fa5d5fe 100644 (file)
@@ -102,7 +102,7 @@ static __devinit int vx855_probe(struct pci_dev *pdev,
        vx855_gpio_resources[1].end = vx855_gpio_resources[1].start + 3;
 
        ret = mfd_add_devices(&pdev->dev, -1, vx855_cells, ARRAY_SIZE(vx855_cells),
-                       NULL, 0);
+                       NULL, 0, NULL);
 
        /* we always return -ENODEV here in order to enable other
         * drivers like old, not-yet-platform_device ported i2c-viapro */
index f39b756df561dcfd5fee7fa310222bb27748d708..86e0e4309fc274e41ec73a20dc1fb675e06fb0fc 100644 (file)
@@ -241,7 +241,7 @@ static int __devinit wl1273_core_probe(struct i2c_client *client,
                __func__, children);
 
        r = mfd_add_devices(&client->dev, -1, core->cells,
-                           children, NULL, 0);
+                           children, NULL, 0, NULL);
        if (r)
                goto err;
 
index 946698fd2dc6a4dc9b3a7868bc7f44c920a46201..3017310359403248719495fe39692698271ba7ed 100644 (file)
@@ -1813,27 +1813,27 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        case WM8310:
                ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8310_devs, ARRAY_SIZE(wm8310_devs),
-                                     NULL, 0);
+                                     NULL, 0, NULL);
                break;
 
        case WM8311:
                ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8311_devs, ARRAY_SIZE(wm8311_devs),
-                                     NULL, 0);
+                                     NULL, 0, NULL);
                if (!pdata || !pdata->disable_touch)
                        mfd_add_devices(wm831x->dev, wm831x_num,
                                        touch_devs, ARRAY_SIZE(touch_devs),
-                                       NULL, 0);
+                                       NULL, 0, NULL);
                break;
 
        case WM8312:
                ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8312_devs, ARRAY_SIZE(wm8312_devs),
-                                     NULL, 0);
+                                     NULL, 0, NULL);
                if (!pdata || !pdata->disable_touch)
                        mfd_add_devices(wm831x->dev, wm831x_num,
                                        touch_devs, ARRAY_SIZE(touch_devs),
-                                       NULL, 0);
+                                       NULL, 0, NULL);
                break;
 
        case WM8320:
@@ -1842,7 +1842,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        case WM8326:
                ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      wm8320_devs, ARRAY_SIZE(wm8320_devs),
-                                     NULL, 0);
+                                     NULL, 0, NULL);
                break;
 
        default:
@@ -1867,7 +1867,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
        if (ret & WM831X_XTAL_ENA) {
                ret = mfd_add_devices(wm831x->dev, wm831x_num,
                                      rtc_devs, ARRAY_SIZE(rtc_devs),
-                                     NULL, 0);
+                                     NULL, 0, NULL);
                if (ret != 0) {
                        dev_err(wm831x->dev, "Failed to add RTC: %d\n", ret);
                        goto err_irq;
@@ -1880,7 +1880,7 @@ int wm831x_device_init(struct wm831x *wm831x, unsigned long id, int irq)
                /* Treat errors as non-critical */
                ret = mfd_add_devices(wm831x->dev, wm831x_num, backlight_devs,
                                      ARRAY_SIZE(backlight_devs), NULL,
-                                     0);
+                                     0, NULL);
                if (ret < 0)
                        dev_err(wm831x->dev, "Failed to add backlight: %d\n",
                                ret);
index 4b7d378551d58daf515532dbcaea2c6f35c17f1e..639ca359242f849cebfe407333e6107c0bca4bbb 100644 (file)
@@ -70,7 +70,7 @@ static int wm8400_register_codec(struct wm8400 *wm8400)
                .pdata_size = sizeof(*wm8400),
        };
 
-       return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0);
+       return mfd_add_devices(wm8400->dev, -1, &cell, 1, NULL, 0, NULL);
 }
 
 /*
index eec74aa55fdfe28c46476c3360e1632bfd51cf7f..2febf88cfce8847383be5a4fe8ab80ae89fe48e2 100644 (file)
@@ -414,7 +414,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
        ret = mfd_add_devices(wm8994->dev, -1,
                              wm8994_regulator_devs,
                              ARRAY_SIZE(wm8994_regulator_devs),
-                             NULL, 0);
+                             NULL, 0, NULL);
        if (ret != 0) {
                dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
                goto err;
@@ -648,7 +648,7 @@ static __devinit int wm8994_device_init(struct wm8994 *wm8994, int irq)
 
        ret = mfd_add_devices(wm8994->dev, -1,
                              wm8994_devs, ARRAY_SIZE(wm8994_devs),
-                             NULL, 0);
+                             NULL, 0, NULL);
        if (ret != 0) {
                dev_err(wm8994->dev, "Failed to add children: %d\n", ret);
                goto err_irq;
index f1c84decb192638e02aa13488e58c855d7335704..172a768036d87d700c018d36cdfdf9dc7093ae4d 100644 (file)
@@ -1411,7 +1411,8 @@ static int mmc_blk_issue_rq(struct mmc_queue *mq, struct request *req)
                /* complete ongoing async transfer before issuing discard */
                if (card->host->areq)
                        mmc_blk_issue_rw_rq(mq, NULL);
-               if (req->cmd_flags & REQ_SECURE)
+               if (req->cmd_flags & REQ_SECURE &&
+                       !(card->quirks & MMC_QUIRK_SEC_ERASE_TRIM_BROKEN))
                        ret = mmc_blk_issue_secdiscard_rq(mq, req);
                else
                        ret = mmc_blk_issue_discard_rq(mq, req);
@@ -1716,6 +1717,7 @@ force_ro_fail:
 #define CID_MANFID_SANDISK     0x2
 #define CID_MANFID_TOSHIBA     0x11
 #define CID_MANFID_MICRON      0x13
+#define CID_MANFID_SAMSUNG     0x15
 
 static const struct mmc_fixup blk_fixups[] =
 {
@@ -1752,6 +1754,28 @@ static const struct mmc_fixup blk_fixups[] =
        MMC_FIXUP(CID_NAME_ANY, CID_MANFID_MICRON, 0x200, add_quirk_mmc,
                  MMC_QUIRK_LONG_READ_TIME),
 
+       /*
+        * On these Samsung MoviNAND parts, performing secure erase or
+        * secure trim can result in unrecoverable corruption due to a
+        * firmware bug.
+        */
+       MMC_FIXUP("M8G2FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MAG4FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MBG8FA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("MCGAFA", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VAL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("KYL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+       MMC_FIXUP("VZL00M", CID_MANFID_SAMSUNG, CID_OEMID_ANY, add_quirk_mmc,
+                 MMC_QUIRK_SEC_ERASE_TRIM_BROKEN),
+
        END_FIXUP
 };
 
index 322412cec4eeb8ca6970d2d12f37c7c83bbba42e..a53c7c478e054c8c47df5a5a219a2b1ed1e6836b 100644 (file)
@@ -81,6 +81,7 @@ struct atmel_mci_caps {
        bool    has_bad_data_ordering;
        bool    need_reset_after_xfer;
        bool    need_blksz_mul_4;
+       bool    need_notbusy_for_read_ops;
 };
 
 struct atmel_mci_dma {
@@ -1625,7 +1626,8 @@ static void atmci_tasklet_func(unsigned long priv)
                                __func__);
                        atmci_set_completed(host, EVENT_XFER_COMPLETE);
 
-                       if (host->data->flags & MMC_DATA_WRITE) {
+                       if (host->caps.need_notbusy_for_read_ops ||
+                          (host->data->flags & MMC_DATA_WRITE)) {
                                atmci_writel(host, ATMCI_IER, ATMCI_NOTBUSY);
                                state = STATE_WAITING_NOTBUSY;
                        } else if (host->mrq->stop) {
@@ -2218,6 +2220,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        host->caps.has_bad_data_ordering = 1;
        host->caps.need_reset_after_xfer = 1;
        host->caps.need_blksz_mul_4 = 1;
+       host->caps.need_notbusy_for_read_ops = 0;
 
        /* keep only major version number */
        switch (version & 0xf00) {
@@ -2238,6 +2241,7 @@ static void __init atmci_get_cap(struct atmel_mci *host)
        case 0x200:
                host->caps.has_rwproof = 1;
                host->caps.need_blksz_mul_4 = 0;
+               host->caps.need_notbusy_for_read_ops = 1;
        case 0x100:
                host->caps.has_bad_data_ordering = 0;
                host->caps.need_reset_after_xfer = 0;
index 03666174ca483e61a351626ad428a9bc833ef981..a17dd7363cebedc69c41d28b47b6c4fd895a327a 100644 (file)
 #define bfin_write_SDH_CFG             bfin_write_RSI_CFG
 #endif
 
-struct dma_desc_array {
-       unsigned long   start_addr;
-       unsigned short  cfg;
-       unsigned short  x_count;
-       short           x_modify;
-} __packed;
-
 struct sdh_host {
        struct mmc_host         *mmc;
        spinlock_t              lock;
index 72dc3cde646d063513f3a55fc8ba0ec74197261b..af40d227bece22ecb51bb0862df913aadc3ce6da 100644 (file)
@@ -627,6 +627,7 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
 {
        struct dw_mci *host = slot->host;
        u32 div;
+       u32 clk_en_a;
 
        if (slot->clock != host->current_speed) {
                div = host->bus_hz / slot->clock;
@@ -659,9 +660,11 @@ static void dw_mci_setup_bus(struct dw_mci_slot *slot)
                mci_send_cmd(slot,
                             SDMMC_CMD_UPD_CLK | SDMMC_CMD_PRV_DAT_WAIT, 0);
 
-               /* enable clock */
-               mci_writel(host, CLKENA, ((SDMMC_CLKEN_ENABLE |
-                          SDMMC_CLKEN_LOW_PWR) << slot->id));
+               /* enable clock; only low power if no SDIO */
+               clk_en_a = SDMMC_CLKEN_ENABLE << slot->id;
+               if (!(mci_readl(host, INTMASK) & SDMMC_INT_SDIO(slot->id)))
+                       clk_en_a |= SDMMC_CLKEN_LOW_PWR << slot->id;
+               mci_writel(host, CLKENA, clk_en_a);
 
                /* inform CIU */
                mci_send_cmd(slot,
@@ -862,6 +865,30 @@ static int dw_mci_get_cd(struct mmc_host *mmc)
        return present;
 }
 
+/*
+ * Disable lower power mode.
+ *
+ * Low power mode will stop the card clock when idle.  According to the
+ * description of the CLKENA register we should disable low power mode
+ * for SDIO cards if we need SDIO interrupts to work.
+ *
+ * This function is fast if low power mode is already disabled.
+ */
+static void dw_mci_disable_low_power(struct dw_mci_slot *slot)
+{
+       struct dw_mci *host = slot->host;
+       u32 clk_en_a;
+       const u32 clken_low_pwr = SDMMC_CLKEN_LOW_PWR << slot->id;
+
+       clk_en_a = mci_readl(host, CLKENA);
+
+       if (clk_en_a & clken_low_pwr) {
+               mci_writel(host, CLKENA, clk_en_a & ~clken_low_pwr);
+               mci_send_cmd(slot, SDMMC_CMD_UPD_CLK |
+                            SDMMC_CMD_PRV_DAT_WAIT, 0);
+       }
+}
+
 static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
 {
        struct dw_mci_slot *slot = mmc_priv(mmc);
@@ -871,6 +898,14 @@ static void dw_mci_enable_sdio_irq(struct mmc_host *mmc, int enb)
        /* Enable/disable Slot Specific SDIO interrupt */
        int_mask = mci_readl(host, INTMASK);
        if (enb) {
+               /*
+                * Turn off low power mode if it was enabled.  This is a bit of
+                * a heavy operation and we disable / enable IRQs a lot, so
+                * we'll leave low power mode disabled and it will get
+                * re-enabled again in dw_mci_setup_bus().
+                */
+               dw_mci_disable_low_power(slot);
+
                mci_writel(host, INTMASK,
                           (int_mask | SDMMC_INT_SDIO(slot->id)));
        } else {
@@ -1429,22 +1464,10 @@ static void dw_mci_read_data_pio(struct dw_mci *host)
                        nbytes += len;
                        remain -= len;
                } while (remain);
-               sg_miter->consumed = offset;
 
+               sg_miter->consumed = offset;
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_RXDR);
-               if (status & DW_MCI_DATA_ERROR_FLAGS) {
-                       host->data_status = status;
-                       data->bytes_xfered += nbytes;
-                       sg_miter_stop(sg_miter);
-                       host->sg = NULL;
-                       smp_wmb();
-
-                       set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
-                       tasklet_schedule(&host->tasklet);
-                       return;
-               }
        } while (status & SDMMC_INT_RXDR); /*if the RXDR is ready read again*/
        data->bytes_xfered += nbytes;
 
@@ -1497,23 +1520,10 @@ static void dw_mci_write_data_pio(struct dw_mci *host)
                        nbytes += len;
                        remain -= len;
                } while (remain);
-               sg_miter->consumed = offset;
 
+               sg_miter->consumed = offset;
                status = mci_readl(host, MINTSTS);
                mci_writel(host, RINTSTS, SDMMC_INT_TXDR);
-               if (status & DW_MCI_DATA_ERROR_FLAGS) {
-                       host->data_status = status;
-                       data->bytes_xfered += nbytes;
-                       sg_miter_stop(sg_miter);
-                       host->sg = NULL;
-
-                       smp_wmb();
-
-                       set_bit(EVENT_DATA_ERROR, &host->pending_events);
-
-                       tasklet_schedule(&host->tasklet);
-                       return;
-               }
        } while (status & SDMMC_INT_TXDR); /* if TXDR write again */
        data->bytes_xfered += nbytes;
 
@@ -1547,12 +1557,11 @@ static void dw_mci_cmd_interrupt(struct dw_mci *host, u32 status)
 static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 {
        struct dw_mci *host = dev_id;
-       u32 status, pending;
+       u32 pending;
        unsigned int pass_count = 0;
        int i;
 
        do {
-               status = mci_readl(host, RINTSTS);
                pending = mci_readl(host, MINTSTS); /* read-only mask reg */
 
                /*
@@ -1570,7 +1579,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & DW_MCI_CMD_ERROR_FLAGS) {
                        mci_writel(host, RINTSTS, DW_MCI_CMD_ERROR_FLAGS);
-                       host->cmd_status = status;
+                       host->cmd_status = pending;
                        smp_wmb();
                        set_bit(EVENT_CMD_COMPLETE, &host->pending_events);
                }
@@ -1578,18 +1587,16 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
                if (pending & DW_MCI_DATA_ERROR_FLAGS) {
                        /* if there is an error report DATA_ERROR */
                        mci_writel(host, RINTSTS, DW_MCI_DATA_ERROR_FLAGS);
-                       host->data_status = status;
+                       host->data_status = pending;
                        smp_wmb();
                        set_bit(EVENT_DATA_ERROR, &host->pending_events);
-                       if (!(pending & (SDMMC_INT_DTO | SDMMC_INT_DCRC |
-                                        SDMMC_INT_SBE | SDMMC_INT_EBE)))
-                               tasklet_schedule(&host->tasklet);
+                       tasklet_schedule(&host->tasklet);
                }
 
                if (pending & SDMMC_INT_DATA_OVER) {
                        mci_writel(host, RINTSTS, SDMMC_INT_DATA_OVER);
                        if (!host->data_status)
-                               host->data_status = status;
+                               host->data_status = pending;
                        smp_wmb();
                        if (host->dir_status == DW_MCI_RECV_STATUS) {
                                if (host->sg != NULL)
@@ -1613,7 +1620,7 @@ static irqreturn_t dw_mci_interrupt(int irq, void *dev_id)
 
                if (pending & SDMMC_INT_CMD_DONE) {
                        mci_writel(host, RINTSTS, SDMMC_INT_CMD_DONE);
-                       dw_mci_cmd_interrupt(host, status);
+                       dw_mci_cmd_interrupt(host, pending);
                }
 
                if (pending & SDMMC_INT_CD) {
index a51f9309ffbb1e49947939fb60d6c6dcc8e3be93..ad3fcea1269ebc179105563333b01cfdf139a9ed 100644 (file)
@@ -285,11 +285,11 @@ static irqreturn_t mxs_mmc_irq_handler(int irq, void *dev_id)
        writel(stat & MXS_MMC_IRQ_BITS,
               host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_CLR);
 
+       spin_unlock(&host->lock);
+
        if ((stat & BM_SSP_CTRL1_SDIO_IRQ) && (stat & BM_SSP_CTRL1_SDIO_IRQ_EN))
                mmc_signal_sdio_irq(host->mmc);
 
-       spin_unlock(&host->lock);
-
        if (stat & BM_SSP_CTRL1_RESP_TIMEOUT_IRQ)
                cmd->error = -ETIMEDOUT;
        else if (stat & BM_SSP_CTRL1_RESP_ERR_IRQ)
@@ -644,11 +644,6 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
                       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_SET);
                writel(BM_SSP_CTRL1_SDIO_IRQ_EN,
                       host->base + HW_SSP_CTRL1(host) + STMP_OFFSET_REG_SET);
-
-               if (readl(host->base + HW_SSP_STATUS(host)) &
-                               BM_SSP_STATUS_SDIO_IRQ)
-                       mmc_signal_sdio_irq(host->mmc);
-
        } else {
                writel(BM_SSP_CTRL0_SDIO_IRQ_CHECK,
                       host->base + HW_SSP_CTRL0 + STMP_OFFSET_REG_CLR);
@@ -657,6 +652,11 @@ static void mxs_mmc_enable_sdio_irq(struct mmc_host *mmc, int enable)
        }
 
        spin_unlock_irqrestore(&host->lock, flags);
+
+       if (enable && readl(host->base + HW_SSP_STATUS(host)) &
+                       BM_SSP_STATUS_SDIO_IRQ)
+               mmc_signal_sdio_irq(host->mmc);
+
 }
 
 static const struct mmc_host_ops mxs_mmc_ops = {
index 50e08f03aa65ce72ce3876deb304db2fbed8a22f..a5999a74496af218c540959ee757b7c1ad3f1365 100644 (file)
@@ -668,7 +668,7 @@ mmc_omap_clk_timer(unsigned long data)
 static void
 mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
 {
-       int n;
+       int n, nwords;
 
        if (host->buffer_bytes_left == 0) {
                host->sg_idx++;
@@ -678,15 +678,23 @@ mmc_omap_xfer_data(struct mmc_omap_host *host, int write)
        n = 64;
        if (n > host->buffer_bytes_left)
                n = host->buffer_bytes_left;
+
+       nwords = n / 2;
+       nwords += n & 1; /* handle odd number of bytes to transfer */
+
        host->buffer_bytes_left -= n;
        host->total_bytes_left -= n;
        host->data->bytes_xfered += n;
 
        if (write) {
-               __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+               __raw_writesw(host->virt_base + OMAP_MMC_REG(host, DATA),
+                             host->buffer, nwords);
        } else {
-               __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA), host->buffer, n);
+               __raw_readsw(host->virt_base + OMAP_MMC_REG(host, DATA),
+                            host->buffer, nwords);
        }
+
+       host->buffer += nwords;
 }
 
 static inline void mmc_omap_report_irq(u16 status)
index b97b2f5dafdb4d15160701dd12060b05c394b464..d25f9ab9a54da919a6e54cc05743f74ad83362f1 100644 (file)
@@ -48,14 +48,14 @@ static inline void esdhc_set_clock(struct sdhci_host *host, unsigned int clock)
        int div = 1;
        u32 temp;
 
+       if (clock == 0)
+               goto out;
+
        temp = sdhci_readl(host, ESDHC_SYSTEM_CONTROL);
        temp &= ~(ESDHC_CLOCK_IPGEN | ESDHC_CLOCK_HCKEN | ESDHC_CLOCK_PEREN
                | ESDHC_CLOCK_MASK);
        sdhci_writel(host, temp, ESDHC_SYSTEM_CONTROL);
 
-       if (clock == 0)
-               goto out;
-
        while (host->max_clk / pre_div / 16 > clock && pre_div < 256)
                pre_div *= 2;
 
index f2f482bec5736b21a562da5e4fda11375e8cf457..a6e74514e6624e95f8e6e56fb319d567b1011f78 100644 (file)
@@ -1123,6 +1123,33 @@ static unsigned long mtdchar_get_unmapped_area(struct file *file,
 }
 #endif
 
+static inline unsigned long get_vm_size(struct vm_area_struct *vma)
+{
+       return vma->vm_end - vma->vm_start;
+}
+
+static inline resource_size_t get_vm_offset(struct vm_area_struct *vma)
+{
+       return (resource_size_t) vma->vm_pgoff << PAGE_SHIFT;
+}
+
+/*
+ * Set a new vm offset.
+ *
+ * Verify that the incoming offset really works as a page offset,
+ * and that the offset and size fit in a resource_size_t.
+ */
+static inline int set_vm_offset(struct vm_area_struct *vma, resource_size_t off)
+{
+       pgoff_t pgoff = off >> PAGE_SHIFT;
+       if (off != (resource_size_t) pgoff << PAGE_SHIFT)
+               return -EINVAL;
+       if (off + get_vm_size(vma) - 1 < off)
+               return -EINVAL;
+       vma->vm_pgoff = pgoff;
+       return 0;
+}
+
 /*
  * set up a mapping for shared memory segments
  */
@@ -1132,20 +1159,29 @@ static int mtdchar_mmap(struct file *file, struct vm_area_struct *vma)
        struct mtd_file_info *mfi = file->private_data;
        struct mtd_info *mtd = mfi->mtd;
        struct map_info *map = mtd->priv;
-       unsigned long start;
-       unsigned long off;
-       u32 len;
+       resource_size_t start, off;
+       unsigned long len, vma_len;
 
        if (mtd->type == MTD_RAM || mtd->type == MTD_ROM) {
-               off = vma->vm_pgoff << PAGE_SHIFT;
+               off = get_vm_offset(vma);
                start = map->phys;
                len = PAGE_ALIGN((start & ~PAGE_MASK) + map->size);
                start &= PAGE_MASK;
-               if ((vma->vm_end - vma->vm_start + off) > len)
+               vma_len = get_vm_size(vma);
+
+               /* Overflow in off+len? */
+               if (vma_len + off < off)
+                       return -EINVAL;
+               /* Does it fit in the mapping? */
+               if (vma_len + off > len)
                        return -EINVAL;
 
                off += start;
-               vma->vm_pgoff = off >> PAGE_SHIFT;
+               /* Did that overflow? */
+               if (off < start)
+                       return -EINVAL;
+               if (set_vm_offset(vma, off) < 0)
+                       return -EINVAL;
                vma->vm_flags |= VM_IO | VM_RESERVED;
 
 #ifdef pgprot_noncached
index 437bc193e170d6da377d6b7447adc5cc43d348bb..568307cc7caf8d882034011aa5303ad47eaf3bed 100644 (file)
@@ -340,7 +340,7 @@ retry:
         * of this LEB as it will be deleted and freed in 'ubi_add_to_av()'.
         */
        err = ubi_add_to_av(ubi, ai, new_aeb->pnum, new_aeb->ec, vid_hdr, 0);
-       kfree(new_aeb);
+       kmem_cache_free(ai->aeb_slab_cache, new_aeb);
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
 
@@ -353,7 +353,7 @@ write_error:
                list_add(&new_aeb->u.list, &ai->erase);
                goto retry;
        }
-       kfree(new_aeb);
+       kmem_cache_free(ai->aeb_slab_cache, new_aeb);
 out_free:
        ubi_free_vid_hdr(ubi, vid_hdr);
        return err;
index 98ee4381991189d8814600967acac3b170525b1d..7edadee487bab16c0cbcf514ab59540f35cc2a41 100644 (file)
@@ -1391,7 +1391,6 @@ static irqreturn_t ican3_irq(int irq, void *dev_id)
  */
 static int ican3_reset_module(struct ican3_dev *mod)
 {
-       u8 val = 1 << mod->num;
        unsigned long start;
        u8 runold, runnew;
 
@@ -1405,8 +1404,7 @@ static int ican3_reset_module(struct ican3_dev *mod)
        runold = ioread8(mod->dpm + TARGET_RUNNING);
 
        /* reset the module */
-       iowrite8(val, &mod->ctrl->reset_assert);
-       iowrite8(val, &mod->ctrl->reset_deassert);
+       iowrite8(0x00, &mod->dpmctrl->hwreset);
 
        /* wait until the module has finished resetting and is running */
        start = jiffies;
index a580db29e50360f8be44403e5893764261562549..26e7129332abc7e18bd7b27cd3f49d67976c3a16 100644 (file)
 #define INSTRUCTION_LOAD_TXB(n)        (0x40 + 2 * (n))
 #define INSTRUCTION_READ_RXB(n)        (((n) == 0) ? 0x90 : 0x94)
 #define INSTRUCTION_RESET      0xC0
+#define RTS_TXB0               0x01
+#define RTS_TXB1               0x02
+#define RTS_TXB2               0x04
+#define INSTRUCTION_RTS(n)     (0x80 | ((n) & 0x07))
+
 
 /* MPC251x registers */
 #define CANSTAT              0x0e
@@ -397,6 +402,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf,
 static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
                          int tx_buf_idx)
 {
+       struct mcp251x_priv *priv = dev_get_drvdata(&spi->dev);
        u32 sid, eid, exide, rtr;
        u8 buf[SPI_TRANSFER_BUF_LEN];
 
@@ -418,7 +424,10 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame,
        buf[TXBDLC_OFF] = (rtr << DLC_RTR_SHIFT) | frame->can_dlc;
        memcpy(buf + TXBDAT_OFF, frame->data, frame->can_dlc);
        mcp251x_hw_tx_frame(spi, buf, frame->can_dlc, tx_buf_idx);
-       mcp251x_write_reg(spi, TXBCTRL(tx_buf_idx), TXBCTRL_TXREQ);
+
+       /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */
+       priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx);
+       mcp251x_spi_trans(priv->spi, 1);
 }
 
 static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf,
index 4f50145f64839f519c232d0e4ec79e7fedf2bd34..662c5f7eb0c54af4cb3c788959109a7693798629 100644 (file)
@@ -109,7 +109,9 @@ static int sp_probe(struct platform_device *pdev)
        priv = netdev_priv(dev);
 
        dev->irq = res_irq->start;
-       priv->irq_flags = res_irq->flags & (IRQF_TRIGGER_MASK | IRQF_SHARED);
+       priv->irq_flags = res_irq->flags & IRQF_TRIGGER_MASK;
+       if (res_irq->flags & IORESOURCE_IRQ_SHAREABLE)
+               priv->irq_flags |= IRQF_SHARED;
        priv->reg_base = addr;
        /* The CAN clock frequency is half the oscillator clock frequency */
        priv->can.clock.freq = pdata->osc_freq / 2;
index 3105961756767cb3b52bc18bce8a248e7ef110b7..b595d3422b9f759d86c760370b30efcb04f76575 100644 (file)
@@ -150,7 +150,7 @@ int softing_load_fw(const char *file, struct softing *card,
        const uint8_t *mem, *end, *dat;
        uint16_t type, len;
        uint32_t addr;
-       uint8_t *buf = NULL;
+       uint8_t *buf = NULL, *new_buf;
        int buflen = 0;
        int8_t type_end = 0;
 
@@ -199,11 +199,12 @@ int softing_load_fw(const char *file, struct softing *card,
                if (len > buflen) {
                        /* align buflen */
                        buflen = (len + (1024-1)) & ~(1024-1);
-                       buf = krealloc(buf, buflen, GFP_KERNEL);
-                       if (!buf) {
+                       new_buf = krealloc(buf, buflen, GFP_KERNEL);
+                       if (!new_buf) {
                                ret = -ENOMEM;
                                goto failed;
                        }
+                       buf = new_buf;
                }
                /* verify record data */
                memcpy_fromio(buf, &dpram[addr + offset], len);
index 527dbcf9533561489bb33332f03462ac5f405f43..9ded21e79db5866602706ca568dea6613bc0a727 100644 (file)
@@ -984,12 +984,12 @@ static int __devexit ti_hecc_remove(struct platform_device *pdev)
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct ti_hecc_priv *priv = netdev_priv(ndev);
 
+       unregister_candev(ndev);
        clk_disable(priv->clk);
        clk_put(priv->clk);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        iounmap(priv->base);
        release_mem_region(res->start, resource_size(res));
-       unregister_candev(ndev);
        free_candev(ndev);
        platform_set_drvdata(pdev, NULL);
 
index 79cebd8525ce3d451e30b935484dac18535939f2..e48312f2305db18a08b5744a01013455a7b732ab 100644 (file)
@@ -8564,7 +8564,7 @@ bnx2_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
        return 0;
 
 error:
-       iounmap(bp->regview);
+       pci_iounmap(pdev, bp->regview);
        pci_release_regions(pdev);
        pci_disable_device(pdev);
        pci_set_drvdata(pdev, NULL);
index 463b9ec57d8077c8a1599457974ab15dc1210536..6d1a24acb77e1cb9332906759811980aa537b4e2 100644 (file)
@@ -1708,9 +1708,6 @@ struct bnx2x_func_init_params {
                        continue;               \
                else
 
-#define for_each_napi_rx_queue(bp, var) \
-       for ((var) = 0; (var) < bp->num_napi_queues; (var)++)
-
 /* Skip OOO FP */
 #define for_each_tx_queue(bp, var) \
        for ((var) = 0; (var) < BNX2X_NUM_QUEUES(bp); (var)++) \
index e879e19eb0d68926a883ee55ffcaaa194a8b513b..e8e97a7d1d06df9a209c741406af32c19a1313e2 100644 (file)
@@ -662,14 +662,16 @@ void bnx2x_csum_validate(struct sk_buff *skb, union eth_rx_cqe *cqe,
                                 struct bnx2x_fastpath *fp,
                                 struct bnx2x_eth_q_stats *qstats)
 {
-       /* Do nothing if no IP/L4 csum validation was done */
-
+       /* Do nothing if no L4 csum validation was done.
+        * We do not check whether IP csum was validated. For IPv4 we assume
+        * that if the card got as far as validating the L4 csum, it also
+        * validated the IP csum. IPv6 has no IP csum.
+        */
        if (cqe->fast_path_cqe.status_flags &
-           (ETH_FAST_PATH_RX_CQE_IP_XSUM_NO_VALIDATION_FLG |
-            ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG))
+           ETH_FAST_PATH_RX_CQE_L4_XSUM_NO_VALIDATION_FLG)
                return;
 
-       /* If both IP/L4 validation were done, check if an error was found. */
+       /* If L4 validation was done, check if an error was found. */
 
        if (cqe->fast_path_cqe.type_error_flags &
            (ETH_FAST_PATH_RX_CQE_IP_BAD_XSUM_FLG |
@@ -2046,6 +2048,8 @@ int bnx2x_nic_load(struct bnx2x *bp, int load_mode)
         */
        bnx2x_setup_tc(bp->dev, bp->max_cos);
 
+       /* Add all NAPI objects */
+       bnx2x_add_all_napi(bp);
        bnx2x_napi_enable(bp);
 
        /* set pf load just before approaching the MCP */
@@ -2408,6 +2412,8 @@ int bnx2x_nic_unload(struct bnx2x *bp, int unload_mode)
 
                /* Disable HW interrupts, NAPI */
                bnx2x_netif_stop(bp, 1);
+               /* Delete all NAPI objects */
+               bnx2x_del_all_napi(bp);
 
                /* Release IRQs */
                bnx2x_free_irq(bp);
index dfa757e742966998fb8e9ea8b99f2667b0835a43..dfd86a55f1dcab583ad08342a21eaae9a97be53f 100644 (file)
@@ -710,17 +710,15 @@ static inline u16 bnx2x_tx_avail(struct bnx2x *bp,
        prod = txdata->tx_bd_prod;
        cons = txdata->tx_bd_cons;
 
-       /* NUM_TX_RINGS = number of "next-page" entries
-          It will be used as a threshold */
-       used = SUB_S16(prod, cons) + (s16)NUM_TX_RINGS;
+       used = SUB_S16(prod, cons);
 
 #ifdef BNX2X_STOP_ON_ERROR
        WARN_ON(used < 0);
-       WARN_ON(used > bp->tx_ring_size);
-       WARN_ON((bp->tx_ring_size - used) > MAX_TX_AVAIL);
+       WARN_ON(used > txdata->tx_ring_size);
+       WARN_ON((txdata->tx_ring_size - used) > MAX_TX_AVAIL);
 #endif
 
-       return (s16)(bp->tx_ring_size) - used;
+       return (s16)(txdata->tx_ring_size) - used;
 }
 
 static inline int bnx2x_tx_queue_has_work(struct bnx2x_fp_txdata *txdata)
@@ -792,7 +790,7 @@ static inline void bnx2x_add_all_napi(struct bnx2x *bp)
        bp->num_napi_queues = bp->num_queues;
 
        /* Add NAPI objects */
-       for_each_napi_rx_queue(bp, i)
+       for_each_rx_queue(bp, i)
                netif_napi_add(bp->dev, &bnx2x_fp(bp, i, napi),
                               bnx2x_poll, BNX2X_NAPI_WEIGHT);
 }
@@ -801,7 +799,7 @@ static inline void bnx2x_del_all_napi(struct bnx2x *bp)
 {
        int i;
 
-       for_each_napi_rx_queue(bp, i)
+       for_each_rx_queue(bp, i)
                netif_napi_del(&bnx2x_fp(bp, i, napi));
 }
 
@@ -1088,6 +1086,7 @@ static inline void bnx2x_init_txdata(struct bnx2x *bp,
        txdata->txq_index = txq_index;
        txdata->tx_cons_sb = tx_cons_sb;
        txdata->parent_fp = fp;
+       txdata->tx_ring_size = IS_FCOE_FP(fp) ? MAX_TX_AVAIL : bp->tx_ring_size;
 
        DP(NETIF_MSG_IFUP, "created tx data cid %d, txq %d\n",
           txdata->cid, txdata->txq_index);
index 3e4cff9b1ebee60a4fa4cedbb90fdeaecc73b580..b926f58e983bbfe083e004c362df6203efb17a3e 100644 (file)
@@ -401,11 +401,11 @@ static const struct reg_addr reg_addrs[] = {
        { 0x70000, 8, RI_ALL_ONLINE },
        { 0x70020, 8184, RI_ALL_OFFLINE },
        { 0x78000, 8192, RI_E3E3B0_OFFLINE },
-       { 0x85000, 3, RI_ALL_ONLINE },
-       { 0x8501c, 7, RI_ALL_ONLINE },
-       { 0x85048, 1, RI_ALL_ONLINE },
-       { 0x85200, 32, RI_ALL_ONLINE },
-       { 0xb0000, 16384, RI_E1H_ONLINE },
+       { 0x85000, 3, RI_ALL_OFFLINE },
+       { 0x8501c, 7, RI_ALL_OFFLINE },
+       { 0x85048, 1, RI_ALL_OFFLINE },
+       { 0x85200, 32, RI_ALL_OFFLINE },
+       { 0xb0000, 16384, RI_E1H_OFFLINE },
        { 0xc1000, 7, RI_ALL_ONLINE },
        { 0xc103c, 2, RI_E2E3E3B0_ONLINE },
        { 0xc1800, 2, RI_ALL_ONLINE },
@@ -581,17 +581,12 @@ static const struct reg_addr reg_addrs[] = {
        { 0x140188, 3, RI_E1E1HE2E3_ONLINE },
        { 0x140194, 13, RI_ALL_ONLINE },
        { 0x140200, 6, RI_E1E1HE2E3_ONLINE },
-       { 0x140220, 4, RI_E2E3_ONLINE },
-       { 0x140240, 4, RI_E2E3_ONLINE },
        { 0x140260, 4, RI_E2E3_ONLINE },
        { 0x140280, 4, RI_E2E3_ONLINE },
-       { 0x1402a0, 4, RI_E2E3_ONLINE },
-       { 0x1402c0, 4, RI_E2E3_ONLINE },
        { 0x1402e0, 2, RI_E2E3_ONLINE },
        { 0x1402e8, 2, RI_E2E3E3B0_ONLINE },
        { 0x1402f0, 9, RI_E2E3_ONLINE },
        { 0x140314, 44, RI_E3B0_ONLINE },
-       { 0x1403d0, 70, RI_E3B0_ONLINE },
        { 0x144000, 4, RI_E1E1H_ONLINE },
        { 0x148000, 4, RI_E1E1H_ONLINE },
        { 0x14c000, 4, RI_E1E1H_ONLINE },
@@ -704,7 +699,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x180398, 1, RI_E2E3E3B0_ONLINE },
        { 0x1803a0, 5, RI_E2E3E3B0_ONLINE },
        { 0x1803b4, 2, RI_E3E3B0_ONLINE },
-       { 0x180400, 1, RI_ALL_ONLINE },
        { 0x180404, 255, RI_E1E1H_OFFLINE },
        { 0x181000, 4, RI_ALL_ONLINE },
        { 0x181010, 1020, RI_ALL_OFFLINE },
@@ -800,9 +794,9 @@ static const struct reg_addr reg_addrs[] = {
        { 0x1b905c, 1, RI_E3E3B0_ONLINE },
        { 0x1b9064, 1, RI_E3B0_ONLINE },
        { 0x1b9080, 10, RI_E3B0_ONLINE },
-       { 0x1b9400, 14, RI_E2E3E3B0_ONLINE },
-       { 0x1b943c, 19, RI_E2E3E3B0_ONLINE },
-       { 0x1b9490, 10, RI_E2E3E3B0_ONLINE },
+       { 0x1b9400, 14, RI_E2E3E3B0_OFFLINE },
+       { 0x1b943c, 19, RI_E2E3E3B0_OFFLINE },
+       { 0x1b9490, 10, RI_E2E3E3B0_OFFLINE },
        { 0x1c0000, 2, RI_ALL_ONLINE },
        { 0x200000, 65, RI_ALL_ONLINE },
        { 0x20014c, 2, RI_E1HE2E3E3B0_ONLINE },
@@ -814,7 +808,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x200398, 1, RI_E2E3E3B0_ONLINE },
        { 0x2003a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x2003a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x200400, 1, RI_ALL_ONLINE },
        { 0x200404, 255, RI_E1E1H_OFFLINE },
        { 0x202000, 4, RI_ALL_ONLINE },
        { 0x202010, 2044, RI_ALL_OFFLINE },
@@ -921,7 +914,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x280398, 1, RI_E2E3E3B0_ONLINE },
        { 0x2803a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x2803a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x280400, 1, RI_ALL_ONLINE },
        { 0x280404, 255, RI_E1E1H_OFFLINE },
        { 0x282000, 4, RI_ALL_ONLINE },
        { 0x282010, 2044, RI_ALL_OFFLINE },
@@ -1031,7 +1023,6 @@ static const struct reg_addr reg_addrs[] = {
        { 0x300398, 1, RI_E2E3E3B0_ONLINE },
        { 0x3003a0, 1, RI_E2E3E3B0_ONLINE },
        { 0x3003a8, 2, RI_E2E3E3B0_ONLINE },
-       { 0x300400, 1, RI_ALL_ONLINE },
        { 0x300404, 255, RI_E1E1H_OFFLINE },
        { 0x302000, 4, RI_ALL_ONLINE },
        { 0x302010, 2044, RI_ALL_OFFLINE },
index fc4e0e3885b039f0cb7dff48edade89e211de15b..ebf40cd7aa1050d716683e806eda505050bf1e40 100644 (file)
@@ -775,7 +775,7 @@ static void bnx2x_get_regs(struct net_device *dev,
        struct bnx2x *bp = netdev_priv(dev);
        struct dump_hdr dump_hdr = {0};
 
-       regs->version = 0;
+       regs->version = 1;
        memset(p, 0, regs->len);
 
        if (!netif_running(bp->dev))
@@ -1587,6 +1587,12 @@ static int bnx2x_set_pauseparam(struct net_device *dev,
                        bp->link_params.req_flow_ctrl[cfg_idx] =
                                BNX2X_FLOW_CTRL_AUTO;
                }
+               bp->link_params.req_fc_auto_adv = BNX2X_FLOW_CTRL_NONE;
+               if (epause->rx_pause)
+                       bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_RX;
+
+               if (epause->tx_pause)
+                       bp->link_params.req_fc_auto_adv |= BNX2X_FLOW_CTRL_TX;
        }
 
        DP(BNX2X_MSG_ETHTOOL,
@@ -2888,11 +2894,9 @@ static void bnx2x_get_channels(struct net_device *dev,
  */
 static void bnx2x_change_num_queues(struct bnx2x *bp, int num_rss)
 {
-       bnx2x_del_all_napi(bp);
        bnx2x_disable_msi(bp);
        BNX2X_NUM_QUEUES(bp) = num_rss + NON_ETH_CONTEXT_USE;
        bnx2x_set_int_mode(bp);
-       bnx2x_add_all_napi(bp);
 }
 
 /**
index f4beb46c4709af8291ed7aecc373d7a72a366f59..b046beb435b2c490f70ef3bc2f67bf3af16bfcb5 100644 (file)
@@ -2667,9 +2667,11 @@ int bnx2x_update_pfc(struct link_params *params,
                return bnx2x_status;
 
        DP(NETIF_MSG_LINK, "About to update PFC in BMAC\n");
-       if (CHIP_IS_E3(bp))
-               bnx2x_update_pfc_xmac(params, vars, 0);
-       else {
+
+       if (CHIP_IS_E3(bp)) {
+               if (vars->mac_type == MAC_TYPE_XMAC)
+                       bnx2x_update_pfc_xmac(params, vars, 0);
+       } else {
                val = REG_RD(bp, MISC_REG_RESET_REG_2);
                if ((val &
                     (MISC_REGISTERS_RESET_REG_2_RST_BMAC0 << params->port))
@@ -5432,7 +5434,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
                switch (speed_mask) {
                case GP_STATUS_10M:
                        vars->line_speed = SPEED_10;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_10TFD;
                        else
                                vars->link_status |= LINK_10THD;
@@ -5440,7 +5442,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 
                case GP_STATUS_100M:
                        vars->line_speed = SPEED_100;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_100TXFD;
                        else
                                vars->link_status |= LINK_100TXHD;
@@ -5449,7 +5451,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
                case GP_STATUS_1G:
                case GP_STATUS_1G_KX:
                        vars->line_speed = SPEED_1000;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_1000TFD;
                        else
                                vars->link_status |= LINK_1000THD;
@@ -5457,7 +5459,7 @@ static int bnx2x_get_link_speed_duplex(struct bnx2x_phy *phy,
 
                case GP_STATUS_2_5G:
                        vars->line_speed = SPEED_2500;
-                       if (vars->duplex == DUPLEX_FULL)
+                       if (is_duplex == DUPLEX_FULL)
                                vars->link_status |= LINK_2500TFD;
                        else
                                vars->link_status |= LINK_2500THD;
@@ -5531,6 +5533,7 @@ static int bnx2x_link_settings_status(struct bnx2x_phy *phy,
 
        if (gp_status & MDIO_GP_STATUS_TOP_AN_STATUS1_LINK_STATUS) {
                if (SINGLE_MEDIA_DIRECT(params)) {
+                       vars->duplex = duplex;
                        bnx2x_flow_ctrl_resolve(phy, params, vars, gp_status);
                        if (phy->req_line_speed == SPEED_AUTO_NEG)
                                bnx2x_xgxs_an_resolve(phy, params, vars,
@@ -5625,6 +5628,7 @@ static int bnx2x_warpcore_read_status(struct bnx2x_phy *phy,
                                        LINK_STATUS_PARALLEL_DETECTION_USED;
                        }
                        bnx2x_ext_phy_resolve_fc(phy, params, vars);
+                       vars->duplex = duplex;
                }
        }
 
index 02b5a343b19506a2edc60be5dd6b41d781aadb85..0875ecfe33729e2c2860dd5149e62042ddcbc6d7 100644 (file)
@@ -7561,8 +7561,14 @@ int bnx2x_set_mac_one(struct bnx2x *bp, u8 *mac,
        }
 
        rc = bnx2x_config_vlan_mac(bp, &ramrod_param);
-       if (rc < 0)
+
+       if (rc == -EEXIST) {
+               DP(BNX2X_MSG_SP, "Failed to schedule ADD operations: %d\n", rc);
+               /* do not treat adding same MAC as error */
+               rc = 0;
+       } else if (rc < 0)
                BNX2X_ERR("%s MAC failed\n", (set ? "Set" : "Del"));
+
        return rc;
 }
 
@@ -8427,6 +8433,8 @@ unload_error:
 
        /* Disable HW interrupts, NAPI */
        bnx2x_netif_stop(bp, 1);
+       /* Delete all NAPI objects */
+       bnx2x_del_all_napi(bp);
 
        /* Release IRQs */
        bnx2x_free_irq(bp);
@@ -9823,12 +9831,13 @@ static void __devinit bnx2x_get_igu_cam_info(struct bnx2x *bp)
        }
 
 #ifdef CONFIG_PCI_MSI
-       /*
-        * It's expected that number of CAM entries for this functions is equal
-        * to the number evaluated based on the MSI-X table size. We want a
-        * harsh warning if these values are different!
+       /* Due to new PF resource allocation by MFW T7.4 and above, it's
+        * optional that number of CAM entries will not be equal to the value
+        * advertised in PCI.
+        * Driver should use the minimal value of both as the actual status
+        * block count
         */
-       WARN_ON(bp->igu_sb_cnt != igu_sb_cnt);
+       bp->igu_sb_cnt = min_t(int, bp->igu_sb_cnt, igu_sb_cnt);
 #endif
 
        if (igu_sb_cnt == 0)
@@ -10292,13 +10301,11 @@ static void __devinit bnx2x_get_fcoe_info(struct bnx2x *bp)
                                dev_info.port_hw_config[port].
                                 fcoe_wwn_node_name_lower);
        } else if (!IS_MF_SD(bp)) {
-               u32 cfg = MF_CFG_RD(bp, func_ext_config[func].func_cfg);
-
                /*
                 * Read the WWN info only if the FCoE feature is enabled for
                 * this function.
                 */
-               if (cfg & MACP_FUNC_CFG_FLAGS_FCOE_OFFLOAD)
+               if (BNX2X_MF_EXT_PROTOCOL_FCOE(bp) && !CHIP_IS_E1x(bp))
                        bnx2x_get_ext_wwn_info(bp, func);
 
        } else if (IS_MF_FCOE_SD(bp))
@@ -11071,7 +11078,14 @@ static int bnx2x_set_uc_list(struct bnx2x *bp)
        netdev_for_each_uc_addr(ha, dev) {
                rc = bnx2x_set_mac_one(bp, bnx2x_uc_addr(ha), mac_obj, true,
                                       BNX2X_UC_LIST_MAC, &ramrod_flags);
-               if (rc < 0) {
+               if (rc == -EEXIST) {
+                       DP(BNX2X_MSG_SP,
+                          "Failed to schedule ADD operations: %d\n", rc);
+                       /* do not treat adding same MAC as error */
+                       rc = 0;
+
+               } else if (rc < 0) {
+
                        BNX2X_ERR("Failed to schedule ADD operations: %d\n",
                                  rc);
                        return rc;
@@ -11229,10 +11243,12 @@ static int bnx2x_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
 static void poll_bnx2x(struct net_device *dev)
 {
        struct bnx2x *bp = netdev_priv(dev);
+       int i;
 
-       disable_irq(bp->pdev->irq);
-       bnx2x_interrupt(bp->pdev->irq, dev);
-       enable_irq(bp->pdev->irq);
+       for_each_eth_queue(bp, i) {
+               struct bnx2x_fastpath *fp = &bp->fp[i];
+               napi_schedule(&bnx2x_fp(bp, fp->index, napi));
+       }
 }
 #endif
 
@@ -11899,9 +11915,6 @@ static int __devinit bnx2x_init_one(struct pci_dev *pdev,
         */
        bnx2x_set_int_mode(bp);
 
-       /* Add all NAPI objects */
-       bnx2x_add_all_napi(bp);
-
        rc = register_netdev(dev);
        if (rc) {
                dev_err(&pdev->dev, "Cannot register net device\n");
@@ -11976,9 +11989,6 @@ static void __devexit bnx2x_remove_one(struct pci_dev *pdev)
 
        unregister_netdev(dev);
 
-       /* Delete all NAPI objects */
-       bnx2x_del_all_napi(bp);
-
        /* Power on: we can't let PCI layer write to us while we are in D3 */
        bnx2x_set_power_state(bp, PCI_D0);
 
@@ -12025,6 +12035,8 @@ static int bnx2x_eeh_nic_unload(struct bnx2x *bp)
        bnx2x_tx_disable(bp);
 
        bnx2x_netif_stop(bp, 0);
+       /* Delete all NAPI objects */
+       bnx2x_del_all_napi(bp);
 
        del_timer_sync(&bp->timer);
 
index 332db64dd5bea11eed0cf878565c5c2e573f5c3e..a1d0446b39b356dd69e0b77e69f6285ba37edb63 100644 (file)
@@ -101,6 +101,11 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
        if (CHIP_REV_IS_SLOW(bp))
                return;
 
+       /* Update MCP's statistics if possible */
+       if (bp->func_stx)
+               memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats,
+                      sizeof(bp->func_stats));
+
        /* loader */
        if (bp->executer_idx) {
                int loader_idx = PMF_DMAE_C(bp);
@@ -128,8 +133,6 @@ static void bnx2x_hw_stats_post(struct bnx2x *bp)
 
        } else if (bp->func_stx) {
                *stats_comp = 0;
-               memcpy(bnx2x_sp(bp, func_stats), &bp->func_stats,
-                      sizeof(bp->func_stats));
                bnx2x_post_dmae(bp, dmae, INIT_DMAE_C(bp));
        }
 }
@@ -1151,9 +1154,11 @@ static void bnx2x_stats_update(struct bnx2x *bp)
        if (bp->port.pmf)
                bnx2x_hw_stats_update(bp);
 
-       if (bnx2x_storm_stats_update(bp) && (bp->stats_pending++ == 3)) {
-               BNX2X_ERR("storm stats were not updated for 3 times\n");
-               bnx2x_panic();
+       if (bnx2x_storm_stats_update(bp)) {
+               if (bp->stats_pending++ == 3) {
+                       BNX2X_ERR("storm stats were not updated for 3 times\n");
+                       bnx2x_panic();
+               }
                return;
        }
 
index 77884191a8c6448a7eea54c94b8ba8d9ce0fef83..4e980a7886fb58758fa84071b2494f56364da1f2 100644 (file)
@@ -1086,7 +1086,7 @@ static int __init at91ether_probe(struct platform_device *pdev)
        /* Clock */
        lp->ether_clk = clk_get(&pdev->dev, "ether_clk");
        if (IS_ERR(lp->ether_clk)) {
-               res = -ENODEV;
+               res = PTR_ERR(lp->ether_clk);
                goto err_ioumap;
        }
        clk_enable(lp->ether_clk);
index 845b2020f291cc20ad8223c8165512604314e812..138446957786a9ce0845a7e8221af4887b904ce3 100644 (file)
@@ -1243,6 +1243,7 @@ static void set_multicast_list(struct net_device *dev)
 {
        struct net_local *lp = netdev_priv(dev);
        unsigned long flags;
+       u16 cfg;
 
        spin_lock_irqsave(&lp->lock, flags);
        if (dev->flags & IFF_PROMISC)
@@ -1260,11 +1261,10 @@ static void set_multicast_list(struct net_device *dev)
        /* in promiscuous mode, we accept errored packets,
         * so we have to enable interrupts on them also
         */
-       writereg(dev, PP_RxCFG,
-                (lp->curr_rx_cfg |
-                 (lp->rx_mode == RX_ALL_ACCEPT)
-                 ? (RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL)
-                 : 0));
+       cfg = lp->curr_rx_cfg;
+       if (lp->rx_mode == RX_ALL_ACCEPT)
+               cfg |= RX_CRC_ERROR_ENBL | RX_RUNT_ENBL | RX_EXTRA_DATA_ENBL;
+       writereg(dev, PP_RxCFG, cfg);
        spin_unlock_irqrestore(&lp->lock, flags);
 }
 
index 7fac97b4bb59c19ecaca1073d84c6a183ecd17b1..8c63d06ab12b6ccf899fae8fa13f75904beb22c1 100644 (file)
@@ -259,7 +259,7 @@ int be_process_mcc(struct be_adapter *adapter)
        int num = 0, status = 0;
        struct be_mcc_obj *mcc_obj = &adapter->mcc_obj;
 
-       spin_lock_bh(&adapter->mcc_cq_lock);
+       spin_lock(&adapter->mcc_cq_lock);
        while ((compl = be_mcc_compl_get(adapter))) {
                if (compl->flags & CQE_FLAGS_ASYNC_MASK) {
                        /* Interpret flags as an async trailer */
@@ -280,7 +280,7 @@ int be_process_mcc(struct be_adapter *adapter)
        if (num)
                be_cq_notify(adapter, mcc_obj->cq.id, mcc_obj->rearm_cq, num);
 
-       spin_unlock_bh(&adapter->mcc_cq_lock);
+       spin_unlock(&adapter->mcc_cq_lock);
        return status;
 }
 
@@ -295,7 +295,9 @@ static int be_mcc_wait_compl(struct be_adapter *adapter)
                if (be_error(adapter))
                        return -EIO;
 
+               local_bh_disable();
                status = be_process_mcc(adapter);
+               local_bh_enable();
 
                if (atomic_read(&mcc_obj->q.used) == 0)
                        break;
index 90a903d83d8747ca26d711b7b3a188f81a554611..78b8aa8069f03c440ea6037f9dc3e86e81c62fe6 100644 (file)
@@ -3763,7 +3763,9 @@ static void be_worker(struct work_struct *work)
        /* when interrupts are not yet enabled, just reap any pending
        * mcc completions */
        if (!netif_running(adapter->netdev)) {
+               local_bh_disable();
                be_process_mcc(adapter);
+               local_bh_enable();
                goto reschedule;
        }
 
index 4605f7246687d0898ad82e9c769026c741d6d540..d3233f59a82e47b1d70a372c0973e1447d0ef90b 100644 (file)
@@ -1041,7 +1041,7 @@ static int gfar_probe(struct platform_device *ofdev)
 
        if (priv->device_flags & FSL_GIANFAR_DEV_HAS_VLAN) {
                dev->hw_features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
-               dev->features |= NETIF_F_HW_VLAN_TX | NETIF_F_HW_VLAN_RX;
+               dev->features |= NETIF_F_HW_VLAN_RX;
        }
 
        if (priv->device_flags & FSL_GIANFAR_DEV_HAS_EXTENDED_HASH) {
index 8971921cc1c84966170b7f7a6350732f93b416e9..ab6762caa95702f492bbb457deae8986257bdcc4 100644 (file)
@@ -1773,6 +1773,7 @@ static int gfar_get_nfc(struct net_device *dev, struct ethtool_rxnfc *cmd,
 }
 
 int gfar_phc_index = -1;
+EXPORT_SYMBOL(gfar_phc_index);
 
 static int gfar_get_ts_info(struct net_device *dev,
                            struct ethtool_ts_info *info)
index c08e5d40fecb425c7f6c26b8de269d270bac727f..0daa66b8eca088735974f7ee45595d22c6be4c56 100644 (file)
@@ -515,7 +515,7 @@ static int gianfar_ptp_probe(struct platform_device *dev)
                err = PTR_ERR(etsects->clock);
                goto no_clock;
        }
-       gfar_phc_clock = ptp_clock_index(etsects->clock);
+       gfar_phc_index = ptp_clock_index(etsects->clock);
 
        dev_set_drvdata(&dev->dev, etsects);
 
@@ -539,7 +539,7 @@ static int gianfar_ptp_remove(struct platform_device *dev)
        gfar_write(&etsects->regs->tmr_temask, 0);
        gfar_write(&etsects->regs->tmr_ctrl,   0);
 
-       gfar_phc_clock = -1;
+       gfar_phc_index = -1;
        ptp_clock_unregister(etsects->clock);
        iounmap(etsects->regs);
        release_resource(etsects->rsrc);
index bd1f1ef91e1910f81f454a7332337870fa031331..ba4e0cea3506f80da5cc36a69f22994a7a3e470e 100644 (file)
@@ -139,8 +139,11 @@ struct znet_private {
 /* Only one can be built-in;-> */
 static struct net_device *znet_dev;
 
+#define NETIDBLK_MAGIC         "NETIDBLK"
+#define NETIDBLK_MAGIC_SIZE    8
+
 struct netidblk {
-       char magic[8];          /* The magic number (string) "NETIDBLK" */
+       char magic[NETIDBLK_MAGIC_SIZE];        /* The magic number (string) "NETIDBLK" */
        unsigned char netid[8]; /* The physical station address */
        char nettype, globalopt;
        char vendor[8];         /* The machine vendor and product name. */
@@ -373,14 +376,16 @@ static int __init znet_probe (void)
        struct znet_private *znet;
        struct net_device *dev;
        char *p;
+       char *plast = phys_to_virt(0x100000 - NETIDBLK_MAGIC_SIZE);
        int err = -ENOMEM;
 
        /* This code scans the region 0xf0000 to 0xfffff for a "NETIDBLK". */
-       for(p = (char *)phys_to_virt(0xf0000); p < (char *)phys_to_virt(0x100000); p++)
-               if (*p == 'N'  &&  strncmp(p, "NETIDBLK", 8) == 0)
+       for(p = (char *)phys_to_virt(0xf0000); p <= plast; p++)
+               if (*p == 'N' &&
+                   strncmp(p, NETIDBLK_MAGIC, NETIDBLK_MAGIC_SIZE) == 0)
                        break;
 
-       if (p >= (char *)phys_to_virt(0x100000)) {
+       if (p > plast) {
                if (znet_debug > 1)
                        printk(KERN_INFO "No Z-Note ethernet adaptor found.\n");
                return -ENODEV;
index 9010cea68bc3094a4b9b18b06cae1aa7d9796cd7..b68d28a130e664e2042bbb9a4335710964f861a7 100644 (file)
@@ -472,14 +472,9 @@ static void ibmveth_cleanup(struct ibmveth_adapter *adapter)
        }
 
        if (adapter->rx_queue.queue_addr != NULL) {
-               if (!dma_mapping_error(dev, adapter->rx_queue.queue_dma)) {
-                       dma_unmap_single(dev,
-                                       adapter->rx_queue.queue_dma,
-                                       adapter->rx_queue.queue_len,
-                                       DMA_BIDIRECTIONAL);
-                       adapter->rx_queue.queue_dma = DMA_ERROR_CODE;
-               }
-               kfree(adapter->rx_queue.queue_addr);
+               dma_free_coherent(dev, adapter->rx_queue.queue_len,
+                                 adapter->rx_queue.queue_addr,
+                                 adapter->rx_queue.queue_dma);
                adapter->rx_queue.queue_addr = NULL;
        }
 
@@ -556,10 +551,13 @@ static int ibmveth_open(struct net_device *netdev)
                goto err_out;
        }
 
+       dev = &adapter->vdev->dev;
+
        adapter->rx_queue.queue_len = sizeof(struct ibmveth_rx_q_entry) *
                                                rxq_entries;
-       adapter->rx_queue.queue_addr = kmalloc(adapter->rx_queue.queue_len,
-                                               GFP_KERNEL);
+       adapter->rx_queue.queue_addr =
+           dma_alloc_coherent(dev, adapter->rx_queue.queue_len,
+                              &adapter->rx_queue.queue_dma, GFP_KERNEL);
 
        if (!adapter->rx_queue.queue_addr) {
                netdev_err(netdev, "unable to allocate rx queue pages\n");
@@ -567,19 +565,13 @@ static int ibmveth_open(struct net_device *netdev)
                goto err_out;
        }
 
-       dev = &adapter->vdev->dev;
-
        adapter->buffer_list_dma = dma_map_single(dev,
                        adapter->buffer_list_addr, 4096, DMA_BIDIRECTIONAL);
        adapter->filter_list_dma = dma_map_single(dev,
                        adapter->filter_list_addr, 4096, DMA_BIDIRECTIONAL);
-       adapter->rx_queue.queue_dma = dma_map_single(dev,
-                       adapter->rx_queue.queue_addr,
-                       adapter->rx_queue.queue_len, DMA_BIDIRECTIONAL);
 
        if ((dma_mapping_error(dev, adapter->buffer_list_dma)) ||
-           (dma_mapping_error(dev, adapter->filter_list_dma)) ||
-           (dma_mapping_error(dev, adapter->rx_queue.queue_dma))) {
+           (dma_mapping_error(dev, adapter->filter_list_dma))) {
                netdev_err(netdev, "unable to map filter or buffer list "
                           "pages\n");
                rc = -ENOMEM;
index 3bfbb8df898935f4acf47a52ebb8be3f0f683a67..bde337ee1a34f954e90c583711f155eec87b633e 100644 (file)
@@ -3149,6 +3149,17 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                return NETDEV_TX_OK;
        }
 
+       /* On PCI/PCI-X HW, if packet size is less than ETH_ZLEN,
+        * packets may get corrupted during padding by HW.
+        * To WA this issue, pad all small packets manually.
+        */
+       if (skb->len < ETH_ZLEN) {
+               if (skb_pad(skb, ETH_ZLEN - skb->len))
+                       return NETDEV_TX_OK;
+               skb->len = ETH_ZLEN;
+               skb_set_tail_pointer(skb, ETH_ZLEN);
+       }
+
        mss = skb_shinfo(skb)->gso_size;
        /* The controller does a simple calculation to
         * make sure there is enough room in the FIFO before
index cd153326c3cf8254543b0b544f0dfd8443cd6736..cb3356c9af803509efb2c58ff4f7d0667e689e1c 100644 (file)
@@ -310,6 +310,7 @@ struct e1000_adapter {
         */
        struct e1000_ring *tx_ring /* One per active queue */
                                                ____cacheline_aligned_in_smp;
+       u32 tx_fifo_limit;
 
        struct napi_struct napi;
 
index 46c3b1f9ff8997af685836bb82fb0e1bd5e599cf..d01a099475a143a44253b83ef212d8ad1f5935bf 100644 (file)
@@ -3516,6 +3516,15 @@ void e1000e_reset(struct e1000_adapter *adapter)
                break;
        }
 
+       /*
+        * Alignment of Tx data is on an arbitrary byte boundary with the
+        * maximum size per Tx descriptor limited only to the transmit
+        * allocation of the packet buffer minus 96 bytes with an upper
+        * limit of 24KB due to receive synchronization limitations.
+        */
+       adapter->tx_fifo_limit = min_t(u32, ((er32(PBA) >> 16) << 10) - 96,
+                                      24 << 10);
+
        /*
         * Disable Adaptive Interrupt Moderation if 2 full packets cannot
         * fit in receive buffer.
@@ -4785,12 +4794,9 @@ static bool e1000_tx_csum(struct e1000_ring *tx_ring, struct sk_buff *skb)
        return 1;
 }
 
-#define E1000_MAX_PER_TXD      8192
-#define E1000_MAX_TXD_PWR      12
-
 static int e1000_tx_map(struct e1000_ring *tx_ring, struct sk_buff *skb,
                        unsigned int first, unsigned int max_per_txd,
-                       unsigned int nr_frags, unsigned int mss)
+                       unsigned int nr_frags)
 {
        struct e1000_adapter *adapter = tx_ring->adapter;
        struct pci_dev *pdev = adapter->pdev;
@@ -5023,20 +5029,19 @@ static int __e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
 
 static int e1000_maybe_stop_tx(struct e1000_ring *tx_ring, int size)
 {
+       BUG_ON(size > tx_ring->count);
+
        if (e1000_desc_unused(tx_ring) >= size)
                return 0;
        return __e1000_maybe_stop_tx(tx_ring, size);
 }
 
-#define TXD_USE_COUNT(S, X) (((S) >> (X)) + 1)
 static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                                    struct net_device *netdev)
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        struct e1000_ring *tx_ring = adapter->tx_ring;
        unsigned int first;
-       unsigned int max_per_txd = E1000_MAX_PER_TXD;
-       unsigned int max_txd_pwr = E1000_MAX_TXD_PWR;
        unsigned int tx_flags = 0;
        unsigned int len = skb_headlen(skb);
        unsigned int nr_frags;
@@ -5056,18 +5061,8 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
        }
 
        mss = skb_shinfo(skb)->gso_size;
-       /*
-        * The controller does a simple calculation to
-        * make sure there is enough room in the FIFO before
-        * initiating the DMA for each buffer.  The calc is:
-        * 4 = ceil(buffer len/mss).  To make sure we don't
-        * overrun the FIFO, adjust the max buffer len if mss
-        * drops.
-        */
        if (mss) {
                u8 hdr_len;
-               max_per_txd = min(mss << 2, max_per_txd);
-               max_txd_pwr = fls(max_per_txd) - 1;
 
                /*
                 * TSO Workaround for 82571/2/3 Controllers -- if skb->data
@@ -5097,12 +5092,12 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                count++;
        count++;
 
-       count += TXD_USE_COUNT(len, max_txd_pwr);
+       count += DIV_ROUND_UP(len, adapter->tx_fifo_limit);
 
        nr_frags = skb_shinfo(skb)->nr_frags;
        for (f = 0; f < nr_frags; f++)
-               count += TXD_USE_COUNT(skb_frag_size(&skb_shinfo(skb)->frags[f]),
-                                      max_txd_pwr);
+               count += DIV_ROUND_UP(skb_frag_size(&skb_shinfo(skb)->frags[f]),
+                                     adapter->tx_fifo_limit);
 
        if (adapter->hw.mac.tx_pkt_filtering)
                e1000_transfer_dhcp_info(adapter, skb);
@@ -5144,15 +5139,18 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                tx_flags |= E1000_TX_FLAGS_NO_FCS;
 
        /* if count is 0 then mapping error has occurred */
-       count = e1000_tx_map(tx_ring, skb, first, max_per_txd, nr_frags, mss);
+       count = e1000_tx_map(tx_ring, skb, first, adapter->tx_fifo_limit,
+                            nr_frags);
        if (count) {
                skb_tx_timestamp(skb);
 
                netdev_sent_queue(netdev, skb->len);
                e1000_tx_queue(tx_ring, tx_flags, count);
                /* Make sure there is space in the ring for the next send. */
-               e1000_maybe_stop_tx(tx_ring, MAX_SKB_FRAGS + 2);
-
+               e1000_maybe_stop_tx(tx_ring,
+                                   (MAX_SKB_FRAGS *
+                                    DIV_ROUND_UP(PAGE_SIZE,
+                                                 adapter->tx_fifo_limit) + 2));
        } else {
                dev_kfree_skb_any(skb);
                tx_ring->buffer_info[first].time_stamp = 0;
@@ -6327,8 +6325,8 @@ static int __devinit e1000_probe(struct pci_dev *pdev,
        adapter->hw.phy.autoneg_advertised = 0x2f;
 
        /* ring size defaults */
-       adapter->rx_ring->count = 256;
-       adapter->tx_ring->count = 256;
+       adapter->rx_ring->count = E1000_DEFAULT_RXD;
+       adapter->tx_ring->count = E1000_DEFAULT_TXD;
 
        /*
         * Initial Wake on LAN setting - If APM wake is enabled in
index daf41792366147c7381e9f8f7f1017489c55a57e..31d02649be41f2317d16f178f88bc1f19153352a 100644 (file)
@@ -227,9 +227,10 @@ int mlx4_UNMAP_ICM_AUX(struct mlx4_dev *dev)
                        MLX4_CMD_TIME_CLASS_B, MLX4_CMD_NATIVE);
 }
 
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
+int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
 {
-       int i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
+       u32 i = (obj & (table->num_obj - 1)) /
+                       (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
        int ret = 0;
 
        mutex_lock(&table->mutex);
@@ -262,16 +263,18 @@ out:
        return ret;
 }
 
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
+void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj)
 {
-       int i;
+       u32 i;
+       u64 offset;
 
        i = (obj & (table->num_obj - 1)) / (MLX4_TABLE_CHUNK_SIZE / table->obj_size);
 
        mutex_lock(&table->mutex);
 
        if (--table->icm[i]->refcount == 0) {
-               mlx4_UNMAP_ICM(dev, table->virt + i * MLX4_TABLE_CHUNK_SIZE,
+               offset = (u64) i * MLX4_TABLE_CHUNK_SIZE;
+               mlx4_UNMAP_ICM(dev, table->virt + offset,
                               MLX4_TABLE_CHUNK_SIZE / MLX4_ICM_PAGE_SIZE);
                mlx4_free_icm(dev, table->icm[i], table->coherent);
                table->icm[i] = NULL;
@@ -280,9 +283,11 @@ void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj)
        mutex_unlock(&table->mutex);
 }
 
-void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle)
+void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
+                       dma_addr_t *dma_handle)
 {
-       int idx, offset, dma_offset, i;
+       int offset, dma_offset, i;
+       u64 idx;
        struct mlx4_icm_chunk *chunk;
        struct mlx4_icm *icm;
        struct page *page = NULL;
@@ -292,7 +297,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_han
 
        mutex_lock(&table->mutex);
 
-       idx = (obj & (table->num_obj - 1)) * table->obj_size;
+       idx = (u64) (obj & (table->num_obj - 1)) * table->obj_size;
        icm = table->icm[idx / MLX4_TABLE_CHUNK_SIZE];
        dma_offset = offset = idx % MLX4_TABLE_CHUNK_SIZE;
 
@@ -326,10 +331,11 @@ out:
 }
 
 int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
-                        int start, int end)
+                        u32 start, u32 end)
 {
        int inc = MLX4_TABLE_CHUNK_SIZE / table->obj_size;
-       int i, err;
+       int err;
+       u32 i;
 
        for (i = start; i <= end; i += inc) {
                err = mlx4_table_get(dev, table, i);
@@ -349,9 +355,9 @@ fail:
 }
 
 void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
-                         int start, int end)
+                         u32 start, u32 end)
 {
-       int i;
+       u32 i;
 
        for (i = start; i <= end; i += MLX4_TABLE_CHUNK_SIZE / table->obj_size)
                mlx4_table_put(dev, table, i);
index a67744f53506af7f86c0de581445e1e67568de7f..dee67fa39107f890508e158e56b680af6496d74a 100644 (file)
@@ -71,17 +71,17 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                                gfp_t gfp_mask, int coherent);
 void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent);
 
-int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
-void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, int obj);
+int mlx4_table_get(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
+void mlx4_table_put(struct mlx4_dev *dev, struct mlx4_icm_table *table, u32 obj);
 int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
-                        int start, int end);
+                        u32 start, u32 end);
 void mlx4_table_put_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
-                         int start, int end);
+                         u32 start, u32 end);
 int mlx4_init_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table,
                        u64 virt, int obj_size, u32 nobj, int reserved,
                        int use_lowmem, int use_coherent);
 void mlx4_cleanup_icm_table(struct mlx4_dev *dev, struct mlx4_icm_table *table);
-void *mlx4_table_find(struct mlx4_icm_table *table, int obj, dma_addr_t *dma_handle);
+void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj, dma_addr_t *dma_handle);
 
 static inline void mlx4_icm_first(struct mlx4_icm *icm,
                                  struct mlx4_icm_iter *iter)
index 827b72dfce99690093f0fe81ee3ccf804d59db85..2f816c6aed72da16bc6afc22c957f0b6c7a5eac0 100644 (file)
@@ -1234,13 +1234,13 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                                mlx4_info(dev, "non-primary physical function, skipping.\n");
                        else
                                mlx4_err(dev, "QUERY_FW command failed, aborting.\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                err = mlx4_load_fw(dev);
                if (err) {
                        mlx4_err(dev, "Failed to start FW, aborting.\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                mlx4_cfg.log_pg_sz_m = 1;
@@ -1304,7 +1304,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
                err = mlx4_init_slave(dev);
                if (err) {
                        mlx4_err(dev, "Failed to initialize slave\n");
-                       goto unmap_bf;
+                       return err;
                }
 
                err = mlx4_slave_cap(dev);
@@ -1324,7 +1324,7 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
        err = mlx4_QUERY_ADAPTER(dev, &adapter);
        if (err) {
                mlx4_err(dev, "QUERY_ADAPTER command failed, aborting.\n");
-               goto err_close;
+               goto unmap_bf;
        }
 
        priv->eq_table.inta_pin = adapter.inta_pin;
@@ -1332,6 +1332,9 @@ static int mlx4_init_hca(struct mlx4_dev *dev)
 
        return 0;
 
+unmap_bf:
+       unmap_bf_area(dev);
+
 err_close:
        mlx4_close_hca(dev);
 
@@ -1344,8 +1347,6 @@ err_stop_fw:
                mlx4_UNMAP_FA(dev);
                mlx4_free_icm(dev, priv->fw.fw_icm, 0);
        }
-unmap_bf:
-       unmap_bf_area(dev);
        return err;
 }
 
@@ -1996,7 +1997,8 @@ static int __mlx4_init_one(struct pci_dev *pdev, const struct pci_device_id *id)
        }
 
 slave_start:
-       if (mlx4_cmd_init(dev)) {
+       err = mlx4_cmd_init(dev);
+       if (err) {
                mlx4_err(dev, "Failed to init command interface, aborting.\n");
                goto err_sriov;
        }
index a018ea2a43deb9c67e773032e62d8a83f54bb3d9..e151c21baf2baf5970c9c232c79d0c8650c0eb4e 100644 (file)
@@ -137,11 +137,11 @@ static int mlx4_GID_HASH(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox,
        return err;
 }
 
-static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 pf_num,
+static struct mlx4_promisc_qp *get_promisc_qp(struct mlx4_dev *dev, u8 port,
                                              enum mlx4_steer_type steer,
                                              u32 qpn)
 {
-       struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[pf_num];
+       struct mlx4_steer *s_steer = &mlx4_priv(dev)->steer[port - 1];
        struct mlx4_promisc_qp *pqp;
 
        list_for_each_entry(pqp, &s_steer->promisc_qps[steer], list) {
@@ -182,7 +182,7 @@ static int new_steering_entry(struct mlx4_dev *dev, u8 port,
        /* If the given qpn is also a promisc qp,
         * it should be inserted to duplicates list
         */
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (pqp) {
                dqp = kmalloc(sizeof *dqp, GFP_KERNEL);
                if (!dqp) {
@@ -256,7 +256,7 @@ static int existing_steering_entry(struct mlx4_dev *dev, u8 port,
 
        s_steer = &mlx4_priv(dev)->steer[port - 1];
 
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (!pqp)
                return 0; /* nothing to do */
 
@@ -302,7 +302,7 @@ static bool check_duplicate_entry(struct mlx4_dev *dev, u8 port,
        s_steer = &mlx4_priv(dev)->steer[port - 1];
 
        /* if qp is not promisc, it cannot be duplicated */
-       if (!get_promisc_qp(dev, 0, steer, qpn))
+       if (!get_promisc_qp(dev, port, steer, qpn))
                return false;
 
        /* The qp is promisc qp so it is a duplicate on this index
@@ -352,7 +352,7 @@ static bool can_remove_steering_entry(struct mlx4_dev *dev, u8 port,
        members_count = be32_to_cpu(mgm->members_count) & 0xffffff;
        for (i = 0;  i < members_count; i++) {
                qpn = be32_to_cpu(mgm->qp[i]) & MGM_QPN_MASK;
-               if (!get_promisc_qp(dev, 0, steer, qpn) && qpn != tqpn) {
+               if (!get_promisc_qp(dev, port, steer, qpn) && qpn != tqpn) {
                        /* the qp is not promisc, the entry can't be removed */
                        goto out;
                }
@@ -398,7 +398,7 @@ static int add_promisc_qp(struct mlx4_dev *dev, u8 port,
 
        mutex_lock(&priv->mcg_table.mutex);
 
-       if (get_promisc_qp(dev, 0, steer, qpn)) {
+       if (get_promisc_qp(dev, port, steer, qpn)) {
                err = 0;  /* Noting to do, already exists */
                goto out_mutex;
        }
@@ -503,7 +503,7 @@ static int remove_promisc_qp(struct mlx4_dev *dev, u8 port,
        s_steer = &mlx4_priv(dev)->steer[port - 1];
        mutex_lock(&priv->mcg_table.mutex);
 
-       pqp = get_promisc_qp(dev, 0, steer, qpn);
+       pqp = get_promisc_qp(dev, port, steer, qpn);
        if (unlikely(!pqp)) {
                mlx4_warn(dev, "QP %x is not promiscuous QP\n", qpn);
                /* nothing to do */
@@ -650,13 +650,6 @@ static int find_entry(struct mlx4_dev *dev, u8 port,
        return err;
 }
 
-struct mlx4_net_trans_rule_hw_ctrl {
-       __be32 ctrl;
-       __be32 vf_vep_port;
-       __be32 qpn;
-       __be32 reserved;
-};
-
 static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
                                  struct mlx4_net_trans_rule_hw_ctrl *hw)
 {
@@ -680,87 +673,18 @@ static void trans_rule_ctrl_to_hw(struct mlx4_net_trans_rule *ctrl,
        hw->qpn = cpu_to_be32(ctrl->qpn);
 }
 
-struct mlx4_net_trans_rule_hw_ib {
-       u8      size;
-       u8      rsvd1;
-       __be16  id;
-       u32     rsvd2;
-       __be32  qpn;
-       __be32  qpn_mask;
-       u8      dst_gid[16];
-       u8      dst_gid_msk[16];
-} __packed;
-
-struct mlx4_net_trans_rule_hw_eth {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       u8      rsvd1[6];
-       u8      dst_mac[6];
-       u16     rsvd2;
-       u8      dst_mac_msk[6];
-       u16     rsvd3;
-       u8      src_mac[6];
-       u16     rsvd4;
-       u8      src_mac_msk[6];
-       u8      rsvd5;
-       u8      ether_type_enable;
-       __be16  ether_type;
-       __be16  vlan_id_msk;
-       __be16  vlan_id;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_tcp_udp {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       __be16  rsvd1[3];
-       __be16  dst_port;
-       __be16  rsvd2;
-       __be16  dst_port_msk;
-       __be16  rsvd3;
-       __be16  src_port;
-       __be16  rsvd4;
-       __be16  src_port_msk;
-} __packed;
-
-struct mlx4_net_trans_rule_hw_ipv4 {
-       u8      size;
-       u8      rsvd;
-       __be16  id;
-       __be32  rsvd1;
-       __be32  dst_ip;
-       __be32  dst_ip_msk;
-       __be32  src_ip;
-       __be32  src_ip_msk;
-} __packed;
-
-struct _rule_hw {
-       union {
-               struct {
-                       u8 size;
-                       u8 rsvd;
-                       __be16 id;
-               };
-               struct mlx4_net_trans_rule_hw_eth eth;
-               struct mlx4_net_trans_rule_hw_ib ib;
-               struct mlx4_net_trans_rule_hw_ipv4 ipv4;
-               struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
-       };
+const u16 __sw_id_hw[] = {
+       [MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001,
+       [MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005,
+       [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
+       [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
+       [MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
+       [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
 };
 
 static int parse_trans_rule(struct mlx4_dev *dev, struct mlx4_spec_list *spec,
                            struct _rule_hw *rule_hw)
 {
-       static const u16 __sw_id_hw[] = {
-               [MLX4_NET_TRANS_RULE_ID_ETH]     = 0xE001,
-               [MLX4_NET_TRANS_RULE_ID_IB]      = 0xE005,
-               [MLX4_NET_TRANS_RULE_ID_IPV6]    = 0xE003,
-               [MLX4_NET_TRANS_RULE_ID_IPV4]    = 0xE002,
-               [MLX4_NET_TRANS_RULE_ID_TCP]     = 0xE004,
-               [MLX4_NET_TRANS_RULE_ID_UDP]     = 0xE006
-       };
-
        static const size_t __rule_hw_sz[] = {
                [MLX4_NET_TRANS_RULE_ID_ETH] =
                        sizeof(struct mlx4_net_trans_rule_hw_eth),
index 4d9df8f2a12617047355fc9988d5187af80a95f5..dba69d98734a29b9a10038e22eff8e93714147ed 100644 (file)
@@ -690,6 +690,82 @@ struct mlx4_steer {
        struct list_head steer_entries[MLX4_NUM_STEERS];
 };
 
+struct mlx4_net_trans_rule_hw_ctrl {
+       __be32 ctrl;
+       __be32 vf_vep_port;
+       __be32 qpn;
+       __be32 reserved;
+};
+
+struct mlx4_net_trans_rule_hw_ib {
+       u8 size;
+       u8 rsvd1;
+       __be16 id;
+       u32 rsvd2;
+       __be32 qpn;
+       __be32 qpn_mask;
+       u8 dst_gid[16];
+       u8 dst_gid_msk[16];
+} __packed;
+
+struct mlx4_net_trans_rule_hw_eth {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       u8      rsvd1[6];
+       u8      dst_mac[6];
+       u16     rsvd2;
+       u8      dst_mac_msk[6];
+       u16     rsvd3;
+       u8      src_mac[6];
+       u16     rsvd4;
+       u8      src_mac_msk[6];
+       u8      rsvd5;
+       u8      ether_type_enable;
+       __be16  ether_type;
+       __be16  vlan_id_msk;
+       __be16  vlan_id;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_tcp_udp {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be16  rsvd1[3];
+       __be16  dst_port;
+       __be16  rsvd2;
+       __be16  dst_port_msk;
+       __be16  rsvd3;
+       __be16  src_port;
+       __be16  rsvd4;
+       __be16  src_port_msk;
+} __packed;
+
+struct mlx4_net_trans_rule_hw_ipv4 {
+       u8      size;
+       u8      rsvd;
+       __be16  id;
+       __be32  rsvd1;
+       __be32  dst_ip;
+       __be32  dst_ip_msk;
+       __be32  src_ip;
+       __be32  src_ip_msk;
+} __packed;
+
+struct _rule_hw {
+       union {
+               struct {
+                       u8 size;
+                       u8 rsvd;
+                       __be16 id;
+               };
+               struct mlx4_net_trans_rule_hw_eth eth;
+               struct mlx4_net_trans_rule_hw_ib ib;
+               struct mlx4_net_trans_rule_hw_ipv4 ipv4;
+               struct mlx4_net_trans_rule_hw_tcp_udp tcp_udp;
+       };
+};
+
 struct mlx4_priv {
        struct mlx4_dev         dev;
 
index 94ceddd17ab28a3ea13a15ea4c7ec1211042278f..293c9e820c49b5d470dce7eda95f2252b94d4251 100644 (file)
@@ -42,6 +42,7 @@
 #include <linux/mlx4/cmd.h>
 #include <linux/mlx4/qp.h>
 #include <linux/if_ether.h>
+#include <linux/etherdevice.h>
 
 #include "mlx4.h"
 #include "fw.h"
@@ -2776,18 +2777,133 @@ ex_put:
        return err;
 }
 
+/*
+ * MAC validation for Flow Steering rules.
+ * VF can attach rules only with a mac address which is assigned to it.
+ */
+static int validate_eth_header_mac(int slave, struct _rule_hw *eth_header,
+                                  struct list_head *rlist)
+{
+       struct mac_res *res, *tmp;
+       __be64 be_mac;
+
+       /* make sure it isn't multicast or broadcast mac*/
+       if (!is_multicast_ether_addr(eth_header->eth.dst_mac) &&
+           !is_broadcast_ether_addr(eth_header->eth.dst_mac)) {
+               list_for_each_entry_safe(res, tmp, rlist, list) {
+                       be_mac = cpu_to_be64(res->mac << 16);
+                       if (!memcmp(&be_mac, eth_header->eth.dst_mac, ETH_ALEN))
+                               return 0;
+               }
+               pr_err("MAC %pM doesn't belong to VF %d, Steering rule rejected\n",
+                      eth_header->eth.dst_mac, slave);
+               return -EINVAL;
+       }
+       return 0;
+}
+
+/*
+ * In case of missing eth header, append eth header with a MAC address
+ * assigned to the VF.
+ */
+static int add_eth_header(struct mlx4_dev *dev, int slave,
+                         struct mlx4_cmd_mailbox *inbox,
+                         struct list_head *rlist, int header_id)
+{
+       struct mac_res *res, *tmp;
+       u8 port;
+       struct mlx4_net_trans_rule_hw_ctrl *ctrl;
+       struct mlx4_net_trans_rule_hw_eth *eth_header;
+       struct mlx4_net_trans_rule_hw_ipv4 *ip_header;
+       struct mlx4_net_trans_rule_hw_tcp_udp *l4_header;
+       __be64 be_mac = 0;
+       __be64 mac_msk = cpu_to_be64(MLX4_MAC_MASK << 16);
+
+       ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+       port = be32_to_cpu(ctrl->vf_vep_port) & 0xff;
+       eth_header = (struct mlx4_net_trans_rule_hw_eth *)(ctrl + 1);
+
+       /* Clear a space in the inbox for eth header */
+       switch (header_id) {
+       case MLX4_NET_TRANS_RULE_ID_IPV4:
+               ip_header =
+                       (struct mlx4_net_trans_rule_hw_ipv4 *)(eth_header + 1);
+               memmove(ip_header, eth_header,
+                       sizeof(*ip_header) + sizeof(*l4_header));
+               break;
+       case MLX4_NET_TRANS_RULE_ID_TCP:
+       case MLX4_NET_TRANS_RULE_ID_UDP:
+               l4_header = (struct mlx4_net_trans_rule_hw_tcp_udp *)
+                           (eth_header + 1);
+               memmove(l4_header, eth_header, sizeof(*l4_header));
+               break;
+       default:
+               return -EINVAL;
+       }
+       list_for_each_entry_safe(res, tmp, rlist, list) {
+               if (port == res->port) {
+                       be_mac = cpu_to_be64(res->mac << 16);
+                       break;
+               }
+       }
+       if (!be_mac) {
+               pr_err("Failed adding eth header to FS rule, Can't find matching MAC for port %d .\n",
+                      port);
+               return -EINVAL;
+       }
+
+       memset(eth_header, 0, sizeof(*eth_header));
+       eth_header->size = sizeof(*eth_header) >> 2;
+       eth_header->id = cpu_to_be16(__sw_id_hw[MLX4_NET_TRANS_RULE_ID_ETH]);
+       memcpy(eth_header->dst_mac, &be_mac, ETH_ALEN);
+       memcpy(eth_header->dst_mac_msk, &mac_msk, ETH_ALEN);
+
+       return 0;
+
+}
+
 int mlx4_QP_FLOW_STEERING_ATTACH_wrapper(struct mlx4_dev *dev, int slave,
                                         struct mlx4_vhcr *vhcr,
                                         struct mlx4_cmd_mailbox *inbox,
                                         struct mlx4_cmd_mailbox *outbox,
                                         struct mlx4_cmd_info *cmd)
 {
+
+       struct mlx4_priv *priv = mlx4_priv(dev);
+       struct mlx4_resource_tracker *tracker = &priv->mfunc.master.res_tracker;
+       struct list_head *rlist = &tracker->slave_list[slave].res_list[RES_MAC];
        int err;
+       struct mlx4_net_trans_rule_hw_ctrl *ctrl;
+       struct _rule_hw  *rule_header;
+       int header_id;
 
        if (dev->caps.steering_mode !=
            MLX4_STEERING_MODE_DEVICE_MANAGED)
                return -EOPNOTSUPP;
 
+       ctrl = (struct mlx4_net_trans_rule_hw_ctrl *)inbox->buf;
+       rule_header = (struct _rule_hw *)(ctrl + 1);
+       header_id = map_hw_to_sw_id(be16_to_cpu(rule_header->id));
+
+       switch (header_id) {
+       case MLX4_NET_TRANS_RULE_ID_ETH:
+               if (validate_eth_header_mac(slave, rule_header, rlist))
+                       return -EINVAL;
+               break;
+       case MLX4_NET_TRANS_RULE_ID_IPV4:
+       case MLX4_NET_TRANS_RULE_ID_TCP:
+       case MLX4_NET_TRANS_RULE_ID_UDP:
+               pr_warn("Can't attach FS rule without L2 headers, adding L2 header.\n");
+               if (add_eth_header(dev, slave, inbox, rlist, header_id))
+                       return -EINVAL;
+               vhcr->in_modifier +=
+                       sizeof(struct mlx4_net_trans_rule_hw_eth) >> 2;
+               break;
+       default:
+               pr_err("Corrupted mailbox.\n");
+               return -EINVAL;
+       }
+
        err = mlx4_cmd_imm(dev, inbox->dma, &vhcr->out_param,
                           vhcr->in_modifier, 0,
                           MLX4_QP_FLOW_STEERING_ATTACH, MLX4_CMD_TIME_CLASS_A,
index c42bbb16cdaebdeb7147dc887705abcfe91e86e0..a688a2ddcfd612866edbce5f8ee08b7f92fbd8e0 100644 (file)
@@ -722,10 +722,8 @@ static int octeon_mgmt_init_phy(struct net_device *netdev)
                                   octeon_mgmt_adjust_link, 0,
                                   PHY_INTERFACE_MODE_MII);
 
-       if (IS_ERR(p->phydev)) {
-               p->phydev = NULL;
+       if (!p->phydev)
                return -1;
-       }
 
        phy_start_aneg(p->phydev);
 
index e559dfa06d6ace1c349cf48efe33738ef642e778..6fa74d530e44d390ce87946b8327a476e5a728e5 100644 (file)
@@ -1101,9 +1101,9 @@ static int pasemi_mac_phy_init(struct net_device *dev)
        phydev = of_phy_connect(dev, phy_dn, &pasemi_adjust_link, 0,
                                PHY_INTERFACE_MODE_SGMII);
 
-       if (IS_ERR(phydev)) {
+       if (!phydev) {
                printk(KERN_ERR "%s: Could not attach to phy\n", dev->name);
-               return PTR_ERR(phydev);
+               return -ENODEV;
        }
 
        mac->phydev = phydev;
index 342b3a79bd0fd7a6a6bde8860446c20c78595ef2..a77c558d8f4078e7cc4747a5308dc315e34d99c1 100644 (file)
@@ -1378,6 +1378,10 @@ static void netxen_mask_aer_correctable(struct netxen_adapter *adapter)
        struct pci_dev *root = pdev->bus->self;
        u32 aer_pos;
 
+       /* root bus? */
+       if (!root)
+               return;
+
        if (adapter->ahw.board_type != NETXEN_BRDTYPE_P3_4_GB_MM &&
                adapter->ahw.board_type != NETXEN_BRDTYPE_P3_10G_TP)
                return;
index b8ead696141efbaf452f3a46c23dfba1f199f2fb..2a179d087207e4375afb0d66f712043a10417786 100644 (file)
@@ -15,7 +15,7 @@ qlcnic_poll_rsp(struct qlcnic_adapter *adapter)
 
        do {
                /* give atleast 1ms for firmware to respond */
-               msleep(1);
+               mdelay(1);
 
                if (++timeout > QLCNIC_OS_CRB_RETRY_COUNT)
                        return QLCNIC_CDRP_RSP_TIMEOUT;
@@ -601,7 +601,7 @@ void qlcnic_fw_destroy_ctx(struct qlcnic_adapter *adapter)
                qlcnic_fw_cmd_destroy_tx_ctx(adapter);
 
                /* Allow dma queues to drain after context reset */
-               msleep(20);
+               mdelay(20);
        }
 }
 
index bb8c8222122b920511f729463a04b97395724c7d..4d15bf413bdc89f060964c8114d4486be337ce46 100644 (file)
@@ -751,6 +751,7 @@ static int __devinit sgiseeq_probe(struct platform_device *pdev)
        sp->srings = sr;
        sp->rx_desc = sp->srings->rxvector;
        sp->tx_desc = sp->srings->txvector;
+       spin_lock_init(&sp->tx_lock);
 
        /* A couple calculations now, saves many cycles later. */
        setup_rx_ring(dev, sp->rx_desc, SEEQ_RX_BUFFERS);
index 8cba2df82b18b9f2dfa1ff82eee3b22ef9eeb0c9..5faedd855b779272342b37c6d992a1a93562a70b 100644 (file)
@@ -863,8 +863,8 @@ static int efx_ethtool_get_class_rule(struct efx_nic *efx,
                                       &ip_entry->ip4dst, &ip_entry->pdst);
        if (rc != 0) {
                rc = efx_filter_get_ipv4_full(
-                       &spec, &proto, &ip_entry->ip4src, &ip_entry->psrc,
-                       &ip_entry->ip4dst, &ip_entry->pdst);
+                       &spec, &proto, &ip_entry->ip4dst, &ip_entry->pdst,
+                       &ip_entry->ip4src, &ip_entry->psrc);
                EFX_WARN_ON_PARANOID(rc);
                ip_mask->ip4src = ~0;
                ip_mask->psrc = ~0;
index e2d083228f3a6b6b6039ab3276182d3adbc72869..719be3912aa9ca5cb7b0a527811df460c257561b 100644 (file)
@@ -22,6 +22,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __COMMON_H__
+#define __COMMON_H__
+
 #include <linux/etherdevice.h>
 #include <linux/netdevice.h>
 #include <linux/phy.h>
@@ -366,3 +369,5 @@ extern void stmmac_set_mac(void __iomem *ioaddr, bool enable);
 
 extern void dwmac_dma_flush_tx_fifo(void __iomem *ioaddr);
 extern const struct stmmac_ring_mode_ops ring_mode_ops;
+
+#endif /* __COMMON_H__ */
index 9820ec842cc01f8a7fb0897d993d0b873902dee8..223adf95fd0374e465447adc52d854491721fe4f 100644 (file)
 
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
+
+#ifndef __DESCS_H__
+#define __DESCS_H__
+
 struct dma_desc {
        /* Receive descriptor */
        union {
@@ -166,3 +170,5 @@ enum tdes_csum_insertion {
                                         * is not calculated */
        cic_full = 3,           /* IP header and pseudoheader */
 };
+
+#endif /* __DESCS_H__ */
index dd8d6e19dff6b2c1182dfb0f31ca8c4696c84931..7ee9499a6e385a77b9b2110b9578750e767745ab 100644 (file)
@@ -27,6 +27,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __DESC_COM_H__
+#define __DESC_COM_H__
+
 #if defined(CONFIG_STMMAC_RING)
 static inline void ehn_desc_rx_set_on_ring_chain(struct dma_desc *p, int end)
 {
@@ -124,3 +127,5 @@ static inline void norm_set_tx_desc_len(struct dma_desc *p, int len)
        p->des01.tx.buffer1_size = len;
 }
 #endif
+
+#endif /* __DESC_COM_H__ */
index 7c6d857a9cc7f0c357bb7b1d0cb9d417ecbc25a5..2ec6aeae349e5f7dd3b4e873d1366037a943cb27 100644 (file)
@@ -22,6 +22,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __DWMAC100_H__
+#define __DWMAC100_H__
+
 #include <linux/phy.h>
 #include "common.h"
 
@@ -119,3 +122,5 @@ enum ttc_control {
 #define DMA_MISSED_FRAME_M_CNTR        0x0000ffff      /* Missed Frame Couinter */
 
 extern const struct stmmac_dma_ops dwmac100_dma_ops;
+
+#endif /* __DWMAC100_H__ */
index f90fcb5f957351b742df584104eade1df609bb8b..0e4cacedc1f0e0cf44fad3bb84c5bac000f8e6ee 100644 (file)
@@ -19,6 +19,8 @@
 
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
+#ifndef __DWMAC1000_H__
+#define __DWMAC1000_H__
 
 #include <linux/phy.h>
 #include "common.h"
@@ -229,6 +231,7 @@ enum rtc_control {
 #define GMAC_MMC_RX_CSUM_OFFLOAD   0x208
 
 /* Synopsys Core versions */
-#define        DWMAC_CORE_3_40 34
+#define        DWMAC_CORE_3_40 0x34
 
 extern const struct stmmac_dma_ops dwmac1000_dma_ops;
+#endif /* __DWMAC1000_H__ */
index e678ce39d0146b707c012bb7bbd40a58361855c2..e49c9a0fd6ffe9a8ad52f19134e2e8c1aa7dcd2e 100644 (file)
@@ -22,6 +22,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __DWMAC_DMA_H__
+#define __DWMAC_DMA_H__
+
 /* DMA CRS Control and Status Register Mapping */
 #define DMA_BUS_MODE           0x00001000      /* Bus Mode */
 #define DMA_XMT_POLL_DEMAND    0x00001004      /* Transmit Poll Demand */
@@ -109,3 +112,5 @@ extern void dwmac_dma_start_rx(void __iomem *ioaddr);
 extern void dwmac_dma_stop_rx(void __iomem *ioaddr);
 extern int dwmac_dma_interrupt(void __iomem *ioaddr,
                                struct stmmac_extra_stats *x);
+
+#endif /* __DWMAC_DMA_H__ */
index a38352024cb8fec7897fc4a990972658efb35dfb..67995ef252515f53c6796ecf77bbe66460223944 100644 (file)
@@ -22,6 +22,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __MMC_H__
+#define __MMC_H__
+
 /* MMC control register */
 /* When set, all counter are reset */
 #define MMC_CNTRL_COUNTER_RESET                0x1
@@ -129,3 +132,5 @@ struct stmmac_counters {
 extern void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode);
 extern void dwmac_mmc_intr_all_mask(void __iomem *ioaddr);
 extern void dwmac_mmc_read(void __iomem *ioaddr, struct stmmac_counters *mmc);
+
+#endif /* __MMC_H__ */
index c07cfe989f6ef35716c59d3b5e29cdeefa4f1f2a..0c74a702d4610597da59200be253306c7b4db534 100644 (file)
@@ -33,7 +33,7 @@
 #define MMC_TX_INTR            0x00000108      /* MMC TX Interrupt */
 #define MMC_RX_INTR_MASK       0x0000010c      /* MMC Interrupt Mask */
 #define MMC_TX_INTR_MASK       0x00000110      /* MMC Interrupt Mask */
-#define MMC_DEFAUL_MASK                0xffffffff
+#define MMC_DEFAULT_MASK               0xffffffff
 
 /* MMC TX counter registers */
 
@@ -147,8 +147,8 @@ void dwmac_mmc_ctrl(void __iomem *ioaddr, unsigned int mode)
 /* To mask all all interrupts.*/
 void dwmac_mmc_intr_all_mask(void __iomem *ioaddr)
 {
-       writel(MMC_DEFAUL_MASK, ioaddr + MMC_RX_INTR_MASK);
-       writel(MMC_DEFAUL_MASK, ioaddr + MMC_TX_INTR_MASK);
+       writel(MMC_DEFAULT_MASK, ioaddr + MMC_RX_INTR_MASK);
+       writel(MMC_DEFAULT_MASK, ioaddr + MMC_TX_INTR_MASK);
 }
 
 /* This reads the MAC core counters (if actaully supported).
index f2d3665430ad455b82552d975d9f91066a5fc913..e872e1da3137cef68265e845188bb8544acb988e 100644 (file)
@@ -20,6 +20,9 @@
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
 
+#ifndef __STMMAC_H__
+#define __STMMAC_H__
+
 #define STMMAC_RESOURCE_NAME   "stmmaceth"
 #define DRV_MODULE_VERSION     "March_2012"
 
@@ -166,3 +169,5 @@ static inline void stmmac_unregister_pci(void)
 {
 }
 #endif /* CONFIG_STMMAC_PCI */
+
+#endif /* __STMMAC_H__ */
index c136162e6473e1746b48f50a0c7cc0adc57986d6..3be88331d17ab0e690b71f06b2ac30f50d7a7f77 100644 (file)
@@ -1066,7 +1066,7 @@ static int stmmac_open(struct net_device *dev)
        } else
                priv->tm->enable = 1;
 #endif
-       clk_enable(priv->stmmac_clk);
+       clk_prepare_enable(priv->stmmac_clk);
 
        stmmac_check_ether_addr(priv);
 
@@ -1188,7 +1188,7 @@ open_error:
        if (priv->phydev)
                phy_disconnect(priv->phydev);
 
-       clk_disable(priv->stmmac_clk);
+       clk_disable_unprepare(priv->stmmac_clk);
 
        return ret;
 }
@@ -1246,7 +1246,7 @@ static int stmmac_release(struct net_device *dev)
 #ifdef CONFIG_STMMAC_DEBUG_FS
        stmmac_exit_fs();
 #endif
-       clk_disable(priv->stmmac_clk);
+       clk_disable_unprepare(priv->stmmac_clk);
 
        return 0;
 }
@@ -2178,7 +2178,7 @@ int stmmac_suspend(struct net_device *ndev)
        else {
                stmmac_set_mac(priv->ioaddr, false);
                /* Disable clock in case of PWM is off */
-               clk_disable(priv->stmmac_clk);
+               clk_disable_unprepare(priv->stmmac_clk);
        }
        spin_unlock_irqrestore(&priv->lock, flags);
        return 0;
@@ -2203,7 +2203,7 @@ int stmmac_resume(struct net_device *ndev)
                priv->hw->mac->pmt(priv->ioaddr, 0);
        else
                /* enable the clk prevously disabled */
-               clk_enable(priv->stmmac_clk);
+               clk_prepare_enable(priv->stmmac_clk);
 
        netif_device_attach(ndev);
 
index 2a0e1abde7e73eeea25c9c457999765b5315a01f..4ccd4e2977b73a0d441f6f0dbb99ea0636c8dae0 100644 (file)
@@ -97,19 +97,19 @@ static struct clk *timer_clock;
 static void stmmac_tmu_start(unsigned int new_freq)
 {
        clk_set_rate(timer_clock, new_freq);
-       clk_enable(timer_clock);
+       clk_prepare_enable(timer_clock);
 }
 
 static void stmmac_tmu_stop(void)
 {
-       clk_disable(timer_clock);
+       clk_disable_unprepare(timer_clock);
 }
 
 int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 {
        timer_clock = clk_get(NULL, TMU_CHANNEL);
 
-       if (timer_clock == NULL)
+       if (IS_ERR(timer_clock))
                return -1;
 
        if (tmu2_register_user(stmmac_timer_handler, (void *)dev) < 0) {
@@ -126,7 +126,7 @@ int stmmac_open_ext_timer(struct net_device *dev, struct stmmac_timer *tm)
 
 int stmmac_close_ext_timer(void)
 {
-       clk_disable(timer_clock);
+       clk_disable_unprepare(timer_clock);
        tmu2_unregister_user();
        clk_put(timer_clock);
        return 0;
index 6863590d184bcc9c335da8bfb51562eafafc7557..aea9b14cdfbeff126a962e766ca97894284e51b6 100644 (file)
@@ -21,6 +21,8 @@
 
   Author: Giuseppe Cavallaro <peppe.cavallaro@st.com>
 *******************************************************************************/
+#ifndef __STMMAC_TIMER_H__
+#define __STMMAC_TIMER_H__
 
 struct stmmac_timer {
        void (*timer_start) (unsigned int new_freq);
@@ -40,3 +42,5 @@ void stmmac_schedule(struct net_device *dev);
 extern int tmu2_register_user(void *fnt, void *data);
 extern void tmu2_unregister_user(void);
 #endif
+
+#endif /* __STMMAC_TIMER_H__ */
index cd7ee204e94a10abaa88b3288dcd2cace5ceca3e..a9ca4a03d31b2fe2adc68818da636edb8d5aeb2b 100644 (file)
@@ -394,8 +394,10 @@ static int __devexit davinci_mdio_remove(struct platform_device *pdev)
        struct device *dev = &pdev->dev;
        struct davinci_mdio_data *data = dev_get_drvdata(dev);
 
-       if (data->bus)
+       if (data->bus) {
+               mdiobus_unregister(data->bus);
                mdiobus_free(data->bus);
+       }
 
        if (data->clk)
                clk_put(data->clk);
index 24d8566cfd8b98cdd50540b09b19c9287757e914..441b4dc79450c1009151692565586c53060e5c83 100644 (file)
@@ -673,7 +673,7 @@ void smt_add_para(struct s_smc *smc, struct s_pcon *pcon, u_short para,
                        sm_pm_get_ls(smc,port_to_mib(smc,port))) ;
                break ;
        case SMT_P_REASON :
-               * (u_long *) to = 0 ;
+               *(u32 *)to = 0 ;
                sp_len = 4 ;
                goto sp_done ;
        case SMT_P1033 :                        /* time stamp */
index 256eddf1f75a1913576067742f8fc1cb3dce3e7a..795109425568623977428b1a62bffc7d11c6fa14 100644 (file)
@@ -280,7 +280,7 @@ static int sh_sir_set_baudrate(struct sh_sir_self *self, u32 baudrate)
        }
 
        clk = clk_get(NULL, "irda_clk");
-       if (!clk) {
+       if (IS_ERR(clk)) {
                dev_err(dev, "can not get irda_clk\n");
                return -EIO;
        }
index 2346b38b9837101deae4848443da3d5b6be7cdeb..799789518e873edf273c95be6ec1c3b59ff4aa80 100644 (file)
@@ -229,3 +229,5 @@ static void __exit bcm87xx_exit(void)
                ARRAY_SIZE(bcm87xx_driver));
 }
 module_exit(bcm87xx_exit);
+
+MODULE_LICENSE("GPL");
index cf287e0eb4088574530bdb65b86d0276b589b744..2165d5fdb8c0f08675772f8dded60f3a15ac34ba 100644 (file)
 #include <linux/phy.h>
 #include <linux/micrel_phy.h>
 
+/* Operation Mode Strap Override */
+#define MII_KSZPHY_OMSO                                0x16
+#define KSZPHY_OMSO_B_CAST_OFF                 (1 << 9)
+#define KSZPHY_OMSO_RMII_OVERRIDE              (1 << 1)
+#define KSZPHY_OMSO_MII_OVERRIDE               (1 << 0)
+
 /* general Interrupt control/status reg in vendor specific block. */
 #define MII_KSZPHY_INTCS                       0x1B
 #define        KSZPHY_INTCS_JABBER                     (1 << 15)
@@ -101,6 +107,13 @@ static int kszphy_config_init(struct phy_device *phydev)
        return 0;
 }
 
+static int ksz8021_config_init(struct phy_device *phydev)
+{
+       const u16 val = KSZPHY_OMSO_B_CAST_OFF | KSZPHY_OMSO_RMII_OVERRIDE;
+       phy_write(phydev, MII_KSZPHY_OMSO, val);
+       return 0;
+}
+
 static int ks8051_config_init(struct phy_device *phydev)
 {
        int regval;
@@ -128,9 +141,22 @@ static struct phy_driver ksphy_driver[] = {
        .config_intr    = ks8737_config_intr,
        .driver         = { .owner = THIS_MODULE,},
 }, {
-       .phy_id         = PHY_ID_KS8041,
+       .phy_id         = PHY_ID_KSZ8021,
+       .phy_id_mask    = 0x00ffffff,
+       .name           = "Micrel KSZ8021",
+       .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause |
+                          SUPPORTED_Asym_Pause),
+       .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
+       .config_init    = ksz8021_config_init,
+       .config_aneg    = genphy_config_aneg,
+       .read_status    = genphy_read_status,
+       .ack_interrupt  = kszphy_ack_interrupt,
+       .config_intr    = kszphy_config_intr,
+       .driver         = { .owner = THIS_MODULE,},
+}, {
+       .phy_id         = PHY_ID_KSZ8041,
        .phy_id_mask    = 0x00fffff0,
-       .name           = "Micrel KS8041",
+       .name           = "Micrel KSZ8041",
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
                                | SUPPORTED_Asym_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -141,9 +167,9 @@ static struct phy_driver ksphy_driver[] = {
        .config_intr    = kszphy_config_intr,
        .driver         = { .owner = THIS_MODULE,},
 }, {
-       .phy_id         = PHY_ID_KS8051,
+       .phy_id         = PHY_ID_KSZ8051,
        .phy_id_mask    = 0x00fffff0,
-       .name           = "Micrel KS8051",
+       .name           = "Micrel KSZ8051",
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause
                                | SUPPORTED_Asym_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -154,8 +180,8 @@ static struct phy_driver ksphy_driver[] = {
        .config_intr    = kszphy_config_intr,
        .driver         = { .owner = THIS_MODULE,},
 }, {
-       .phy_id         = PHY_ID_KS8001,
-       .name           = "Micrel KS8001 or KS8721",
+       .phy_id         = PHY_ID_KSZ8001,
+       .name           = "Micrel KSZ8001 or KS8721",
        .phy_id_mask    = 0x00ffffff,
        .features       = (PHY_BASIC_FEATURES | SUPPORTED_Pause),
        .flags          = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT,
@@ -201,10 +227,11 @@ MODULE_LICENSE("GPL");
 
 static struct mdio_device_id __maybe_unused micrel_tbl[] = {
        { PHY_ID_KSZ9021, 0x000ffffe },
-       { PHY_ID_KS8001, 0x00ffffff },
+       { PHY_ID_KSZ8001, 0x00ffffff },
        { PHY_ID_KS8737, 0x00fffff0 },
-       { PHY_ID_KS8041, 0x00fffff0 },
-       { PHY_ID_KS8051, 0x00fffff0 },
+       { PHY_ID_KSZ8021, 0x00ffffff },
+       { PHY_ID_KSZ8041, 0x00fffff0 },
+       { PHY_ID_KSZ8051, 0x00fffff0 },
        { }
 };
 
index 6d6192316b30988ed742cf7261de5c5daaa310f2..88e3991464e7e1531934bcb562718e97abcbfb9b 100644 (file)
@@ -56,6 +56,32 @@ static int smsc_phy_config_init(struct phy_device *phydev)
        return smsc_phy_ack_interrupt (phydev);
 }
 
+static int lan87xx_config_init(struct phy_device *phydev)
+{
+       /*
+        * Make sure the EDPWRDOWN bit is NOT set. Setting this bit on
+        * LAN8710/LAN8720 PHY causes the PHY to misbehave, likely due
+        * to a bug on the chip.
+        *
+        * When the system is powered on with the network cable being
+        * disconnected all the way until after ifconfig ethX up is
+        * issued for the LAN port with this PHY, connecting the cable
+        * afterwards does not cause LINK change detection, while the
+        * expected behavior is the Link UP being detected.
+        */
+       int rc = phy_read(phydev, MII_LAN83C185_CTRL_STATUS);
+       if (rc < 0)
+               return rc;
+
+       rc &= ~MII_LAN83C185_EDPWRDOWN;
+
+       rc = phy_write(phydev, MII_LAN83C185_CTRL_STATUS, rc);
+       if (rc < 0)
+               return rc;
+
+       return smsc_phy_ack_interrupt(phydev);
+}
+
 static int lan911x_config_init(struct phy_device *phydev)
 {
        return smsc_phy_ack_interrupt(phydev);
@@ -162,7 +188,7 @@ static struct phy_driver smsc_phy_driver[] = {
        /* basic functions */
        .config_aneg    = genphy_config_aneg,
        .read_status    = genphy_read_status,
-       .config_init    = smsc_phy_config_init,
+       .config_init    = lan87xx_config_init,
 
        /* IRQ related */
        .ack_interrupt  = smsc_phy_ack_interrupt,
index cbf7047decc04340d39be3daa95359469b9e73ec..20f31d0d1536c36658b481fa083eb6b445637ef7 100644 (file)
@@ -570,7 +570,7 @@ static int pppoe_release(struct socket *sock)
 
        po = pppox_sk(sk);
 
-       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND)) {
+       if (sk->sk_state & (PPPOX_CONNECTED | PPPOX_BOUND | PPPOX_ZOMBIE)) {
                dev_put(po->pppoe_dev);
                po->pppoe_dev = NULL;
        }
index 341b65dbbcd324d9512f957fc7b663481a073aea..f8cd61f449a4772da5a50a446cd07fc80d5928c8 100644 (file)
@@ -848,7 +848,7 @@ static struct netpoll_info *team_netpoll_info(struct team *team)
 }
 #endif
 
-static void __team_port_change_check(struct team_port *port, bool linkup);
+static void __team_port_change_port_added(struct team_port *port, bool linkup);
 
 static int team_port_add(struct team *team, struct net_device *port_dev)
 {
@@ -948,7 +948,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev)
        team_port_enable(team, port);
        list_add_tail_rcu(&port->list, &team->port_list);
        __team_compute_features(team);
-       __team_port_change_check(port, !!netif_carrier_ok(port_dev));
+       __team_port_change_port_added(port, !!netif_carrier_ok(port_dev));
        __team_options_change_check(team);
 
        netdev_info(dev, "Port device %s added\n", portname);
@@ -983,6 +983,8 @@ err_set_mtu:
        return err;
 }
 
+static void __team_port_change_port_removed(struct team_port *port);
+
 static int team_port_del(struct team *team, struct net_device *port_dev)
 {
        struct net_device *dev = team->dev;
@@ -999,8 +1001,7 @@ static int team_port_del(struct team *team, struct net_device *port_dev)
        __team_option_inst_mark_removed_port(team, port);
        __team_options_change_check(team);
        __team_option_inst_del_port(team, port);
-       port->removed = true;
-       __team_port_change_check(port, false);
+       __team_port_change_port_removed(port);
        team_port_disable(team, port);
        list_del_rcu(&port->list);
        netdev_rx_handler_unregister(port_dev);
@@ -1652,8 +1653,8 @@ static int team_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
 
        hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
                          &team_nl_family, 0, TEAM_CMD_NOOP);
-       if (IS_ERR(hdr)) {
-               err = PTR_ERR(hdr);
+       if (!hdr) {
+               err = -EMSGSIZE;
                goto err_msg_put;
        }
 
@@ -1847,8 +1848,8 @@ start_again:
 
        hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags | NLM_F_MULTI,
                          TEAM_CMD_OPTIONS_GET);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -EMSGSIZE;
 
        if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
                goto nla_put_failure;
@@ -2067,8 +2068,8 @@ static int team_nl_fill_port_list_get(struct sk_buff *skb,
 
        hdr = genlmsg_put(skb, pid, seq, &team_nl_family, flags,
                          TEAM_CMD_PORT_LIST_GET);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -EMSGSIZE;
 
        if (nla_put_u32(skb, TEAM_ATTR_TEAM_IFINDEX, team->dev->ifindex))
                goto nla_put_failure;
@@ -2251,13 +2252,11 @@ static void __team_options_change_check(struct team *team)
 }
 
 /* rtnl lock is held */
-static void __team_port_change_check(struct team_port *port, bool linkup)
+
+static void __team_port_change_send(struct team_port *port, bool linkup)
 {
        int err;
 
-       if (!port->removed && port->state.linkup == linkup)
-               return;
-
        port->changed = true;
        port->state.linkup = linkup;
        team_refresh_port_linkup(port);
@@ -2282,6 +2281,23 @@ send_event:
 
 }
 
+static void __team_port_change_check(struct team_port *port, bool linkup)
+{
+       if (port->state.linkup != linkup)
+               __team_port_change_send(port, linkup);
+}
+
+static void __team_port_change_port_added(struct team_port *port, bool linkup)
+{
+       __team_port_change_send(port, linkup);
+}
+
+static void __team_port_change_port_removed(struct team_port *port)
+{
+       port->removed = true;
+       __team_port_change_send(port, false);
+}
+
 static void team_port_change_check(struct team_port *port, bool linkup)
 {
        struct team *team = port->team;
index 4fd48df6b989eee8aff62ee1d5edb5014bae5e1d..32e31c5c5dc6bfe95b4d38e377a508448d85c890 100644 (file)
@@ -961,6 +961,10 @@ static const struct usb_device_id  products [] = {
        // DLink DUB-E100 H/W Ver B1 Alternate
        USB_DEVICE (0x2001, 0x3c05),
        .driver_info = (unsigned long) &ax88772_info,
+}, {
+       // DLink DUB-E100 H/W Ver C1
+       USB_DEVICE (0x2001, 0x1a02),
+       .driver_info = (unsigned long) &ax88772_info,
 }, {
        // Linksys USB1000
        USB_DEVICE (0x1737, 0x0039),
index 328397c66730cae37a9c1cdc02cdb7dde523e2b3..3543c9e578247e6ee550ef7f18f680b680be3587 100644 (file)
@@ -297,7 +297,7 @@ static int qmi_wwan_suspend(struct usb_interface *intf, pm_message_t message)
        if (ret < 0)
                goto err;
 
-       if (info->subdriver && info->subdriver->suspend)
+       if (intf == info->control && info->subdriver && info->subdriver->suspend)
                ret = info->subdriver->suspend(intf, message);
        if (ret < 0)
                usbnet_resume(intf);
@@ -310,13 +310,14 @@ static int qmi_wwan_resume(struct usb_interface *intf)
        struct usbnet *dev = usb_get_intfdata(intf);
        struct qmi_wwan_state *info = (void *)&dev->data;
        int ret = 0;
+       bool callsub = (intf == info->control && info->subdriver && info->subdriver->resume);
 
-       if (info->subdriver && info->subdriver->resume)
+       if (callsub)
                ret = info->subdriver->resume(intf);
        if (ret < 0)
                goto err;
        ret = usbnet_resume(intf);
-       if (ret < 0 && info->subdriver && info->subdriver->resume && info->subdriver->suspend)
+       if (ret < 0 && callsub && info->subdriver->suspend)
                info->subdriver->suspend(intf, PMSG_SUSPEND);
 err:
        return ret;
@@ -365,16 +366,20 @@ static const struct usb_device_id products[] = {
        },
 
        /* 2. Combined interface devices matching on class+protocol */
+       {       /* Huawei E367 and possibly others in "Windows mode" */
+               USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 7),
+               .driver_info        = (unsigned long)&qmi_wwan_info,
+       },
        {       /* Huawei E392, E398 and possibly others in "Windows mode" */
                USB_VENDOR_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, USB_CLASS_VENDOR_SPEC, 1, 17),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
-       {       /* Pantech UML290 */
-               USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
+       {       /* Pantech UML290, P4200 and more */
+               USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf0, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
        {       /* Pantech UML290 - newer firmware */
-               USB_DEVICE_AND_INTERFACE_INFO(0x106c, 0x3718, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
+               USB_VENDOR_AND_INTERFACE_INFO(0x106c, USB_CLASS_VENDOR_SPEC, 0xf1, 0xff),
                .driver_info        = (unsigned long)&qmi_wwan_shared,
        },
 
@@ -382,6 +387,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x19d2, 0x0055, 1)},    /* ZTE (Vodafone) K3520-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0063, 4)},    /* ZTE (Vodafone) K3565-Z */
        {QMI_FIXED_INTF(0x19d2, 0x0104, 4)},    /* ZTE (Vodafone) K4505-Z */
+       {QMI_FIXED_INTF(0x19d2, 0x0157, 5)},    /* ZTE MF683 */
        {QMI_FIXED_INTF(0x19d2, 0x0167, 4)},    /* ZTE MF820D */
        {QMI_FIXED_INTF(0x19d2, 0x0326, 4)},    /* ZTE MF821D */
        {QMI_FIXED_INTF(0x19d2, 0x1008, 4)},    /* ZTE (Vodafone) K3570-Z */
@@ -398,7 +404,6 @@ static const struct usb_device_id products[] = {
        /* 4. Gobi 1000 devices */
        {QMI_GOBI1K_DEVICE(0x05c6, 0x9212)},    /* Acer Gobi Modem Device */
        {QMI_GOBI1K_DEVICE(0x03f0, 0x1f1d)},    /* HP un2400 Gobi Modem Device */
-       {QMI_GOBI1K_DEVICE(0x03f0, 0x371d)},    /* HP un2430 Mobile Broadband Module */
        {QMI_GOBI1K_DEVICE(0x04da, 0x250d)},    /* Panasonic Gobi Modem device */
        {QMI_GOBI1K_DEVICE(0x413c, 0x8172)},    /* Dell Gobi Modem device */
        {QMI_GOBI1K_DEVICE(0x1410, 0xa001)},    /* Novatel Gobi Modem device */
@@ -413,7 +418,9 @@ static const struct usb_device_id products[] = {
 
        /* 5. Gobi 2000 and 3000 devices */
        {QMI_GOBI_DEVICE(0x413c, 0x8186)},      /* Dell Gobi 2000 Modem device (N0218, VU936) */
+       {QMI_GOBI_DEVICE(0x413c, 0x8194)},      /* Dell Gobi 3000 Composite */
        {QMI_GOBI_DEVICE(0x05c6, 0x920b)},      /* Generic Gobi 2000 Modem device */
+       {QMI_GOBI_DEVICE(0x05c6, 0x920d)},      /* Gobi 3000 Composite */
        {QMI_GOBI_DEVICE(0x05c6, 0x9225)},      /* Sony Gobi 2000 Modem device (N0279, VU730) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9245)},      /* Samsung Gobi 2000 Modem device (VL176) */
        {QMI_GOBI_DEVICE(0x03f0, 0x251d)},      /* HP Gobi 2000 Modem device (VP412) */
@@ -438,9 +445,12 @@ static const struct usb_device_id products[] = {
        {QMI_GOBI_DEVICE(0x16d8, 0x8002)},      /* CMDTech Gobi 2000 Modem device (VU922) */
        {QMI_GOBI_DEVICE(0x05c6, 0x9205)},      /* Gobi 2000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x9013)},      /* Sierra Wireless Gobi 3000 Modem device (MC8355) */
+       {QMI_GOBI_DEVICE(0x03f0, 0x371d)},      /* HP un2430 Mobile Broadband Module */
        {QMI_GOBI_DEVICE(0x1199, 0x9015)},      /* Sierra Wireless Gobi 3000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x9019)},      /* Sierra Wireless Gobi 3000 Modem device */
        {QMI_GOBI_DEVICE(0x1199, 0x901b)},      /* Sierra Wireless MC7770 */
+       {QMI_GOBI_DEVICE(0x12d1, 0x14f1)},      /* Sony Gobi 3000 Composite */
+       {QMI_GOBI_DEVICE(0x1410, 0xa021)},      /* Foxconn Gobi 3000 Modem device (Novatel E396) */
 
        { }                                     /* END */
 };
index 7be49ea60b6d8f9353720d757f47c2c61b16fc60..8e22417fa6c11b5d41845bda1ff4c84e9d369cda 100644 (file)
@@ -656,7 +656,7 @@ static int sierra_net_get_fw_attr(struct usbnet *dev, u16 *datap)
                return -EIO;
        }
 
-       *datap = *attrdata;
+       *datap = le16_to_cpu(*attrdata);
 
        kfree(attrdata);
        return result;
index f5ab6e613ec8dcddf6b36e25a1dd0f79c50849db..376143e8a1aaf6f78ee44fb76888922064c46dd1 100644 (file)
@@ -1253,6 +1253,7 @@ static struct usb_driver smsc75xx_driver = {
        .probe          = usbnet_probe,
        .suspend        = usbnet_suspend,
        .resume         = usbnet_resume,
+       .reset_resume   = usbnet_resume,
        .disconnect     = usbnet_disconnect,
        .disable_hub_initiated_lpm = 1,
 };
index 8531c1caac283263febc4f674daedef5b7844ff1..fc9f578a1e253a781b9406b1e4a43ed2de2688d1 100644 (file)
@@ -1201,19 +1201,26 @@ deferred:
 }
 EXPORT_SYMBOL_GPL(usbnet_start_xmit);
 
-static void rx_alloc_submit(struct usbnet *dev, gfp_t flags)
+static int rx_alloc_submit(struct usbnet *dev, gfp_t flags)
 {
        struct urb      *urb;
        int             i;
+       int             ret = 0;
 
        /* don't refill the queue all at once */
        for (i = 0; i < 10 && dev->rxq.qlen < RX_QLEN(dev); i++) {
                urb = usb_alloc_urb(0, flags);
                if (urb != NULL) {
-                       if (rx_submit(dev, urb, flags) == -ENOLINK)
-                               return;
+                       ret = rx_submit(dev, urb, flags);
+                       if (ret)
+                               goto err;
+               } else {
+                       ret = -ENOMEM;
+                       goto err;
                }
        }
+err:
+       return ret;
 }
 
 /*-------------------------------------------------------------------------*/
@@ -1257,7 +1264,8 @@ static void usbnet_bh (unsigned long param)
                int     temp = dev->rxq.qlen;
 
                if (temp < RX_QLEN(dev)) {
-                       rx_alloc_submit(dev, GFP_ATOMIC);
+                       if (rx_alloc_submit(dev, GFP_ATOMIC) == -ENOLINK)
+                               return;
                        if (temp != dev->rxq.qlen)
                                netif_dbg(dev, link, dev->net,
                                          "rxqlen %d --> %d\n",
@@ -1573,7 +1581,7 @@ int usbnet_resume (struct usb_interface *intf)
                                netif_device_present(dev->net) &&
                                !timer_pending(&dev->delay) &&
                                !test_bit(EVENT_RX_HALT, &dev->flags))
-                                       rx_alloc_submit(dev, GFP_KERNEL);
+                                       rx_alloc_submit(dev, GFP_NOIO);
 
                        if (!(dev->txq.qlen >= TX_QLEN(dev)))
                                netif_tx_wake_all_queues(dev->net);
index aaaca9aa2293dcf4fc991cb1645056ebfa3d0da1..3f575afd8cfcb03f283df0932f6fb33bb1495cca 100644 (file)
@@ -10,6 +10,7 @@
 
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
+#include <linux/module.h>
 #include <linux/bitops.h>
 #include <linux/cdev.h>
 #include <linux/dma-mapping.h>
index 4026c906cc7b45745e3a80dbc5edc9360413f78f..b7e0258887e70cf9be193c70e73334e9e8fe0473 100644 (file)
@@ -1482,7 +1482,7 @@ ath5k_eeprom_read_target_rate_pwr_info(struct ath5k_hw *ah, unsigned int mode)
        case AR5K_EEPROM_MODE_11A:
                offset += AR5K_EEPROM_TARGET_PWR_OFF_11A(ee->ee_version);
                rate_pcal_info = ee->ee_rate_tpwr_a;
-               ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_CHAN;
+               ee->ee_rate_target_pwr_num[mode] = AR5K_EEPROM_N_5GHZ_RATE_CHAN;
                break;
        case AR5K_EEPROM_MODE_11B:
                offset += AR5K_EEPROM_TARGET_PWR_OFF_11B(ee->ee_version);
index dc2bcfeadeb45b121de183bd558045a69dda47ba..94a9bbea6874c0daf10510e26fa2862f8ebbfa81 100644 (file)
 #define AR5K_EEPROM_EEP_DELTA          10
 #define AR5K_EEPROM_N_MODES            3
 #define AR5K_EEPROM_N_5GHZ_CHAN                10
+#define AR5K_EEPROM_N_5GHZ_RATE_CHAN   8
 #define AR5K_EEPROM_N_2GHZ_CHAN                3
 #define AR5K_EEPROM_N_2GHZ_CHAN_2413   4
 #define        AR5K_EEPROM_N_2GHZ_CHAN_MAX     4
index 2588848f4a822a1bf879ce447f9f146c5e186873..d066f2516e4753617aa55f1522427eb96f4a1115 100644 (file)
@@ -2982,6 +2982,10 @@ static u32 ath9k_hw_ar9300_get_eeprom(struct ath_hw *ah,
        case EEP_RX_MASK:
                return pBase->txrxMask & 0xf;
        case EEP_PAPRD:
+               if (AR_SREV_9462(ah))
+                       return false;
+               if (!ah->config.enable_paprd);
+                       return false;
                return !!(pBase->featureEnable & BIT(5));
        case EEP_CHAIN_MASK_REDUCE:
                return (pBase->miscConfiguration >> 0x3) & 0x1;
index 2c9f7d7ed4cc2557a86cb5256afc213a4c16f5c5..0ed3846f9cbb36e8aa1f67eab09dc9e5f219b0c8 100644 (file)
@@ -142,6 +142,7 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
        };
        int training_power;
        int i, val;
+       u32 am2pm_mask = ah->paprd_ratemask;
 
        if (IS_CHAN_2GHZ(ah->curchan))
                training_power = ar9003_get_training_power_2g(ah);
@@ -158,10 +159,13 @@ static int ar9003_paprd_setup_single_table(struct ath_hw *ah)
        }
        ah->paprd_training_power = training_power;
 
+       if (AR_SREV_9330(ah))
+               am2pm_mask = 0;
+
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2AM, AR_PHY_PAPRD_AM2AM_MASK,
                      ah->paprd_ratemask);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_AM2PM, AR_PHY_PAPRD_AM2PM_MASK,
-                     ah->paprd_ratemask);
+                     am2pm_mask);
        REG_RMW_FIELD(ah, AR_PHY_PAPRD_HT40, AR_PHY_PAPRD_HT40_MASK,
                      ah->paprd_ratemask_ht40);
 
@@ -782,6 +786,102 @@ int ar9003_paprd_setup_gain_table(struct ath_hw *ah, int chain)
 }
 EXPORT_SYMBOL(ar9003_paprd_setup_gain_table);
 
+static bool ar9003_paprd_retrain_pa_in(struct ath_hw *ah,
+                                      struct ath9k_hw_cal_data *caldata,
+                                      int chain)
+{
+       u32 *pa_in = caldata->pa_table[chain];
+       int capdiv_offset, quick_drop_offset;
+       int capdiv2g, quick_drop;
+       int count = 0;
+       int i;
+
+       if (!AR_SREV_9485(ah) && !AR_SREV_9330(ah))
+               return false;
+
+       capdiv2g = REG_READ_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
+                                 AR_PHY_65NM_CH0_TXRF3_CAPDIV2G);
+
+       quick_drop = REG_READ_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                                   AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP);
+
+       if (quick_drop)
+               quick_drop -= 0x40;
+
+       for (i = 0; i < NUM_BIN + 1; i++) {
+               if (pa_in[i] == 1400)
+                       count++;
+       }
+
+       if (AR_SREV_9485(ah)) {
+               if (pa_in[23] < 800) {
+                       capdiv_offset = (int)((1000 - pa_in[23] + 75) / 150);
+                       capdiv2g += capdiv_offset;
+                       if (capdiv2g > 7) {
+                               capdiv2g = 7;
+                               if (pa_in[23] < 600) {
+                                       quick_drop++;
+                                       if (quick_drop > 0)
+                                               quick_drop = 0;
+                               }
+                       }
+               } else if (pa_in[23] == 1400) {
+                       quick_drop_offset = min_t(int, count / 3, 2);
+                       quick_drop += quick_drop_offset;
+                       capdiv2g += quick_drop_offset / 2;
+
+                       if (capdiv2g > 7)
+                               capdiv2g = 7;
+
+                       if (quick_drop > 0) {
+                               quick_drop = 0;
+                               capdiv2g -= quick_drop_offset;
+                               if (capdiv2g < 0)
+                                       capdiv2g = 0;
+                       }
+               } else {
+                       return false;
+               }
+       } else if (AR_SREV_9330(ah)) {
+               if (pa_in[23] < 1000) {
+                       capdiv_offset = (1000 - pa_in[23]) / 100;
+                       capdiv2g += capdiv_offset;
+                       if (capdiv_offset > 3) {
+                               capdiv_offset = 1;
+                               quick_drop--;
+                       }
+
+                       capdiv2g += capdiv_offset;
+                       if (capdiv2g > 6)
+                               capdiv2g = 6;
+                       if (quick_drop < -4)
+                               quick_drop = -4;
+               } else if (pa_in[23] == 1400) {
+                       if (count > 3) {
+                               quick_drop++;
+                               capdiv2g -= count / 4;
+                               if (quick_drop > -2)
+                                       quick_drop = -2;
+                       } else {
+                               capdiv2g--;
+                       }
+
+                       if (capdiv2g < 0)
+                               capdiv2g = 0;
+               } else {
+                       return false;
+               }
+       }
+
+       REG_RMW_FIELD(ah, AR_PHY_65NM_CH0_TXRF3,
+                     AR_PHY_65NM_CH0_TXRF3_CAPDIV2G, capdiv2g);
+       REG_RMW_FIELD(ah, AR_PHY_PAPRD_TRAINER_CNTL3,
+                     AR_PHY_PAPRD_TRAINER_CNTL3_CF_PAPRD_QUICK_DROP,
+                     quick_drop);
+
+       return true;
+}
+
 int ar9003_paprd_create_curve(struct ath_hw *ah,
                              struct ath9k_hw_cal_data *caldata, int chain)
 {
@@ -817,6 +917,9 @@ int ar9003_paprd_create_curve(struct ath_hw *ah,
        if (!create_pa_curve(data_L, data_U, pa_table, small_signal_gain))
                status = -2;
 
+       if (ar9003_paprd_retrain_pa_in(ah, caldata, chain))
+               status = -EINPROGRESS;
+
        REG_CLR_BIT(ah, AR_PHY_PAPRD_TRAINER_STAT1,
                    AR_PHY_PAPRD_TRAINER_STAT1_PAPRD_TRAIN_DONE);
 
index 7bfbaf065a4332c89ac5568c0cde81ed42d9313e..84d3d49568616c5452692b1660253f6ae70468cf 100644 (file)
 #define AR_PHY_AIC_CTRL_4_B0   (AR_SM_BASE + 0x4c0)
 #define AR_PHY_AIC_STAT_2_B0   (AR_SM_BASE + 0x4cc)
 
+#define AR_PHY_65NM_CH0_TXRF3       0x16048
+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G         0x0000001e
+#define AR_PHY_65NM_CH0_TXRF3_CAPDIV2G_S       1
+
 #define AR_PHY_65NM_CH0_SYNTH4      0x1608c
 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT   (AR_SREV_9462(ah) ? 0x00000001 : 0x00000002)
 #define AR_PHY_SYNTH4_LONG_SHIFT_SELECT_S (AR_SREV_9462(ah) ? 0 : 1)
index 68b643c8943c4c2db074e4ada4eeb2fda397eccc..c8ef30127adb53da590bf4d6350798fa261dffa6 100644 (file)
@@ -1577,6 +1577,8 @@ int ath9k_init_debug(struct ath_hw *ah)
                            sc->debug.debugfs_phy, sc, &fops_tx_chainmask);
        debugfs_create_file("disable_ani", S_IRUSR | S_IWUSR,
                            sc->debug.debugfs_phy, sc, &fops_disable_ani);
+       debugfs_create_bool("paprd", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
+                           &sc->sc_ah->config.enable_paprd);
        debugfs_create_file("regidx", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
                            sc, &fops_regidx);
        debugfs_create_file("regval", S_IRUSR | S_IWUSR, sc->debug.debugfs_phy,
index bacdb8fb4ef453dda48d5a9394c0030cb7866596..9f83f71742a5ecb774f95c3d563f2e0dc7d37ab7 100644 (file)
@@ -341,7 +341,8 @@ void ath9k_btcoex_stop_gen_timer(struct ath_softc *sc)
 {
        struct ath_btcoex *btcoex = &sc->btcoex;
 
-       ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
+       if (btcoex->hw_timer_enabled)
+               ath9k_gen_timer_stop(sc->sc_ah, btcoex->no_stomp_timer);
 }
 
 u16 ath9k_btcoex_aggr_limit(struct ath_softc *sc, u32 max_4ms_framelen)
index 60b6a9daff7e21cde68fb6eda800e4ca065c62aa..4faf0a3958765bd07ae683fdd6dceb879a5adbfd 100644 (file)
@@ -463,9 +463,6 @@ static void ath9k_hw_init_config(struct ath_hw *ah)
                ah->config.spurchans[i][1] = AR_NO_SPUR;
        }
 
-       /* PAPRD needs some more work to be enabled */
-       ah->config.paprd_disable = 1;
-
        ah->config.rx_intr_mitigation = true;
        ah->config.pcieSerDesWrite = true;
 
@@ -978,9 +975,6 @@ static void ath9k_hw_init_interrupt_masks(struct ath_hw *ah,
        else
                imr_reg |= AR_IMR_TXOK;
 
-       if (opmode == NL80211_IFTYPE_AP)
-               imr_reg |= AR_IMR_MIB;
-
        ENABLE_REGWRITE_BUFFER(ah);
 
        REG_WRITE(ah, AR_IMR, imr_reg);
@@ -1778,6 +1772,8 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
                /* Operating channel changed, reset channel calibration data */
                memset(caldata, 0, sizeof(*caldata));
                ath9k_init_nfcal_hist_buffer(ah, chan);
+       } else if (caldata) {
+               caldata->paprd_packet_sent = false;
        }
        ah->noise = ath9k_hw_getchan_noise(ah, chan);
 
@@ -2501,9 +2497,6 @@ int ath9k_hw_fill_cap_info(struct ath_hw *ah)
                pCap->rx_status_len = sizeof(struct ar9003_rxs);
                pCap->tx_desc_len = sizeof(struct ar9003_txc);
                pCap->txs_len = sizeof(struct ar9003_txs);
-               if (!ah->config.paprd_disable &&
-                   ah->eep_ops->get_eeprom(ah, EEP_PAPRD))
-                       pCap->hw_caps |= ATH9K_HW_CAP_PAPRD;
        } else {
                pCap->tx_desc_len = sizeof(struct ath_desc);
                if (AR_SREV_9280_20(ah))
index ce7332c64efb2c5b417cd40fec2428522186142a..de6968fc64f42920304fe52dd93a493c3ce679c6 100644 (file)
@@ -236,7 +236,6 @@ enum ath9k_hw_caps {
        ATH9K_HW_CAP_LDPC                       = BIT(6),
        ATH9K_HW_CAP_FASTCLOCK                  = BIT(7),
        ATH9K_HW_CAP_SGI_20                     = BIT(8),
-       ATH9K_HW_CAP_PAPRD                      = BIT(9),
        ATH9K_HW_CAP_ANT_DIV_COMB               = BIT(10),
        ATH9K_HW_CAP_2GHZ                       = BIT(11),
        ATH9K_HW_CAP_5GHZ                       = BIT(12),
@@ -287,12 +286,12 @@ struct ath9k_ops_config {
        u8 pcie_clock_req;
        u32 pcie_waen;
        u8 analog_shiftreg;
-       u8 paprd_disable;
        u32 ofdm_trig_low;
        u32 ofdm_trig_high;
        u32 cck_trig_high;
        u32 cck_trig_low;
        u32 enable_ani;
+       u32 enable_paprd;
        int serialize_regmode;
        bool rx_intr_mitigation;
        bool tx_intr_mitigation;
@@ -405,6 +404,7 @@ struct ath9k_hw_cal_data {
        int8_t iCoff;
        int8_t qCoff;
        bool rtt_done;
+       bool paprd_packet_sent;
        bool paprd_done;
        bool nfcal_pending;
        bool nfcal_interference;
index d4549e9aac5c5f1f30ace855d6c94dafe98f4d38..7b88b9c39ccddc4ef4e3aeafb53e437d0f35a0ce 100644 (file)
@@ -254,8 +254,9 @@ void ath_paprd_calibrate(struct work_struct *work)
        int chain_ok = 0;
        int chain;
        int len = 1800;
+       int ret;
 
-       if (!caldata)
+       if (!caldata || !caldata->paprd_packet_sent || caldata->paprd_done)
                return;
 
        ath9k_ps_wakeup(sc);
@@ -282,13 +283,6 @@ void ath_paprd_calibrate(struct work_struct *work)
                        continue;
 
                chain_ok = 0;
-
-               ath_dbg(common, CALIBRATE,
-                       "Sending PAPRD frame for thermal measurement on chain %d\n",
-                       chain);
-               if (!ath_paprd_send_frame(sc, skb, chain))
-                       goto fail_paprd;
-
                ar9003_paprd_setup_gain_table(ah, chain);
 
                ath_dbg(common, CALIBRATE,
@@ -302,7 +296,13 @@ void ath_paprd_calibrate(struct work_struct *work)
                        break;
                }
 
-               if (ar9003_paprd_create_curve(ah, caldata, chain)) {
+               ret = ar9003_paprd_create_curve(ah, caldata, chain);
+               if (ret == -EINPROGRESS) {
+                       ath_dbg(common, CALIBRATE,
+                               "PAPRD curve on chain %d needs to be re-trained\n",
+                               chain);
+                       break;
+               } else if (ret) {
                        ath_dbg(common, CALIBRATE,
                                "PAPRD create curve failed on chain %d\n",
                                chain);
@@ -423,7 +423,7 @@ set_timer:
                cal_interval = min(cal_interval, (u32)short_cal_interval);
 
        mod_timer(&common->ani.timer, jiffies + msecs_to_jiffies(cal_interval));
-       if ((sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_PAPRD) && ah->caldata) {
+       if (ah->eep_ops->get_eeprom(ah, EEP_PAPRD) && ah->caldata) {
                if (!ah->caldata->paprd_done)
                        ieee80211_queue_work(sc->hw, &sc->paprd_work);
                else if (!ah->paprd_table_write_done)
index 2c9da6b2ecb1b7b1141770f1240188bf2af50277..0d4155aec48d72196d5c64eee5c2517766760632 100644 (file)
@@ -2018,6 +2018,9 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
 
        ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
 
+       if (sc->sc_ah->caldata)
+               sc->sc_ah->caldata->paprd_packet_sent = true;
+
        if (!(tx_flags & ATH_TX_ERROR))
                /* Frame was ACKed */
                tx_info->flags |= IEEE80211_TX_STAT_ACK;
index 49765d34b4e0b43ac947aa360fb58d1fff88aa90..7c4ee72f9d56006cb7e069a9472a0524bbebb9c9 100644 (file)
@@ -638,6 +638,8 @@ static int brcmf_sdio_pd_probe(struct platform_device *pdev)
 
                oobirq_entry = kzalloc(sizeof(struct brcmf_sdio_oobirq),
                                       GFP_KERNEL);
+               if (!oobirq_entry)
+                       return -ENOMEM;
                oobirq_entry->irq = res->start;
                oobirq_entry->flags = res->flags & IRQF_TRIGGER_MASK;
                list_add_tail(&oobirq_entry->list, &oobirq_lh);
index 2621dd3d7dcd9d3b6ac5ca05db587cdd94454011..6f70953f0bade06ef046a845829a887611c0a8b8 100644 (file)
@@ -764,8 +764,11 @@ static void brcmf_c_arp_offload_set(struct brcmf_pub *drvr, int arp_mode)
 {
        char iovbuf[32];
        int retcode;
+       __le32 arp_mode_le;
 
-       brcmf_c_mkiovar("arp_ol", (char *)&arp_mode, 4, iovbuf, sizeof(iovbuf));
+       arp_mode_le = cpu_to_le32(arp_mode);
+       brcmf_c_mkiovar("arp_ol", (char *)&arp_mode_le, 4, iovbuf,
+                       sizeof(iovbuf));
        retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
                                   iovbuf, sizeof(iovbuf));
        retcode = retcode >= 0 ? 0 : retcode;
@@ -781,8 +784,11 @@ static void brcmf_c_arp_offload_enable(struct brcmf_pub *drvr, int arp_enable)
 {
        char iovbuf[32];
        int retcode;
+       __le32 arp_enable_le;
 
-       brcmf_c_mkiovar("arpoe", (char *)&arp_enable, 4,
+       arp_enable_le = cpu_to_le32(arp_enable);
+
+       brcmf_c_mkiovar("arpoe", (char *)&arp_enable_le, 4,
                        iovbuf, sizeof(iovbuf));
        retcode = brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR,
                                   iovbuf, sizeof(iovbuf));
@@ -800,10 +806,10 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
        char iovbuf[BRCMF_EVENTING_MASK_LEN + 12];      /*  Room for
                                 "event_msgs" + '\0' + bitvec  */
        char buf[128], *ptr;
-       u32 roaming = 1;
-       uint bcn_timeout = 3;
-       int scan_assoc_time = 40;
-       int scan_unassoc_time = 40;
+       __le32 roaming_le = cpu_to_le32(1);
+       __le32 bcn_timeout_le = cpu_to_le32(3);
+       __le32 scan_assoc_time_le = cpu_to_le32(40);
+       __le32 scan_unassoc_time_le = cpu_to_le32(40);
        int i;
        struct brcmf_bus_dcmd *cmdlst;
        struct list_head *cur, *q;
@@ -829,14 +835,14 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
 
        /* Setup timeout if Beacons are lost and roam is off to report
                 link down */
-       brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
+       brcmf_c_mkiovar("bcn_timeout", (char *)&bcn_timeout_le, 4, iovbuf,
                    sizeof(iovbuf));
        brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
                                  sizeof(iovbuf));
 
        /* Enable/Disable build-in roaming to allowed ext supplicant to take
                 of romaing */
-       brcmf_c_mkiovar("roam_off", (char *)&roaming, 4,
+       brcmf_c_mkiovar("roam_off", (char *)&roaming_le, 4,
                      iovbuf, sizeof(iovbuf));
        brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_VAR, iovbuf,
                                  sizeof(iovbuf));
@@ -848,9 +854,9 @@ int brcmf_c_preinit_dcmds(struct brcmf_pub *drvr)
                                  sizeof(iovbuf));
 
        brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_CHANNEL_TIME,
-                        (char *)&scan_assoc_time, sizeof(scan_assoc_time));
+                (char *)&scan_assoc_time_le, sizeof(scan_assoc_time_le));
        brcmf_proto_cdc_set_dcmd(drvr, 0, BRCMF_C_SET_SCAN_UNASSOC_TIME,
-                        (char *)&scan_unassoc_time, sizeof(scan_unassoc_time));
+                (char *)&scan_unassoc_time_le, sizeof(scan_unassoc_time_le));
 
        /* Set and enable ARP offload feature */
        brcmf_c_arp_offload_set(drvr, BRCMF_ARPOL_MODE);
index a299d42da8e74a358939b8fa5da8a32a01fd312b..58f89fa9c9f8a218ed29cfb93ad253c41471c648 100644 (file)
@@ -519,7 +519,7 @@ static void brcmf_usb_tx_complete(struct urb *urb)
        else
                devinfo->bus_pub.bus->dstats.tx_errors++;
 
-       dev_kfree_skb(req->skb);
+       brcmu_pkt_buf_free_skb(req->skb);
        req->skb = NULL;
        brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
 
@@ -540,7 +540,7 @@ static void brcmf_usb_rx_complete(struct urb *urb)
                devinfo->bus_pub.bus->dstats.rx_packets++;
        } else {
                devinfo->bus_pub.bus->dstats.rx_errors++;
-               dev_kfree_skb(skb);
+               brcmu_pkt_buf_free_skb(skb);
                brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
                return;
        }
@@ -550,13 +550,15 @@ static void brcmf_usb_rx_complete(struct urb *urb)
                if (brcmf_proto_hdrpull(devinfo->dev, &ifidx, skb) != 0) {
                        brcmf_dbg(ERROR, "rx protocol error\n");
                        brcmu_pkt_buf_free_skb(skb);
+                       brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
                        devinfo->bus_pub.bus->dstats.rx_errors++;
                } else {
                        brcmf_rx_packet(devinfo->dev, ifidx, skb);
                        brcmf_usb_rx_refill(devinfo, req);
                }
        } else {
-               dev_kfree_skb(skb);
+               brcmu_pkt_buf_free_skb(skb);
+               brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
        }
        return;
 
@@ -581,14 +583,13 @@ static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
        usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->rx_pipe,
                          skb->data, skb_tailroom(skb), brcmf_usb_rx_complete,
                          req);
-       req->urb->transfer_flags |= URB_ZERO_PACKET;
        req->devinfo = devinfo;
+       brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
 
        ret = usb_submit_urb(req->urb, GFP_ATOMIC);
-       if (ret == 0) {
-               brcmf_usb_enq(devinfo, &devinfo->rx_postq, req);
-       } else {
-               dev_kfree_skb(req->skb);
+       if (ret) {
+               brcmf_usb_del_fromq(devinfo, req);
+               brcmu_pkt_buf_free_skb(req->skb);
                req->skb = NULL;
                brcmf_usb_enq(devinfo, &devinfo->rx_freeq, req);
        }
@@ -683,23 +684,22 @@ static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
 
        req = brcmf_usb_deq(devinfo, &devinfo->tx_freeq);
        if (!req) {
+               brcmu_pkt_buf_free_skb(skb);
                brcmf_dbg(ERROR, "no req to send\n");
                return -ENOMEM;
        }
-       if (!req->urb) {
-               brcmf_dbg(ERROR, "no urb for req %p\n", req);
-               return -ENOBUFS;
-       }
 
        req->skb = skb;
        req->devinfo = devinfo;
        usb_fill_bulk_urb(req->urb, devinfo->usbdev, devinfo->tx_pipe,
                          skb->data, skb->len, brcmf_usb_tx_complete, req);
        req->urb->transfer_flags |= URB_ZERO_PACKET;
+       brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
        ret = usb_submit_urb(req->urb, GFP_ATOMIC);
-       if (!ret) {
-               brcmf_usb_enq(devinfo, &devinfo->tx_postq, req);
-       } else {
+       if (ret) {
+               brcmf_dbg(ERROR, "brcmf_usb_tx usb_submit_urb FAILED\n");
+               brcmf_usb_del_fromq(devinfo, req);
+               brcmu_pkt_buf_free_skb(req->skb);
                req->skb = NULL;
                brcmf_usb_enq(devinfo, &devinfo->tx_freeq, req);
        }
index 28c5fbb4af267b59ef1c8bab67f2d4ac2d7e9485..50b5553b6964b95dffecf40f4d28fdb91796efc8 100644 (file)
@@ -500,8 +500,10 @@ static void wl_iscan_prep(struct brcmf_scan_params_le *params_le,
        params_le->active_time = cpu_to_le32(-1);
        params_le->passive_time = cpu_to_le32(-1);
        params_le->home_time = cpu_to_le32(-1);
-       if (ssid && ssid->SSID_len)
-               memcpy(&params_le->ssid_le, ssid, sizeof(struct brcmf_ssid));
+       if (ssid && ssid->SSID_len) {
+               params_le->ssid_le.SSID_len = cpu_to_le32(ssid->SSID_len);
+               memcpy(&params_le->ssid_le.SSID, ssid->SSID, ssid->SSID_len);
+       }
 }
 
 static s32
@@ -1876,16 +1878,17 @@ brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
        }
 
        if (test_bit(WL_STATUS_CONNECTED, &cfg_priv->status)) {
-               scb_val.val = cpu_to_le32(0);
+               memset(&scb_val, 0, sizeof(scb_val));
                err = brcmf_exec_dcmd(ndev, BRCMF_C_GET_RSSI, &scb_val,
                                      sizeof(struct brcmf_scb_val_le));
-               if (err)
+               if (err) {
                        WL_ERR("Could not get rssi (%d)\n", err);
-
-               rssi = le32_to_cpu(scb_val.val);
-               sinfo->filled |= STATION_INFO_SIGNAL;
-               sinfo->signal = rssi;
-               WL_CONN("RSSI %d dBm\n", rssi);
+               } else {
+                       rssi = le32_to_cpu(scb_val.val);
+                       sinfo->filled |= STATION_INFO_SIGNAL;
+                       sinfo->signal = rssi;
+                       WL_CONN("RSSI %d dBm\n", rssi);
+               }
        }
 
 done:
index 7ed7d7577024628d228a78f6e94433c810295bc2..64a48f06d68bfa124c1687bc1fa81a799fb5be82 100644 (file)
@@ -77,7 +77,7 @@
                                         NL80211_RRF_NO_IBSS)
 
 static const struct ieee80211_regdomain brcms_regdom_x2 = {
-       .n_reg_rules = 7,
+       .n_reg_rules = 6,
        .alpha2 = "X2",
        .reg_rules = {
                BRCM_2GHZ_2412_2462,
index 192ad5c1fcc8813805702d7b75c4ab89761cfd42..a5edebeb0b4f7f748155551df76396602885078e 100644 (file)
@@ -1233,6 +1233,9 @@ uint brcms_reset(struct brcms_info *wl)
        /* dpc will not be rescheduled */
        wl->resched = false;
 
+       /* inform publicly that interface is down */
+       wl->pub->up = false;
+
        return 0;
 }
 
index 95aa8e1683ecb4bdeb663e0cf605d699407b96f0..83324b3216527ec72195b35da104a4ce6c5ad6e1 100644 (file)
@@ -2042,7 +2042,8 @@ static void isr_indicate_associated(struct ipw2100_priv *priv, u32 status)
                return;
        }
        len = ETH_ALEN;
-       ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, &bssid, &len);
+       ret = ipw2100_get_ordinal(priv, IPW_ORD_STAT_ASSN_AP_BSSID, bssid,
+                                 &len);
        if (ret) {
                IPW_DEBUG_INFO("failed querying ordinals at line %d\n",
                               __LINE__);
index 46782f1102ac7c8e159c3ef764a54205326923fd..a47b306b522cd3a49fcbb1622083baacb245d621 100644 (file)
@@ -124,6 +124,9 @@ static ssize_t iwl_dbgfs_sram_read(struct file *file,
        const struct fw_img *img;
        size_t bufsz;
 
+       if (!iwl_is_ready_rf(priv))
+               return -EAGAIN;
+
        /* default is to dump the entire data segment */
        if (!priv->dbgfs_sram_offset && !priv->dbgfs_sram_len) {
                priv->dbgfs_sram_offset = 0x800000;
index d9694c58208c38cd60575bb48f37bc75f42884bd..4ffc18dc3a5761cc6b63c5aa60691727459e5e27 100644 (file)
@@ -350,7 +350,7 @@ int iwl_queue_space(const struct iwl_queue *q);
 /*****************************************************
 * Error handling
 ******************************************************/
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display);
+int iwl_dump_fh(struct iwl_trans *trans, char **buf);
 void iwl_dump_csr(struct iwl_trans *trans);
 
 /*****************************************************
index 39a6ca1f009c39fdaf8c60775348f4790ede45dd..d1a61ba6247ab68a13e4cd8943959c92d0fa3452 100644 (file)
@@ -555,7 +555,7 @@ static void iwl_irq_handle_error(struct iwl_trans *trans)
        }
 
        iwl_dump_csr(trans);
-       iwl_dump_fh(trans, NULL, false);
+       iwl_dump_fh(trans, NULL);
 
        iwl_op_mode_nic_error(trans->op_mode);
 }
index 939c2f78df5833cc1d203deabe311568dc7ff88c..dbeebef562d5ca0bca0c9b3ac391747ebfe02973 100644 (file)
@@ -1442,6 +1442,7 @@ static int iwl_trans_pcie_start_hw(struct iwl_trans *trans)
        return err;
 
 err_free_irq:
+       trans_pcie->irq_requested = false;
        free_irq(trans_pcie->irq, trans);
 error:
        iwl_free_isr_ict(trans);
@@ -1649,13 +1650,9 @@ static const char *get_fh_string(int cmd)
 #undef IWL_CMD
 }
 
-int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
+int iwl_dump_fh(struct iwl_trans *trans, char **buf)
 {
        int i;
-#ifdef CONFIG_IWLWIFI_DEBUG
-       int pos = 0;
-       size_t bufsz = 0;
-#endif
        static const u32 fh_tbl[] = {
                FH_RSCSR_CHNL0_STTS_WPTR_REG,
                FH_RSCSR_CHNL0_RBDCB_BASE_REG,
@@ -1667,29 +1664,35 @@ int iwl_dump_fh(struct iwl_trans *trans, char **buf, bool display)
                FH_TSSR_TX_STATUS_REG,
                FH_TSSR_TX_ERROR_REG
        };
-#ifdef CONFIG_IWLWIFI_DEBUG
-       if (display) {
-               bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+       if (buf) {
+               int pos = 0;
+               size_t bufsz = ARRAY_SIZE(fh_tbl) * 48 + 40;
+
                *buf = kmalloc(bufsz, GFP_KERNEL);
                if (!*buf)
                        return -ENOMEM;
+
                pos += scnprintf(*buf + pos, bufsz - pos,
                                "FH register values:\n");
-               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++) {
+
+               for (i = 0; i < ARRAY_SIZE(fh_tbl); i++)
                        pos += scnprintf(*buf + pos, bufsz - pos,
                                "  %34s: 0X%08x\n",
                                get_fh_string(fh_tbl[i]),
                                iwl_read_direct32(trans, fh_tbl[i]));
-               }
+
                return pos;
        }
 #endif
+
        IWL_ERR(trans, "FH register values:\n");
-       for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++) {
+       for (i = 0; i <  ARRAY_SIZE(fh_tbl); i++)
                IWL_ERR(trans, "  %34s: 0X%08x\n",
                        get_fh_string(fh_tbl[i]),
                        iwl_read_direct32(trans, fh_tbl[i]));
-       }
+
        return 0;
 }
 
@@ -1982,11 +1985,11 @@ static ssize_t iwl_dbgfs_fh_reg_read(struct file *file,
                                     size_t count, loff_t *ppos)
 {
        struct iwl_trans *trans = file->private_data;
-       char *buf;
+       char *buf = NULL;
        int pos = 0;
        ssize_t ret = -EFAULT;
 
-       ret = pos = iwl_dump_fh(trans, &buf, true);
+       ret = pos = iwl_dump_fh(trans, &buf);
        if (buf) {
                ret = simple_read_from_buffer(user_buf,
                                              count, ppos, buf, pos);
index e970897f6ab52370a632a64a62cc10bb3c39a3c6..4cb234349fbfacc305b1565ed5f1a30ba16aa108 100644 (file)
@@ -1326,6 +1326,11 @@ static int if_sdio_suspend(struct device *dev)
 
        mmc_pm_flag_t flags = sdio_get_host_pm_caps(func);
 
+       /* If we're powered off anyway, just let the mmc layer remove the
+        * card. */
+       if (!lbs_iface_active(card->priv))
+               return -ENOSYS;
+
        dev_info(dev, "%s: suspend: PM flags = 0x%x\n",
                 sdio_func_id(func), flags);
 
index c68adec3cc8b6522678c98582c7781b885193849..565527aee0ea3f73caa832f336c0ded06a3b22d9 100644 (file)
@@ -170,7 +170,20 @@ static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv,
        cmd_code = le16_to_cpu(host_cmd->command);
        cmd_size = le16_to_cpu(host_cmd->size);
 
-       skb_trim(cmd_node->cmd_skb, cmd_size);
+       /* Adjust skb length */
+       if (cmd_node->cmd_skb->len > cmd_size)
+               /*
+                * cmd_size is less than sizeof(struct host_cmd_ds_command).
+                * Trim off the unused portion.
+                */
+               skb_trim(cmd_node->cmd_skb, cmd_size);
+       else if (cmd_node->cmd_skb->len < cmd_size)
+               /*
+                * cmd_size is larger than sizeof(struct host_cmd_ds_command)
+                * because we have appended custom IE TLV. Increase skb length
+                * accordingly.
+                */
+               skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len);
 
        do_gettimeofday(&tstamp);
        dev_dbg(adapter->dev, "cmd: DNLD_CMD: (%lu.%lu): %#x, act %#x, len %d,"
index 8b9dbd76a25255634ad79338223739c939429d26..64328af496f598bb3280784b6d2adfd25ec5cc70 100644 (file)
@@ -1611,6 +1611,7 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -1623,6 +1624,14 @@ static int rt2400pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_BIT8, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
        /*
         * Initialize hw specifications.
         */
index d3a4a68cc439b22faea7f6e9d4899e9313e5a7e2..7564ae992b735179b15e24a3d616c5a71acb1aeb 100644 (file)
 #define GPIOCSR_BIT5                   FIELD32(0x00000020)
 #define GPIOCSR_BIT6                   FIELD32(0x00000040)
 #define GPIOCSR_BIT7                   FIELD32(0x00000080)
+#define GPIOCSR_BIT8                   FIELD32(0x00000100)
 
 /*
  * BBPPCSR: BBP Pin control register.
index d2cf8a4bc8b52fd985f4720df6bc20a9269069c3..3de0406735f6b7347b46cdf2305e413aaa17256d 100644 (file)
@@ -1929,6 +1929,7 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -1941,6 +1942,14 @@ static int rt2500pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIOCSR, &reg);
+       rt2x00_set_field32(&reg, GPIOCSR_DIR0, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIOCSR, reg);
+
        /*
         * Initialize hw specifications.
         */
index 3aae36bb0a9e9f99cf89705bc2dca5022109824a..89fee311d8fda5ad07ae5ecd50fae567232aa35d 100644 (file)
@@ -283,7 +283,7 @@ static int rt2500usb_rfkill_poll(struct rt2x00_dev *rt2x00dev)
        u16 reg;
 
        rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
-       return rt2x00_get_field32(reg, MAC_CSR19_BIT7);
+       return rt2x00_get_field16(reg, MAC_CSR19_BIT7);
 }
 
 #ifdef CONFIG_RT2X00_LIB_LEDS
@@ -1768,6 +1768,7 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u16 reg;
 
        /*
         * Allocate eeprom data.
@@ -1780,6 +1781,14 @@ static int rt2500usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2500usb_register_read(rt2x00dev, MAC_CSR19, &reg);
+       rt2x00_set_field16(&reg, MAC_CSR19_BIT8, 0);
+       rt2500usb_register_write(rt2x00dev, MAC_CSR19, reg);
+
        /*
         * Initialize hw specifications.
         */
index b493306a7eede0888af2cccef613c6612b579514..196bd5103e4f5450483ce1e60449021bf6eafd2c 100644 (file)
  * MAC_CSR19: GPIO control register.
  */
 #define MAC_CSR19                      0x0426
-#define MAC_CSR19_BIT0                 FIELD32(0x0001)
-#define MAC_CSR19_BIT1                 FIELD32(0x0002)
-#define MAC_CSR19_BIT2                 FIELD32(0x0004)
-#define MAC_CSR19_BIT3                 FIELD32(0x0008)
-#define MAC_CSR19_BIT4                 FIELD32(0x0010)
-#define MAC_CSR19_BIT5                 FIELD32(0x0020)
-#define MAC_CSR19_BIT6                 FIELD32(0x0040)
-#define MAC_CSR19_BIT7                 FIELD32(0x0080)
+#define MAC_CSR19_BIT0                 FIELD16(0x0001)
+#define MAC_CSR19_BIT1                 FIELD16(0x0002)
+#define MAC_CSR19_BIT2                 FIELD16(0x0004)
+#define MAC_CSR19_BIT3                 FIELD16(0x0008)
+#define MAC_CSR19_BIT4                 FIELD16(0x0010)
+#define MAC_CSR19_BIT5                 FIELD16(0x0020)
+#define MAC_CSR19_BIT6                 FIELD16(0x0040)
+#define MAC_CSR19_BIT7                 FIELD16(0x0080)
+#define MAC_CSR19_BIT8                 FIELD16(0x0100)
 
 /*
  * MAC_CSR20: LED control register.
index cb8c2aca54e4dfdac4a7e223a8070f4e4543399e..b93516d832fb5603e4bb3d287a4770c0c8de06ad 100644 (file)
@@ -4089,6 +4089,7 @@ static int rt2800_init_rfcsr(struct rt2x00_dev *rt2x00dev)
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
                msleep(1);
                rt2800_register_read(rt2x00dev, LDO_CFG0, &reg);
+               rt2x00_set_field32(&reg, LDO_CFG0_LDO_CORE_VLEVEL, 0);
                rt2x00_set_field32(&reg, LDO_CFG0_BGSEL, 1);
                rt2800_register_write(rt2x00dev, LDO_CFG0, reg);
        }
index 98aa426a35649828e3c70c0f2bab0acf24e49381..4765bbd654cdcfeea617c84f9c755db05409600d 100644 (file)
@@ -983,6 +983,7 @@ static int rt2800pci_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -995,6 +996,14 @@ static int rt2800pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+       rt2x00pci_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
        /*
         * Initialize hw specifications.
         */
index 6cf336595e2544a5703612e5156af0559b5cc8ab..6b4226b716187ea037d2a1c84e012806649e8816 100644 (file)
@@ -667,8 +667,16 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
        skb_pull(entry->skb, RXINFO_DESC_SIZE);
 
        /*
-        * FIXME: we need to check for rx_pkt_len validity
+        * Check for rx_pkt_len validity. Return if invalid, leaving
+        * rxdesc->size zeroed out by the upper level.
         */
+       if (unlikely(rx_pkt_len == 0 ||
+                       rx_pkt_len > entry->queue->data_size)) {
+               ERROR(entry->queue->rt2x00dev,
+                       "Bad frame size %d, forcing to 0\n", rx_pkt_len);
+               return;
+       }
+
        rxd = (__le32 *)(entry->skb->data + rx_pkt_len);
 
        /*
@@ -736,6 +744,7 @@ static int rt2800usb_validate_eeprom(struct rt2x00_dev *rt2x00dev)
 static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -748,6 +757,14 @@ static int rt2800usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00usb_register_read(rt2x00dev, GPIO_CTRL_CFG, &reg);
+       rt2x00_set_field32(&reg, GPIO_CTRL_CFG_GPIOD_BIT2, 1);
+       rt2x00usb_register_write(rt2x00dev, GPIO_CTRL_CFG, reg);
+
        /*
         * Initialize hw specifications.
         */
@@ -1157,6 +1174,8 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x1690, 0x0744) },
        { USB_DEVICE(0x1690, 0x0761) },
        { USB_DEVICE(0x1690, 0x0764) },
+       /* ASUS */
+       { USB_DEVICE(0x0b05, 0x179d) },
        /* Cisco */
        { USB_DEVICE(0x167b, 0x4001) },
        /* EnGenius */
@@ -1222,7 +1241,6 @@ static struct usb_device_id rt2800usb_device_table[] = {
        { USB_DEVICE(0x0b05, 0x1760) },
        { USB_DEVICE(0x0b05, 0x1761) },
        { USB_DEVICE(0x0b05, 0x1790) },
-       { USB_DEVICE(0x0b05, 0x179d) },
        /* AzureWave */
        { USB_DEVICE(0x13d3, 0x3262) },
        { USB_DEVICE(0x13d3, 0x3284) },
index a6b88bd4a1a57d7f904c75faa62c95ea219be029..3f07e36f462b384565884580170faf7c3be2f25f 100644 (file)
@@ -629,7 +629,7 @@ void rt2x00lib_rxdone(struct queue_entry *entry, gfp_t gfp)
         */
        if (unlikely(rxdesc.size == 0 ||
                     rxdesc.size > entry->queue->data_size)) {
-               WARNING(rt2x00dev, "Wrong frame size %d max %d.\n",
+               ERROR(rt2x00dev, "Wrong frame size %d max %d.\n",
                        rxdesc.size, entry->queue->data_size);
                dev_kfree_skb(entry->skb);
                goto renew_skb;
index 3f7bc5cadf9a8a7a433688e8d480d76de3c1ab82..b8ec96163922a11711a3d6800b9556052c1386fc 100644 (file)
@@ -2832,6 +2832,7 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Disable power saving.
@@ -2849,6 +2850,14 @@ static int rt61pci_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00pci_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_BIT13, 1);
+       rt2x00pci_register_write(rt2x00dev, MAC_CSR13, reg);
+
        /*
         * Initialize hw specifications.
         */
index e3cd6db76b0e561d481873d22c5637d3d1732446..8f3da5a56766f4c3293825c2d649078f4cb5455f 100644 (file)
@@ -372,6 +372,7 @@ struct hw_pairwise_ta_entry {
 #define MAC_CSR13_BIT10                        FIELD32(0x00000400)
 #define MAC_CSR13_BIT11                        FIELD32(0x00000800)
 #define MAC_CSR13_BIT12                        FIELD32(0x00001000)
+#define MAC_CSR13_BIT13                        FIELD32(0x00002000)
 
 /*
  * MAC_CSR14: LED control register.
index ba6e434b859d66506c26c5f05b7d5a569403c9d9..248436c13ce04ae1f79312c6cbb1e16d8a4b5fc9 100644 (file)
@@ -2177,6 +2177,7 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
 static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
 {
        int retval;
+       u32 reg;
 
        /*
         * Allocate eeprom data.
@@ -2189,6 +2190,14 @@ static int rt73usb_probe_hw(struct rt2x00_dev *rt2x00dev)
        if (retval)
                return retval;
 
+       /*
+        * Enable rfkill polling by setting GPIO direction of the
+        * rfkill switch GPIO pin correctly.
+        */
+       rt2x00usb_register_read(rt2x00dev, MAC_CSR13, &reg);
+       rt2x00_set_field32(&reg, MAC_CSR13_BIT15, 0);
+       rt2x00usb_register_write(rt2x00dev, MAC_CSR13, reg);
+
        /*
         * Initialize hw specifications.
         */
index 9f6b470414d33a687c8795b380add18cd8efaeb4..df1cc116b83be891ee2ff20702260f5949d3d983 100644 (file)
@@ -282,6 +282,9 @@ struct hw_pairwise_ta_entry {
 #define MAC_CSR13_BIT10                        FIELD32(0x00000400)
 #define MAC_CSR13_BIT11                        FIELD32(0x00000800)
 #define MAC_CSR13_BIT12                        FIELD32(0x00001000)
+#define MAC_CSR13_BIT13                        FIELD32(0x00002000)
+#define MAC_CSR13_BIT14                        FIELD32(0x00004000)
+#define MAC_CSR13_BIT15                        FIELD32(0x00008000)
 
 /*
  * MAC_CSR14: LED control register.
index 04c3aef8a4f62e178fbac155a956c64c529b97c8..2925094b2d912529fb32dc5202487d1def6d9910 100644 (file)
 
 #define CHIP_VER_B                     BIT(4)
 #define CHIP_92C_BITMASK               BIT(0)
+#define CHIP_UNKNOWN                   BIT(7)
 #define CHIP_92C_1T2R                  0x03
 #define CHIP_92C                       0x01
 #define CHIP_88C                       0x00
index bd0da7ef290b3cf5cafafe4d56ec4c3d7cf33611..dd4bb0950a575ddd37c31489f10d2bacdaaab940 100644 (file)
@@ -994,8 +994,16 @@ static enum version_8192c _rtl92ce_read_chip_version(struct ieee80211_hw *hw)
                version = (value32 & TYPE_ID) ? VERSION_A_CHIP_92C :
                           VERSION_A_CHIP_88C;
        } else {
-               version = (value32 & TYPE_ID) ? VERSION_B_CHIP_92C :
-                          VERSION_B_CHIP_88C;
+               version = (enum version_8192c) (CHIP_VER_B |
+                               ((value32 & TYPE_ID) ? CHIP_92C_BITMASK : 0) |
+                               ((value32 & VENDOR_ID) ? CHIP_VENDOR_UMC : 0));
+               if ((!IS_CHIP_VENDOR_UMC(version)) && (value32 &
+                    CHIP_VER_RTL_MASK)) {
+                       version = (enum version_8192c)(version |
+                                  ((((value32 & CHIP_VER_RTL_MASK) == BIT(12))
+                                  ? CHIP_VENDOR_UMC_B_CUT : CHIP_UNKNOWN) |
+                                  CHIP_VENDOR_UMC));
+               }
        }
 
        switch (version) {
index 3aa927f8b9b93bfbf0b12d9d0194966cd24900c8..7d8f96405f42068bafa9c08d7ec6a382f2e2c7f0 100644 (file)
@@ -162,10 +162,12 @@ int rtl92c_init_sw_vars(struct ieee80211_hw *hw)
 
        /* request fw */
        if (IS_VENDOR_UMC_A_CUT(rtlhal->version) &&
-           !IS_92C_SERIAL(rtlhal->version))
+           !IS_92C_SERIAL(rtlhal->version)) {
                rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU.bin";
-       else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version))
+       } else if (IS_81xxC_VENDOR_UMC_B_CUT(rtlhal->version)) {
                rtlpriv->cfg->fw_name = "rtlwifi/rtl8192cfwU_B.bin";
+               pr_info("****** This B_CUT device may not work with kernels 3.6 and earlier\n");
+       }
 
        rtlpriv->max_fw_size = 0x4000;
        pr_info("Using firmware %s\n", rtlpriv->cfg->fw_name);
index 30899901aef56b00e05c5f062c86cabcb54127d8..650f79a1f2bd4a89cd96326d63c85982b24db0aa 100644 (file)
@@ -57,8 +57,7 @@
 static const struct ethtool_ops xennet_ethtool_ops;
 
 struct netfront_cb {
-       struct page *page;
-       unsigned offset;
+       int pull_to;
 };
 
 #define NETFRONT_SKB_CB(skb)   ((struct netfront_cb *)((skb)->cb))
@@ -867,15 +866,9 @@ static int handle_incoming_queue(struct net_device *dev,
        struct sk_buff *skb;
 
        while ((skb = __skb_dequeue(rxq)) != NULL) {
-               struct page *page = NETFRONT_SKB_CB(skb)->page;
-               void *vaddr = page_address(page);
-               unsigned offset = NETFRONT_SKB_CB(skb)->offset;
-
-               memcpy(skb->data, vaddr + offset,
-                      skb_headlen(skb));
+               int pull_to = NETFRONT_SKB_CB(skb)->pull_to;
 
-               if (page != skb_frag_page(&skb_shinfo(skb)->frags[0]))
-                       __free_page(page);
+               __pskb_pull_tail(skb, pull_to - skb_headlen(skb));
 
                /* Ethernet work: Delayed to here as it peeks the header. */
                skb->protocol = eth_type_trans(skb, dev);
@@ -913,7 +906,6 @@ static int xennet_poll(struct napi_struct *napi, int budget)
        struct sk_buff_head errq;
        struct sk_buff_head tmpq;
        unsigned long flags;
-       unsigned int len;
        int err;
 
        spin_lock(&np->rx_lock);
@@ -955,24 +947,13 @@ err:
                        }
                }
 
-               NETFRONT_SKB_CB(skb)->page =
-                       skb_frag_page(&skb_shinfo(skb)->frags[0]);
-               NETFRONT_SKB_CB(skb)->offset = rx->offset;
-
-               len = rx->status;
-               if (len > RX_COPY_THRESHOLD)
-                       len = RX_COPY_THRESHOLD;
-               skb_put(skb, len);
+               NETFRONT_SKB_CB(skb)->pull_to = rx->status;
+               if (NETFRONT_SKB_CB(skb)->pull_to > RX_COPY_THRESHOLD)
+                       NETFRONT_SKB_CB(skb)->pull_to = RX_COPY_THRESHOLD;
 
-               if (rx->status > len) {
-                       skb_shinfo(skb)->frags[0].page_offset =
-                               rx->offset + len;
-                       skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status - len);
-                       skb->data_len = rx->status - len;
-               } else {
-                       __skb_fill_page_desc(skb, 0, NULL, 0, 0);
-                       skb_shinfo(skb)->nr_frags = 0;
-               }
+               skb_shinfo(skb)->frags[0].page_offset = rx->offset;
+               skb_frag_size_set(&skb_shinfo(skb)->frags[0], rx->status);
+               skb->data_len = rx->status;
 
                i = xennet_fill_frags(np, skb, &tmpq);
 
@@ -999,7 +980,7 @@ err:
                 * receive throughout using the standard receive
                 * buffer size was cut by 25%(!!!).
                 */
-               skb->truesize += skb->data_len - (RX_COPY_THRESHOLD - len);
+               skb->truesize += skb->data_len - RX_COPY_THRESHOLD;
                skb->len += skb->data_len;
 
                if (rx->flags & XEN_NETRXF_csum_blank)
index 5270f1a99328d678396739781c7b0d4a87a586ef..d6fd6b6d9d4b575c26eb0041e503ddb10ddb9d64 100644 (file)
@@ -280,8 +280,12 @@ static long local_pci_probe(void *_ddi)
 {
        struct drv_dev_and_id *ddi = _ddi;
        struct device *dev = &ddi->dev->dev;
+       struct device *parent = dev->parent;
        int rc;
 
+       /* The parent bridge must be in active state when probing */
+       if (parent)
+               pm_runtime_get_sync(parent);
        /* Unbound PCI devices are always set to disabled and suspended.
         * During probe, the device is set to enabled and active and the
         * usage count is incremented.  If the driver supports runtime PM,
@@ -298,6 +302,8 @@ static long local_pci_probe(void *_ddi)
                pm_runtime_set_suspended(dev);
                pm_runtime_put_noidle(dev);
        }
+       if (parent)
+               pm_runtime_put(parent);
        return rc;
 }
 
index 6869009c7393f7081497c51901f11f31e62957bf..02d107b152818e948cc3e561d276bf24126ac997 100644 (file)
@@ -458,6 +458,40 @@ boot_vga_show(struct device *dev, struct device_attribute *attr, char *buf)
 }
 struct device_attribute vga_attr = __ATTR_RO(boot_vga);
 
+static void
+pci_config_pm_runtime_get(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       if (parent)
+               pm_runtime_get_sync(parent);
+       pm_runtime_get_noresume(dev);
+       /*
+        * pdev->current_state is set to PCI_D3cold during suspending,
+        * so wait until suspending completes
+        */
+       pm_runtime_barrier(dev);
+       /*
+        * Only need to resume devices in D3cold, because config
+        * registers are still accessible for devices suspended but
+        * not in D3cold.
+        */
+       if (pdev->current_state == PCI_D3cold)
+               pm_runtime_resume(dev);
+}
+
+static void
+pci_config_pm_runtime_put(struct pci_dev *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct device *parent = dev->parent;
+
+       pm_runtime_put(dev);
+       if (parent)
+               pm_runtime_put_sync(parent);
+}
+
 static ssize_t
 pci_read_config(struct file *filp, struct kobject *kobj,
                struct bin_attribute *bin_attr,
@@ -484,6 +518,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                size = count;
        }
 
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                u8 val;
                pci_user_read_config_byte(dev, off, &val);
@@ -529,6 +565,8 @@ pci_read_config(struct file *filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
@@ -549,6 +587,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                count = size;
        }
        
+       pci_config_pm_runtime_get(dev);
+
        if ((off & 1) && size) {
                pci_user_write_config_byte(dev, off, data[off - init_off]);
                off++;
@@ -587,6 +627,8 @@ pci_write_config(struct file* filp, struct kobject *kobj,
                --size;
        }
 
+       pci_config_pm_runtime_put(dev);
+
        return count;
 }
 
index f3ea977a5b1bf6f458c8ed0757cd8e02cc1d3ff2..ab4bf5a4c2f12ee6dc90a83666d03387fc618fca 100644 (file)
@@ -1941,6 +1941,7 @@ void pci_pm_init(struct pci_dev *dev)
        dev->pm_cap = pm;
        dev->d3_delay = PCI_PM_D3_WAIT;
        dev->d3cold_delay = PCI_PM_D3COLD_WAIT;
+       dev->d3cold_allowed = true;
 
        dev->d1_support = false;
        dev->d2_support = false;
index 3a7eefcb270a5dda9a2dcbcead63086da4433c3e..e76b44777dbf7f2893ecdcde08997cad1d904eb4 100644 (file)
@@ -140,9 +140,17 @@ static int pcie_port_runtime_resume(struct device *dev)
 {
        return 0;
 }
+
+static int pcie_port_runtime_idle(struct device *dev)
+{
+       /* Delay for a short while to prevent too frequent suspend/resume */
+       pm_schedule_suspend(dev, 10);
+       return -EBUSY;
+}
 #else
 #define pcie_port_runtime_suspend      NULL
 #define pcie_port_runtime_resume       NULL
+#define pcie_port_runtime_idle         NULL
 #endif
 
 static const struct dev_pm_ops pcie_portdrv_pm_ops = {
@@ -155,6 +163,7 @@ static const struct dev_pm_ops pcie_portdrv_pm_ops = {
        .resume_noirq   = pcie_port_resume_noirq,
        .runtime_suspend = pcie_port_runtime_suspend,
        .runtime_resume = pcie_port_runtime_resume,
+       .runtime_idle   = pcie_port_runtime_idle,
 };
 
 #define PCIE_PORTDRV_PM_OPS    (&pcie_portdrv_pm_ops)
@@ -200,6 +209,11 @@ static int __devinit pcie_portdrv_probe(struct pci_dev *dev,
                return status;
 
        pci_save_state(dev);
+       /*
+        * D3cold may not work properly on some PCIe port, so disable
+        * it by default.
+        */
+       dev->d3cold_allowed = false;
        if (!pci_match_id(port_runtime_pm_black_list, dev))
                pm_runtime_put_noidle(&dev->dev);
 
index 6c143b4497ca4381677dcc34459ecf269e5cdc88..9f8a6b79a8ecf22d604056a902e7ca7adee8520a 100644 (file)
@@ -144,15 +144,13 @@ static inline unsigned long decode_bar(struct pci_dev *dev, u32 bar)
        case PCI_BASE_ADDRESS_MEM_TYPE_32:
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_1M:
-               dev_info(&dev->dev, "1M mem BAR treated as 32-bit BAR\n");
+               /* 1M mem BAR treated as 32-bit BAR */
                break;
        case PCI_BASE_ADDRESS_MEM_TYPE_64:
                flags |= IORESOURCE_MEM_64;
                break;
        default:
-               dev_warn(&dev->dev,
-                        "mem unknown type %x treated as 32-bit BAR\n",
-                        mem_type);
+               /* mem unknown type treated as 32-bit BAR */
                break;
        }
        return flags;
@@ -173,9 +171,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
        u32 l, sz, mask;
        u16 orig_cmd;
        struct pci_bus_region region;
+       bool bar_too_big = false, bar_disabled = false;
 
        mask = type ? PCI_ROM_ADDRESS_MASK : ~0;
 
+       /* No printks while decoding is disabled! */
        if (!dev->mmio_always_on) {
                pci_read_config_word(dev, PCI_COMMAND, &orig_cmd);
                pci_write_config_word(dev, PCI_COMMAND,
@@ -240,8 +240,7 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        goto fail;
 
                if ((sizeof(resource_size_t) < 8) && (sz64 > 0x100000000ULL)) {
-                       dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n",
-                               pos);
+                       bar_too_big = true;
                        goto fail;
                }
 
@@ -252,12 +251,11 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                        region.start = 0;
                        region.end = sz64;
                        pcibios_bus_to_resource(dev, res, &region);
+                       bar_disabled = true;
                } else {
                        region.start = l64;
                        region.end = l64 + sz64;
                        pcibios_bus_to_resource(dev, res, &region);
-                       dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n",
-                                  pos, res);
                }
        } else {
                sz = pci_size(l, sz, mask);
@@ -268,18 +266,23 @@ int __pci_read_base(struct pci_dev *dev, enum pci_bar_type type,
                region.start = l;
                region.end = l + sz;
                pcibios_bus_to_resource(dev, res, &region);
-
-               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
        }
 
- out:
+       goto out;
+
+
+fail:
+       res->flags = 0;
+out:
        if (!dev->mmio_always_on)
                pci_write_config_word(dev, PCI_COMMAND, orig_cmd);
 
+       if (bar_too_big)
+               dev_err(&dev->dev, "reg %x: can't handle 64-bit BAR\n", pos);
+       if (res->flags && !bar_disabled)
+               dev_printk(KERN_DEBUG, &dev->dev, "reg %x: %pR\n", pos, res);
+
        return (res->flags & IORESOURCE_MEM_64) ? 1 : 0;
- fail:
-       res->flags = 0;
-       goto out;
 }
 
 static void pci_read_bases(struct pci_dev *dev, unsigned int howmany, int rom)
index 3782e1cd3697020219d34b81aa039a8c767be486..934d861a32359bb553ce17966d152f089b31c04d 100644 (file)
@@ -2196,10 +2196,8 @@ static int __init acer_wmi_init(void)
                interface->capability &= ~ACER_CAP_BRIGHTNESS;
                pr_info("Brightness must be controlled by acpi video driver\n");
        } else {
-#ifdef CONFIG_ACPI_VIDEO
                pr_info("Disabling ACPI video driver\n");
                acpi_video_unregister();
-#endif
        }
 
        if (wmi_has_guid(WMID_GUID3)) {
index dfb1a92ce9497cb49e913fa23d8f8819300243e9..db8f63841b4265922b5a630c020e00cb4f490ad3 100644 (file)
@@ -101,7 +101,7 @@ static void gmux_pio_write32(struct apple_gmux_data *gmux_data, int port,
 
        for (i = 0; i < 4; i++) {
                tmpval = (val >> (i * 8)) & 0xff;
-               outb(tmpval, port + i);
+               outb(tmpval, gmux_data->iostart + port + i);
        }
 }
 
@@ -142,8 +142,9 @@ static u8 gmux_index_read8(struct apple_gmux_data *gmux_data, int port)
        u8 val;
 
        mutex_lock(&gmux_data->index_lock);
-       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
        gmux_index_wait_ready(gmux_data);
+       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+       gmux_index_wait_complete(gmux_data);
        val = inb(gmux_data->iostart + GMUX_PORT_VALUE);
        mutex_unlock(&gmux_data->index_lock);
 
@@ -166,8 +167,9 @@ static u32 gmux_index_read32(struct apple_gmux_data *gmux_data, int port)
        u32 val;
 
        mutex_lock(&gmux_data->index_lock);
-       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
        gmux_index_wait_ready(gmux_data);
+       outb((port & 0xff), gmux_data->iostart + GMUX_PORT_READ);
+       gmux_index_wait_complete(gmux_data);
        val = inl(gmux_data->iostart + GMUX_PORT_VALUE);
        mutex_unlock(&gmux_data->index_lock);
 
@@ -461,18 +463,22 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
        ver_release = gmux_read8(gmux_data, GMUX_PORT_VERSION_RELEASE);
        if (ver_major == 0xff && ver_minor == 0xff && ver_release == 0xff) {
                if (gmux_is_indexed(gmux_data)) {
+                       u32 version;
                        mutex_init(&gmux_data->index_lock);
                        gmux_data->indexed = true;
+                       version = gmux_read32(gmux_data,
+                               GMUX_PORT_VERSION_MAJOR);
+                       ver_major = (version >> 24) & 0xff;
+                       ver_minor = (version >> 16) & 0xff;
+                       ver_release = (version >> 8) & 0xff;
                } else {
                        pr_info("gmux device not present\n");
                        ret = -ENODEV;
                        goto err_release;
                }
-               pr_info("Found indexed gmux\n");
-       } else {
-               pr_info("Found gmux version %d.%d.%d\n", ver_major, ver_minor,
-                       ver_release);
        }
+       pr_info("Found gmux version %d.%d.%d [%s]\n", ver_major, ver_minor,
+               ver_release, (gmux_data->indexed ? "indexed" : "classic"));
 
        memset(&props, 0, sizeof(props));
        props.type = BACKLIGHT_PLATFORM;
@@ -505,9 +511,7 @@ static int __devinit gmux_probe(struct pnp_dev *pnp,
         * Disable the other backlight choices.
         */
        acpi_video_dmi_promote_vendor();
-#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)
        acpi_video_unregister();
-#endif
        apple_bl_unregister();
 
        gmux_data->power_state = VGA_SWITCHEROO_ON;
@@ -593,9 +597,7 @@ static void __devexit gmux_remove(struct pnp_dev *pnp)
        kfree(gmux_data);
 
        acpi_video_dmi_demote_vendor();
-#if defined (CONFIG_ACPI_VIDEO) || defined (CONFIG_ACPI_VIDEO_MODULE)
        acpi_video_register();
-#endif
        apple_bl_register();
 }
 
index e38f91be0b10964c12f6a9b8eb4347908fc54d94..4b568df56643f846de78a3228582342fb3a89c67 100644 (file)
@@ -85,7 +85,7 @@ static char *wled_type = "unknown";
 static char *bled_type = "unknown";
 
 module_param(wled_type, charp, 0444);
-MODULE_PARM_DESC(wlan_status, "Set the wled type on boot "
+MODULE_PARM_DESC(wled_type, "Set the wled type on boot "
                 "(unknown, led or rfkill). "
                 "default is unknown");
 
@@ -863,9 +863,9 @@ static ssize_t show_infos(struct device *dev,
         * The significance of others is yet to be found.
         * If we don't find the method, we assume the device are present.
         */
-       rv = acpi_evaluate_integer(asus->handle, "HRWS", NULL, &temp);
+       rv = acpi_evaluate_integer(asus->handle, "HWRS", NULL, &temp);
        if (!ACPI_FAILURE(rv))
-               len += sprintf(page + len, "HRWS value         : %#x\n",
+               len += sprintf(page + len, "HWRS value         : %#x\n",
                               (uint) temp);
        /*
         * Another value for userspace: the ASYM method returns 0x02 for
@@ -1751,9 +1751,9 @@ static int asus_laptop_get_info(struct asus_laptop *asus)
         * The significance of others is yet to be found.
         */
        status =
-           acpi_evaluate_integer(asus->handle, "HRWS", NULL, &hwrs_result);
+           acpi_evaluate_integer(asus->handle, "HWRS", NULL, &hwrs_result);
        if (!ACPI_FAILURE(status))
-               pr_notice("  HRWS returned %x", (int)hwrs_result);
+               pr_notice("  HWRS returned %x", (int)hwrs_result);
 
        if (!acpi_check_handle(asus->handle, METHOD_WL_STATUS, NULL))
                asus->have_rsts = true;
index 2eb9fe8e8efd038c7bb1d25ad4fbde2961ca8e1a..c0e9ff489b2417f2469e7abc7d2289e4b971c8a2 100644 (file)
@@ -47,9 +47,7 @@
 #include <linux/thermal.h>
 #include <acpi/acpi_bus.h>
 #include <acpi/acpi_drivers.h>
-#ifdef CONFIG_ACPI_VIDEO
 #include <acpi/video.h>
-#endif
 
 #include "asus-wmi.h"
 
@@ -1704,10 +1702,8 @@ static int asus_wmi_add(struct platform_device *pdev)
        if (asus->driver->quirks->wmi_backlight_power)
                acpi_video_dmi_promote_vendor();
        if (!acpi_video_backlight_support()) {
-#ifdef CONFIG_ACPI_VIDEO
                pr_info("Disabling ACPI video driver\n");
                acpi_video_unregister();
-#endif
                err = asus_wmi_backlight_init(asus);
                if (err && err != -ENODEV)
                        goto fail_backlight;
index dab91b48d22cf5fbb955efd7ecb5fc0f6fa318c1..5ca264179f4e32a758102b0a05f865164250534b 100644 (file)
@@ -610,12 +610,12 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
 
                if (!bus) {
                        pr_warn("Unable to find PCI bus 1?\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                if (pci_bus_read_config_dword(bus, 0, PCI_VENDOR_ID, &l)) {
                        pr_err("Unable to read PCI config space?\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                absent = (l == 0xffffffff);
@@ -627,7 +627,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                                absent ? "absent" : "present");
                        pr_warn("skipped wireless hotplug as probably "
                                "inappropriate for this model\n");
-                       goto out_unlock;
+                       goto out_put_dev;
                }
 
                if (!blocked) {
@@ -635,7 +635,7 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                        if (dev) {
                                /* Device already present */
                                pci_dev_put(dev);
-                               goto out_unlock;
+                               goto out_put_dev;
                        }
                        dev = pci_scan_single_device(bus, 0);
                        if (dev) {
@@ -650,6 +650,8 @@ static void eeepc_rfkill_hotplug(struct eeepc_laptop *eeepc, acpi_handle handle)
                                pci_dev_put(dev);
                        }
                }
+out_put_dev:
+               pci_dev_put(port);
        }
 
 out_unlock:
index c1ca7bcebb66b52bfb033fc24cc0bc2856bd313d..dd90d15f52101e24296b30523d68056e01bac7df 100644 (file)
@@ -26,9 +26,7 @@
 #include <linux/seq_file.h>
 #include <linux/debugfs.h>
 #include <linux/ctype.h>
-#ifdef CONFIG_ACPI_VIDEO
 #include <acpi/video.h>
-#endif
 
 /*
  * This driver is needed because a number of Samsung laptops do not hook
@@ -1558,9 +1556,7 @@ static int __init samsung_init(void)
                samsung->handle_backlight = false;
        } else if (samsung->quirks->broken_acpi_video) {
                pr_info("Disabling ACPI video driver\n");
-#ifdef CONFIG_ACPI_VIDEO
                acpi_video_unregister();
-#endif
        }
 #endif
 
index 80e377949314ba37b3f00f09655290ed062349ed..52daaa816e53691792b6071955dbe680c4721b91 100644 (file)
@@ -545,7 +545,7 @@ TPACPI_HANDLE(hkey, ec, "\\_SB.HKEY",       /* 600e/x, 770e, 770x */
  */
 
 static int acpi_evalf(acpi_handle handle,
-                     void *res, char *method, char *fmt, ...)
+                     int *res, char *method, char *fmt, ...)
 {
        char *fmt0 = fmt;
        struct acpi_object_list params;
@@ -606,7 +606,7 @@ static int acpi_evalf(acpi_handle handle,
                success = (status == AE_OK &&
                           out_obj.type == ACPI_TYPE_INTEGER);
                if (success && res)
-                       *(int *)res = out_obj.integer.value;
+                       *res = out_obj.integer.value;
                break;
        case 'v':               /* void */
                success = status == AE_OK;
@@ -7386,17 +7386,18 @@ static int fan_get_status(u8 *status)
         * Add TPACPI_FAN_RD_ACPI_FANS ? */
 
        switch (fan_status_access_mode) {
-       case TPACPI_FAN_RD_ACPI_GFAN:
+       case TPACPI_FAN_RD_ACPI_GFAN: {
                /* 570, 600e/x, 770e, 770x */
+               int res;
 
-               if (unlikely(!acpi_evalf(gfan_handle, &s, NULL, "d")))
+               if (unlikely(!acpi_evalf(gfan_handle, &res, NULL, "d")))
                        return -EIO;
 
                if (likely(status))
-                       *status = s & 0x07;
+                       *status = res & 0x07;
 
                break;
-
+       }
        case TPACPI_FAN_RD_TPEC:
                /* all except 570, 600e/x, 770e, 770x */
                if (unlikely(!acpi_ec_read(fan_status_offset, &s)))
index 0b66d0f259224f9e7ca679a2759a473708cd3be6..4b6688909fee076c5573e086b972b7b3cf5ebffc 100644 (file)
@@ -100,6 +100,13 @@ static int ecap_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                writel(period_cycles, pc->mmio_base + CAP3);
        }
 
+       if (!test_bit(PWMF_ENABLED, &pwm->flags)) {
+               reg_val = readw(pc->mmio_base + ECCTL2);
+               /* Disable APWM mode to put APWM output Low */
+               reg_val &= ~ECCTL2_APWM_MODE;
+               writew(reg_val, pc->mmio_base + ECCTL2);
+       }
+
        pm_runtime_put_sync(pc->chip.dev);
        return 0;
 }
index c3756d1be19496fdf3dd163787b7e289e9ad70bd..b1996bcd5b788fd8923ef646b828d71dbc769265 100644 (file)
@@ -104,6 +104,7 @@ struct ehrpwm_pwm_chip {
        struct pwm_chip chip;
        unsigned int    clk_rate;
        void __iomem    *mmio_base;
+       unsigned long period_cycles[NUM_PWM_CHANNEL];
 };
 
 static inline struct ehrpwm_pwm_chip *to_ehrpwm_pwm_chip(struct pwm_chip *chip)
@@ -210,6 +211,7 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
        unsigned long long c;
        unsigned long period_cycles, duty_cycles;
        unsigned short ps_divval, tb_divval;
+       int i;
 
        if (period_ns < 0 || duty_ns < 0 || period_ns > NSEC_PER_SEC)
                return -ERANGE;
@@ -229,6 +231,28 @@ static int ehrpwm_pwm_config(struct pwm_chip *chip, struct pwm_device *pwm,
                duty_cycles = (unsigned long)c;
        }
 
+       /*
+        * Period values should be same for multiple PWM channels as IP uses
+        * same period register for multiple channels.
+        */
+       for (i = 0; i < NUM_PWM_CHANNEL; i++) {
+               if (pc->period_cycles[i] &&
+                               (pc->period_cycles[i] != period_cycles)) {
+                       /*
+                        * Allow channel to reconfigure period if no other
+                        * channels being configured.
+                        */
+                       if (i == pwm->hwpwm)
+                               continue;
+
+                       dev_err(chip->dev, "Period value conflicts with channel %d\n",
+                                       i);
+                       return -EINVAL;
+               }
+       }
+
+       pc->period_cycles[pwm->hwpwm] = period_cycles;
+
        /* Configure clock prescaler to support Low frequency PWM wave */
        if (set_prescale_div(period_cycles/PERIOD_MAX, &ps_divval,
                                &tb_divval)) {
@@ -320,10 +344,15 @@ static void ehrpwm_pwm_disable(struct pwm_chip *chip, struct pwm_device *pwm)
 
 static void ehrpwm_pwm_free(struct pwm_chip *chip, struct pwm_device *pwm)
 {
+       struct ehrpwm_pwm_chip *pc = to_ehrpwm_pwm_chip(chip);
+
        if (test_bit(PWMF_ENABLED, &pwm->flags)) {
                dev_warn(chip->dev, "Removing PWM device without disabling\n");
                pm_runtime_put_sync(chip->dev);
        }
+
+       /* set period value to zero on free */
+       pc->period_cycles[pwm->hwpwm] = 0;
 }
 
 static const struct pwm_ops ehrpwm_pwm_ops = {
index 6caa222af77a284f09f1e8a5f634da794dd84838..ab00cab905b730459c6e752907f1139aaec9ee57 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/err.h>
 #include <linux/platform_device.h>
 
+#include <linux/regulator/of_regulator.h>
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 #include <linux/mfd/tps65217.h>
@@ -281,37 +282,130 @@ static const struct regulator_desc regulators[] = {
                           NULL),
 };
 
+#ifdef CONFIG_OF
+static struct of_regulator_match reg_matches[] = {
+       { .name = "dcdc1", .driver_data = (void *)TPS65217_DCDC_1 },
+       { .name = "dcdc2", .driver_data = (void *)TPS65217_DCDC_2 },
+       { .name = "dcdc3", .driver_data = (void *)TPS65217_DCDC_3 },
+       { .name = "ldo1", .driver_data = (void *)TPS65217_LDO_1 },
+       { .name = "ldo2", .driver_data = (void *)TPS65217_LDO_2 },
+       { .name = "ldo3", .driver_data = (void *)TPS65217_LDO_3 },
+       { .name = "ldo4", .driver_data = (void *)TPS65217_LDO_4 },
+};
+
+static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
+{
+       struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct device_node *node = tps->dev->of_node;
+       struct tps65217_board *pdata;
+       struct device_node *regs;
+       int i, count;
+
+       regs = of_find_node_by_name(node, "regulators");
+       if (!regs)
+               return NULL;
+
+       count = of_regulator_match(pdev->dev.parent, regs,
+                               reg_matches, TPS65217_NUM_REGULATOR);
+       of_node_put(regs);
+       if ((count < 0) || (count > TPS65217_NUM_REGULATOR))
+               return NULL;
+
+       pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
+       if (!pdata)
+               return NULL;
+
+       for (i = 0; i < count; i++) {
+               if (!reg_matches[i].init_data || !reg_matches[i].of_node)
+                       continue;
+
+               pdata->tps65217_init_data[i] = reg_matches[i].init_data;
+               pdata->of_node[i] = reg_matches[i].of_node;
+       }
+
+       return pdata;
+}
+#else
+static struct tps65217_board *tps65217_parse_dt(struct platform_device *pdev)
+{
+       return NULL;
+}
+#endif
+
 static int __devinit tps65217_regulator_probe(struct platform_device *pdev)
 {
+       struct tps65217 *tps = dev_get_drvdata(pdev->dev.parent);
+       struct tps65217_board *pdata = dev_get_platdata(tps->dev);
+       struct regulator_init_data *reg_data;
        struct regulator_dev *rdev;
-       struct tps65217 *tps;
-       struct tps_info *info = &tps65217_pmic_regs[pdev->id];
        struct regulator_config config = { };
+       int i, ret;
 
-       /* Already set by core driver */
-       tps = dev_to_tps65217(pdev->dev.parent);
-       tps->info[pdev->id] = info;
+       if (tps->dev->of_node)
+               pdata = tps65217_parse_dt(pdev);
 
-       config.dev = &pdev->dev;
-       config.of_node = pdev->dev.of_node;
-       config.init_data = pdev->dev.platform_data;
-       config.driver_data = tps;
+       if (!pdata) {
+               dev_err(&pdev->dev, "Platform data not found\n");
+               return -EINVAL;
+       }
 
-       rdev = regulator_register(&regulators[pdev->id], &config);
-       if (IS_ERR(rdev))
-               return PTR_ERR(rdev);
+       if (tps65217_chip_id(tps) != TPS65217) {
+               dev_err(&pdev->dev, "Invalid tps chip version\n");
+               return -ENODEV;
+       }
 
-       platform_set_drvdata(pdev, rdev);
+       platform_set_drvdata(pdev, tps);
 
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++) {
+
+               reg_data = pdata->tps65217_init_data[i];
+
+               /*
+                * Regulator API handles empty constraints but not NULL
+                * constraints
+                */
+               if (!reg_data)
+                       continue;
+
+               /* Register the regulators */
+               tps->info[i] = &tps65217_pmic_regs[i];
+
+               config.dev = tps->dev;
+               config.init_data = reg_data;
+               config.driver_data = tps;
+               config.regmap = tps->regmap;
+               if (tps->dev->of_node)
+                       config.of_node = pdata->of_node[i];
+
+               rdev = regulator_register(&regulators[i], &config);
+               if (IS_ERR(rdev)) {
+                       dev_err(tps->dev, "failed to register %s regulator\n",
+                               pdev->name);
+                       ret = PTR_ERR(rdev);
+                       goto err_unregister_regulator;
+               }
+
+               /* Save regulator for cleanup */
+               tps->rdev[i] = rdev;
+       }
        return 0;
+
+err_unregister_regulator:
+       while (--i >= 0)
+               regulator_unregister(tps->rdev[i]);
+
+       return ret;
 }
 
 static int __devexit tps65217_regulator_remove(struct platform_device *pdev)
 {
-       struct regulator_dev *rdev = platform_get_drvdata(pdev);
+       struct tps65217 *tps = platform_get_drvdata(pdev);
+       unsigned int i;
+
+       for (i = 0; i < TPS65217_NUM_REGULATOR; i++)
+               regulator_unregister(tps->rdev[i]);
 
        platform_set_drvdata(pdev, NULL);
-       regulator_unregister(rdev);
 
        return 0;
 }
index 590cfafc7c172ce8a2d3230de12057a85dfaa7d0..1859f71372e24912203dca245f3d60c71c80a35d 100644 (file)
@@ -1008,8 +1008,8 @@ static int rpmsg_probe(struct virtio_device *vdev)
        return 0;
 
 free_coherent:
-       dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE, bufs_va,
-                                       vrp->bufs_dma);
+       dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE,
+                                       bufs_va, vrp->bufs_dma);
 vqs_del:
        vdev->config->del_vqs(vrp->vdev);
 free_vrp:
@@ -1043,7 +1043,7 @@ static void __devexit rpmsg_remove(struct virtio_device *vdev)
 
        vdev->config->del_vqs(vrp->vdev);
 
-       dma_free_coherent(vdev->dev.parent, RPMSG_TOTAL_BUF_SPACE,
+       dma_free_coherent(vdev->dev.parent->parent, RPMSG_TOTAL_BUF_SPACE,
                                        vrp->rbufs, vrp->bufs_dma);
 
        kfree(vrp);
index 831868904e02fd39b7058de5b4e7a65c9d8555b3..1dd61f402b040441c99078214017f802050c8fa5 100644 (file)
@@ -58,6 +58,7 @@ struct sam9_rtc {
        struct rtc_device       *rtcdev;
        u32                     imr;
        void __iomem            *gpbr;
+       int                     irq;
 };
 
 #define rtt_readl(rtc, field) \
@@ -292,7 +293,7 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
 {
        struct resource *r, *r_gpbr;
        struct sam9_rtc *rtc;
-       int             ret;
+       int             ret, irq;
        u32             mr;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -302,10 +303,18 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
                return -ENODEV;
        }
 
+       irq = platform_get_irq(pdev, 0);
+       if (irq < 0) {
+               dev_err(&pdev->dev, "failed to get interrupt resource\n");
+               return irq;
+       }
+
        rtc = kzalloc(sizeof *rtc, GFP_KERNEL);
        if (!rtc)
                return -ENOMEM;
 
+       rtc->irq = irq;
+
        /* platform setup code should have handled this; sigh */
        if (!device_can_wakeup(&pdev->dev))
                device_init_wakeup(&pdev->dev, 1);
@@ -345,11 +354,10 @@ static int __devinit at91_rtc_probe(struct platform_device *pdev)
        }
 
        /* register irq handler after we know what name we'll use */
-       ret = request_irq(AT91_ID_SYS, at91_rtc_interrupt,
-                               IRQF_SHARED,
+       ret = request_irq(rtc->irq, at91_rtc_interrupt, IRQF_SHARED,
                                dev_name(&rtc->rtcdev->dev), rtc);
        if (ret) {
-               dev_dbg(&pdev->dev, "can't share IRQ %d?\n", AT91_ID_SYS);
+               dev_dbg(&pdev->dev, "can't share IRQ %d?\n", rtc->irq);
                rtc_device_unregister(rtc->rtcdev);
                goto fail_register;
        }
@@ -386,7 +394,7 @@ static int __devexit at91_rtc_remove(struct platform_device *pdev)
 
        /* disable all interrupts */
        rtt_writel(rtc, MR, mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN));
-       free_irq(AT91_ID_SYS, rtc);
+       free_irq(rtc->irq, rtc);
 
        rtc_device_unregister(rtc->rtcdev);
 
@@ -423,7 +431,7 @@ static int at91_rtc_suspend(struct platform_device *pdev,
        rtc->imr = mr & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN);
        if (rtc->imr) {
                if (device_may_wakeup(&pdev->dev) && (mr & AT91_RTT_ALMIEN)) {
-                       enable_irq_wake(AT91_ID_SYS);
+                       enable_irq_wake(rtc->irq);
                        /* don't let RTTINC cause wakeups */
                        if (mr & AT91_RTT_RTTINCIEN)
                                rtt_writel(rtc, MR, mr & ~AT91_RTT_RTTINCIEN);
@@ -441,7 +449,7 @@ static int at91_rtc_resume(struct platform_device *pdev)
 
        if (rtc->imr) {
                if (device_may_wakeup(&pdev->dev))
-                       disable_irq_wake(AT91_ID_SYS);
+                       disable_irq_wake(rtc->irq);
                mr = rtt_readl(rtc, MR);
                rtt_writel(rtc, MR, mr | rtc->imr);
        }
index c5d06fe83bba6274f2e6b944a43489395e04e01c..9277d945bf4853d136ec483036be8cd0cf6f06b3 100644 (file)
@@ -495,6 +495,11 @@ static int __devinit twl_rtc_probe(struct platform_device *pdev)
        if (ret < 0)
                goto out1;
 
+       /* ensure interrupts are disabled, bootloaders can be strange */
+       ret = twl_rtc_write_u8(0, REG_RTC_INTERRUPTS_REG);
+       if (ret < 0)
+               dev_warn(&pdev->dev, "unable to disable interrupt\n");
+
        /* init cached IRQ enable bits */
        ret = twl_rtc_read_u8(&rtc_irq_bits, REG_RTC_INTERRUPTS_REG);
        if (ret < 0)
index 15370a2c5ff0b29e5286a9ffb2660beefd045f2e..0595c763dafd687ac3938f803618eed679549d76 100644 (file)
@@ -534,11 +534,11 @@ static void dasd_change_state(struct dasd_device *device)
        if (rc)
                device->target = device->state;
 
-       if (device->state == device->target)
-               wake_up(&dasd_init_waitq);
-
        /* let user-space know that the device status changed */
        kobject_uevent(&device->cdev->dev.kobj, KOBJ_CHANGE);
+
+       if (device->state == device->target)
+               wake_up(&dasd_init_waitq);
 }
 
 /*
@@ -2157,6 +2157,7 @@ static int _dasd_sleep_on(struct dasd_ccw_req *maincqr, int interruptible)
                    test_bit(DASD_CQR_FLAGS_FAILFAST, &cqr->flags) &&
                    (!dasd_eer_enabled(device))) {
                        cqr->status = DASD_CQR_FAILED;
+                       cqr->intrc = -EAGAIN;
                        continue;
                }
                /* Don't try to start requests if device is stopped */
@@ -3270,6 +3271,16 @@ void dasd_generic_path_event(struct ccw_device *cdev, int *path_event)
                        dasd_schedule_device_bh(device);
                }
                if (path_event[chp] & PE_PATHGROUP_ESTABLISHED) {
+                       if (!(device->path_data.opm & eventlpm) &&
+                           !(device->path_data.tbvpm & eventlpm)) {
+                               /*
+                                * we can not establish a pathgroup on an
+                                * unavailable path, so trigger a path
+                                * verification first
+                                */
+                               device->path_data.tbvpm |= eventlpm;
+                               dasd_schedule_device_bh(device);
+                       }
                        DBF_DEV_EVENT(DBF_WARNING, device, "%s",
                                      "Pathgroup re-established\n");
                        if (device->discipline->kick_validate)
index 157defe5e0693c06c6432ddfbd65d0f6632a6f90..6b556995bb33e9baf98663175973bbb69805522d 100644 (file)
@@ -384,6 +384,29 @@ static void _remove_device_from_lcu(struct alias_lcu *lcu,
                group->next = NULL;
 };
 
+static int
+suborder_not_supported(struct dasd_ccw_req *cqr)
+{
+       char *sense;
+       char reason;
+       char msg_format;
+       char msg_no;
+
+       sense = dasd_get_sense(&cqr->irb);
+       if (!sense)
+               return 0;
+
+       reason = sense[0];
+       msg_format = (sense[7] & 0xF0);
+       msg_no = (sense[7] & 0x0F);
+
+       /* command reject, Format 0 MSG 4 - invalid parameter */
+       if ((reason == 0x80) && (msg_format == 0x00) && (msg_no == 0x04))
+               return 1;
+
+       return 0;
+}
+
 static int read_unit_address_configuration(struct dasd_device *device,
                                           struct alias_lcu *lcu)
 {
@@ -435,6 +458,8 @@ static int read_unit_address_configuration(struct dasd_device *device,
 
        do {
                rc = dasd_sleep_on(cqr);
+               if (rc && suborder_not_supported(cqr))
+                       return -EOPNOTSUPP;
        } while (rc && (cqr->retries > 0));
        if (rc) {
                spin_lock_irqsave(&lcu->lock, flags);
@@ -521,7 +546,7 @@ static void lcu_update_work(struct work_struct *work)
         * processing the data
         */
        spin_lock_irqsave(&lcu->lock, flags);
-       if (rc || (lcu->flags & NEED_UAC_UPDATE)) {
+       if ((rc && (rc != -EOPNOTSUPP)) || (lcu->flags & NEED_UAC_UPDATE)) {
                DBF_DEV_EVENT(DBF_WARNING, device, "could not update"
                            " alias data in lcu (rc = %d), retry later", rc);
                schedule_delayed_work(&lcu->ruac_data.dwork, 30*HZ);
index 40a826a7295f7282ec8f05e2dcfd66d8f9601927..c48c72abbefc640671af73090536bd206b1c95dc 100644 (file)
@@ -1507,7 +1507,8 @@ static struct dasd_ccw_req *dasd_eckd_build_psf_ssc(struct dasd_device *device,
  * call might change behaviour of DASD devices.
  */
 static int
-dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
+dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav,
+                 unsigned long flags)
 {
        struct dasd_ccw_req *cqr;
        int rc;
@@ -1516,10 +1517,19 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
        if (IS_ERR(cqr))
                return PTR_ERR(cqr);
 
+       /*
+        * set flags e.g. turn on failfast, to prevent blocking
+        * the calling function should handle failed requests
+        */
+       cqr->flags |= flags;
+
        rc = dasd_sleep_on(cqr);
        if (!rc)
                /* trigger CIO to reprobe devices */
                css_schedule_reprobe();
+       else if (cqr->intrc == -EAGAIN)
+               rc = -EAGAIN;
+
        dasd_sfree_request(cqr, cqr->memdev);
        return rc;
 }
@@ -1527,7 +1537,8 @@ dasd_eckd_psf_ssc(struct dasd_device *device, int enable_pav)
 /*
  * Valide storage server of current device.
  */
-static void dasd_eckd_validate_server(struct dasd_device *device)
+static int dasd_eckd_validate_server(struct dasd_device *device,
+                                    unsigned long flags)
 {
        int rc;
        struct dasd_eckd_private *private;
@@ -1536,17 +1547,18 @@ static void dasd_eckd_validate_server(struct dasd_device *device)
        private = (struct dasd_eckd_private *) device->private;
        if (private->uid.type == UA_BASE_PAV_ALIAS ||
            private->uid.type == UA_HYPER_PAV_ALIAS)
-               return;
+               return 0;
        if (dasd_nopav || MACHINE_IS_VM)
                enable_pav = 0;
        else
                enable_pav = 1;
-       rc = dasd_eckd_psf_ssc(device, enable_pav);
+       rc = dasd_eckd_psf_ssc(device, enable_pav, flags);
 
        /* may be requested feature is not available on server,
         * therefore just report error and go ahead */
        DBF_EVENT_DEVID(DBF_WARNING, device->cdev, "PSF-SSC for SSID %04x "
                        "returned rc=%d", private->uid.ssid, rc);
+       return rc;
 }
 
 /*
@@ -1556,7 +1568,13 @@ static void dasd_eckd_do_validate_server(struct work_struct *work)
 {
        struct dasd_device *device = container_of(work, struct dasd_device,
                                                  kick_validate);
-       dasd_eckd_validate_server(device);
+       if (dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST)
+           == -EAGAIN) {
+               /* schedule worker again if failed */
+               schedule_work(&device->kick_validate);
+               return;
+       }
+
        dasd_put_device(device);
 }
 
@@ -1685,7 +1703,7 @@ dasd_eckd_check_characteristics(struct dasd_device *device)
        if (rc)
                goto out_err2;
 
-       dasd_eckd_validate_server(device);
+       dasd_eckd_validate_server(device, 0);
 
        /* device may report different configuration data after LCU setup */
        rc = dasd_eckd_read_conf(device);
@@ -3804,7 +3822,7 @@ dasd_eckd_ioctl(struct dasd_block *block, unsigned int cmd, void __user *argp)
        case BIODASDSYMMIO:
                return dasd_symm_io(device, argp);
        default:
-               return -ENOIOCTLCMD;
+               return -ENOTTY;
        }
 }
 
@@ -4153,7 +4171,7 @@ static int dasd_eckd_restore_device(struct dasd_device *device)
        rc = dasd_alias_make_device_known_to_lcu(device);
        if (rc)
                return rc;
-       dasd_eckd_validate_server(device);
+       dasd_eckd_validate_server(device, DASD_CQR_FLAGS_FAILFAST);
 
        /* RE-Read Configuration Data */
        rc = dasd_eckd_read_conf(device);
index cceae70279f6407d96f7249f02939de53405ea03..654c6921a6d462f5d9fc0f0b82e9813480b96670 100644 (file)
@@ -498,12 +498,9 @@ int dasd_ioctl(struct block_device *bdev, fmode_t mode,
                break;
        default:
                /* if the discipline has an ioctl method try it. */
-               if (base->discipline->ioctl) {
+               rc = -ENOTTY;
+               if (base->discipline->ioctl)
                        rc = base->discipline->ioctl(block, cmd, argp);
-                       if (rc == -ENOIOCTLCMD)
-                               rc = -EINVAL;
-               } else
-                       rc = -EINVAL;
        }
        dasd_put_device(base);
        return rc;
index ed25c8740a9ce4b0bb8e8334a32b72abc08655ae..fc916f5d731412c7146465d3ff29277979b69189 100644 (file)
@@ -1426,6 +1426,8 @@ static enum io_sch_action sch_get_action(struct subchannel *sch)
                return IO_SCH_REPROBE;
        if (cdev->online)
                return IO_SCH_VERIFY;
+       if (cdev->private->state == DEV_STATE_NOT_OPER)
+               return IO_SCH_UNREG_ATTACH;
        return IO_SCH_NOP;
 }
 
@@ -1519,11 +1521,14 @@ static int io_subchannel_sch_event(struct subchannel *sch, int process)
                        goto out;
                break;
        case IO_SCH_UNREG_ATTACH:
+               spin_lock_irqsave(sch->lock, flags);
                if (cdev->private->flags.resuming) {
                        /* Device will be handled later. */
                        rc = 0;
-                       goto out;
+                       goto out_unlock;
                }
+               sch_set_cdev(sch, NULL);
+               spin_unlock_irqrestore(sch->lock, flags);
                /* Unregister ccw device. */
                ccw_device_unregister(cdev);
                break;
index 33d6630529ded9b8db625a1ca4545c6fdb2472b3..91eec60252ee1c973198ae5c230762af37607073 100644 (file)
@@ -1264,6 +1264,9 @@ int bnx2i_send_fw_iscsi_init_msg(struct bnx2i_hba *hba)
        int rc = 0;
        u64 mask64;
 
+       memset(&iscsi_init, 0x00, sizeof(struct iscsi_kwqe_init1));
+       memset(&iscsi_init2, 0x00, sizeof(struct iscsi_kwqe_init2));
+
        bnx2i_adjust_qp_size(hba);
 
        iscsi_init.flags =
index 796482badf13acfe91f4391822d90cd6339d9ffc..2b4261cb77424b52046d6e4c255f32f3359bbf2a 100644 (file)
@@ -1315,8 +1315,9 @@ static void complete_scsi_command(struct CommandList *cp)
        }
                break;
        case CMD_PROTOCOL_ERR:
+               cmd->result = DID_ERROR << 16;
                dev_warn(&h->pdev->dev, "cp %p has "
-                       "protocol error \n", cp);
+                       "protocol error\n", cp);
                break;
        case CMD_HARDWARE_ERR:
                cmd->result = DID_ERROR << 16;
index dc27598785e5d781ff9790697f8b3a5960921d85..ed38454228c626bdabbea4d4265b22dfbc637864 100644 (file)
@@ -4066,7 +4066,6 @@ megasas_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        spin_lock_init(&instance->cmd_pool_lock);
        spin_lock_init(&instance->hba_lock);
        spin_lock_init(&instance->completion_lock);
-       spin_lock_init(&poll_aen_lock);
 
        mutex_init(&instance->aen_mutex);
        mutex_init(&instance->reset_mutex);
@@ -5392,6 +5391,8 @@ static int __init megasas_init(void)
        printk(KERN_INFO "megasas: %s %s\n", MEGASAS_VERSION,
               MEGASAS_EXT_VERSION);
 
+       spin_lock_init(&poll_aen_lock);
+
        support_poll_for_event = 2;
        support_device_change = 1;
 
index 9d46fcbe7755fd2aa258e3de91c5a8cd76e3079c..9d5a56c4b3321deea9b9001468755d222fa13b51 100644 (file)
@@ -1209,6 +1209,13 @@ _base_check_enable_msix(struct MPT2SAS_ADAPTER *ioc)
        u16 message_control;
 
 
+       /* Check whether controller SAS2008 B0 controller,
+          if it is SAS2008 B0 controller use IO-APIC instead of MSIX */
+       if (ioc->pdev->device == MPI2_MFGPAGE_DEVID_SAS2008 &&
+           ioc->pdev->revision == 0x01) {
+               return -EINVAL;
+       }
+
        base = pci_find_capability(ioc->pdev, PCI_CAP_ID_MSIX);
        if (!base) {
                dfailprintk(ioc, printk(MPT2SAS_INFO_FMT "msix not "
@@ -2424,10 +2431,13 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        }
 
        /* command line tunables  for max controller queue depth */
-       if (max_queue_depth != -1)
-               max_request_credit = (max_queue_depth < facts->RequestCredit)
-                   ? max_queue_depth : facts->RequestCredit;
-       else
+       if (max_queue_depth != -1 && max_queue_depth != 0) {
+               max_request_credit = min_t(u16, max_queue_depth +
+                       ioc->hi_priority_depth + ioc->internal_depth,
+                       facts->RequestCredit);
+               if (max_request_credit > MAX_HBA_QUEUE_DEPTH)
+                       max_request_credit =  MAX_HBA_QUEUE_DEPTH;
+       } else
                max_request_credit = min_t(u16, facts->RequestCredit,
                    MAX_HBA_QUEUE_DEPTH);
 
@@ -2502,7 +2512,7 @@ _base_allocate_memory_pools(struct MPT2SAS_ADAPTER *ioc,  int sleep_flag)
        /* set the scsi host can_queue depth
         * with some internal commands that could be outstanding
         */
-       ioc->shost->can_queue = ioc->scsiio_depth - (2);
+       ioc->shost->can_queue = ioc->scsiio_depth;
        dinitprintk(ioc, printk(MPT2SAS_INFO_FMT "scsi host: "
            "can_queue depth (%d)\n", ioc->name, ioc->shost->can_queue));
 
index 4a6381c87253ec4be307eb47dc8d1ff6ebad4dc3..de2337f255a74ff02888f67e1d202766f257930a 100644 (file)
@@ -42,6 +42,8 @@
 
 #include <trace/events/scsi.h>
 
+static void scsi_eh_done(struct scsi_cmnd *scmd);
+
 #define SENSE_TIMEOUT          (10*HZ)
 
 /*
@@ -241,6 +243,14 @@ static int scsi_check_sense(struct scsi_cmnd *scmd)
        if (! scsi_command_normalize_sense(scmd, &sshdr))
                return FAILED;  /* no valid sense data */
 
+       if (scmd->cmnd[0] == TEST_UNIT_READY && scmd->scsi_done != scsi_eh_done)
+               /*
+                * nasty: for mid-layer issued TURs, we need to return the
+                * actual sense data without any recovery attempt.  For eh
+                * issued ones, we need to try to recover and interpret
+                */
+               return SUCCESS;
+
        if (scsi_sense_is_deferred(&sshdr))
                return NEEDS_RETRY;
 
index ffd77739ae3e2bc4bf793fe7b4bb0ed37c3ca8f4..faa790fba1347fc61b0869015e2a28bad4f113f2 100644 (file)
@@ -776,7 +776,6 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
        }
 
        if (req->cmd_type == REQ_TYPE_BLOCK_PC) { /* SG_IO ioctl from block level */
-               req->errors = result;
                if (result) {
                        if (sense_valid && req->sense) {
                                /*
@@ -792,6 +791,10 @@ void scsi_io_completion(struct scsi_cmnd *cmd, unsigned int good_bytes)
                        if (!sense_deferred)
                                error = __scsi_error_from_host_byte(cmd, result);
                }
+               /*
+                * __scsi_error_from_host_byte may have reset the host_byte
+                */
+               req->errors = cmd->result;
 
                req->resid_len = scsi_get_resid(cmd);
 
index 56a93794c470ae99d603426f15eaccb1dd3ae727..d947ffc20ceba301eaaf45973fee97dfba7fb7f7 100644 (file)
@@ -764,6 +764,16 @@ static int scsi_add_lun(struct scsi_device *sdev, unsigned char *inq_result,
        sdev->model = (char *) (sdev->inquiry + 16);
        sdev->rev = (char *) (sdev->inquiry + 32);
 
+       if (strncmp(sdev->vendor, "ATA     ", 8) == 0) {
+               /*
+                * sata emulation layer device.  This is a hack to work around
+                * the SATL power management specifications which state that
+                * when the SATL detects the device has gone into standby
+                * mode, it shall respond with NOT READY.
+                */
+               sdev->allow_restart = 1;
+       }
+
        if (*bflags & BLIST_ISROM) {
                sdev->type = TYPE_ROM;
                sdev->removable = 1;
index c7030fbee79c254ace6a41eed0a88e6b968e6bfb..3e79a2f0004279d0b2b1175281d003a664d5aeee 100644 (file)
@@ -331,7 +331,7 @@ static void virtscsi_map_sgl(struct scatterlist *sg, unsigned int *p_idx,
        int i;
 
        for_each_sg(table->sgl, sg_elem, table->nents, i)
-               sg_set_buf(&sg[idx++], sg_virt(sg_elem), sg_elem->length);
+               sg[idx++] = *sg_elem;
 
        *p_idx = idx;
 }
index 32c26d795ed06d3a58c43bf3d295d8f75dcf676f..8f32a1323a79dd40e6e91433fa38e15709a3ca02 100644 (file)
@@ -355,7 +355,7 @@ int __init register_intc_controller(struct intc_desc *desc)
                        if (unlikely(res)) {
                                if (res == -EEXIST) {
                                        res = irq_domain_associate(d->domain,
-                                                                  irq, irq);
+                                                                  irq2, irq2);
                                        if (unlikely(res)) {
                                                pr_err("domain association "
                                                       "failure\n");
index 2804eaae804e7279aedb64f52066e380212a2176..0646bf6e7889a10ed6e4773af378c264377d5f8b 100644 (file)
@@ -208,10 +208,13 @@ static int sh_pfc_gpio_request_enable(struct pinctrl_dev *pctldev,
 
                break;
        case PINMUX_TYPE_GPIO:
+       case PINMUX_TYPE_INPUT:
+       case PINMUX_TYPE_OUTPUT:
                break;
        default:
                pr_err("Unsupported mux type (%d), bailing...\n", pinmux_type);
-               return -ENOTSUPP;
+               ret = -ENOTSUPP;
+               goto err;
        }
 
        ret = 0;
index ea0aaa3f13d07549263a8b8e4da08acd92c3bc7e..a9f4049c6769316c368a716b0b6707d7082abd25 100644 (file)
@@ -47,6 +47,8 @@ struct bcm63xx_spi {
        /* Platform data */
        u32                     speed_hz;
        unsigned                fifo_size;
+       unsigned int            msg_type_shift;
+       unsigned int            msg_ctl_width;
 
        /* Data buffers */
        const unsigned char     *tx_ptr;
@@ -221,13 +223,20 @@ static unsigned int bcm63xx_txrx_bufs(struct spi_device *spi,
        msg_ctl = (t->len << SPI_BYTE_CNT_SHIFT);
 
        if (t->rx_buf && t->tx_buf)
-               msg_ctl |= (SPI_FD_RW << SPI_MSG_TYPE_SHIFT);
+               msg_ctl |= (SPI_FD_RW << bs->msg_type_shift);
        else if (t->rx_buf)
-               msg_ctl |= (SPI_HD_R << SPI_MSG_TYPE_SHIFT);
+               msg_ctl |= (SPI_HD_R << bs->msg_type_shift);
        else if (t->tx_buf)
-               msg_ctl |= (SPI_HD_W << SPI_MSG_TYPE_SHIFT);
-
-       bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
+               msg_ctl |= (SPI_HD_W << bs->msg_type_shift);
+
+       switch (bs->msg_ctl_width) {
+       case 8:
+               bcm_spi_writeb(bs, msg_ctl, SPI_MSG_CTL);
+               break;
+       case 16:
+               bcm_spi_writew(bs, msg_ctl, SPI_MSG_CTL);
+               break;
+       }
 
        /* Issue the transfer */
        cmd = SPI_CMD_START_IMMEDIATE;
@@ -406,9 +415,21 @@ static int __devinit bcm63xx_spi_probe(struct platform_device *pdev)
        master->transfer_one_message = bcm63xx_spi_transfer_one;
        master->mode_bits = MODEBITS;
        bs->speed_hz = pdata->speed_hz;
+       bs->msg_type_shift = pdata->msg_type_shift;
+       bs->msg_ctl_width = pdata->msg_ctl_width;
        bs->tx_io = (u8 *)(bs->regs + bcm63xx_spireg(SPI_MSG_DATA));
        bs->rx_io = (const u8 *)(bs->regs + bcm63xx_spireg(SPI_RX_DATA));
 
+       switch (bs->msg_ctl_width) {
+       case 8:
+       case 16:
+               break;
+       default:
+               dev_err(dev, "unsupported MSG_CTL width: %d\n",
+                        bs->msg_ctl_width);
+               goto out_clk_disable;
+       }
+
        /* Initialize hardware */
        clk_enable(bs->clk);
        bcm_spi_writeb(bs, SPI_INTR_CLEAR_ALL, SPI_INT_STATUS);
index d0cafd6371996c75e3ee094b2be3168ad14d38b7..f2ffd963f1c348e3986f761b1d2d2b7b75b361e2 100644 (file)
@@ -51,10 +51,12 @@ enum android_alarm_return_flags {
 #define ANDROID_ALARM_WAIT                  _IO('a', 1)
 
 #define ALARM_IOW(c, type, size)            _IOW('a', (c) | ((type) << 4), size)
+#define ALARM_IOR(c, type, size)            _IOR('a', (c) | ((type) << 4), size)
+
 /* Set alarm */
 #define ANDROID_ALARM_SET(type)             ALARM_IOW(2, type, struct timespec)
 #define ANDROID_ALARM_SET_AND_WAIT(type)    ALARM_IOW(3, type, struct timespec)
-#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOW(4, type, struct timespec)
+#define ANDROID_ALARM_GET_TIME(type)        ALARM_IOR(4, type, struct timespec)
 #define ANDROID_ALARM_SET_RTC               _IOW('a', 5, struct timespec)
 #define ANDROID_ALARM_BASE_CMD(cmd)         (cmd & ~(_IOC(0, 0, 0xf0, 0)))
 #define ANDROID_ALARM_IOCTL_TO_TYPE(cmd)    (_IOC_NR(cmd) >> 4)
index 6c81e377262c204ca8a9354743f344ff824267d5..cc8931fde839c491455ed10beaa56529480fbe2d 100644 (file)
@@ -1412,6 +1412,13 @@ static int __devinit dio200_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in dio200_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via dio200_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return dio200_pci_common_attach(dev, pci_dev);
 }
 
index aabba9886b7d9276eb1c4233c89ce894685fbd58..f50287903038bb22772c1c99522c69078fc638c0 100644 (file)
@@ -565,6 +565,13 @@ static int __devinit pc236_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pc236_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pc236_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pc236_pci_common_attach(dev, pci_dev);
 }
 
index 40ec1ffebba651fda62f23af21ff7b0e3ef097a4..8191c4e28e0a6849fb53e7def7b4fc1639c79c09 100644 (file)
@@ -298,6 +298,13 @@ static int __devinit pc263_attach_pci(struct comedi_device *dev,
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pc263_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pc263_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pc263_pci_common_attach(dev, pci_dev);
 }
 
index 4e17f13e57f6530b2bc3cfd1afc4485d0940d880..8bf109e7bb05cef4c9c50669314289cde734c47c 100644 (file)
@@ -1503,6 +1503,13 @@ pci224_attach_pci(struct comedi_device *dev, struct pci_dev *pci_dev)
                        DRIVER_NAME ": BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pci224_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pci224_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pci224_attach_common(dev, pci_dev, NULL);
 }
 
index 1b67d0c61fa72ff782e02a09dc63b2c14ec5982c..66e74bd12267a565263556f8e6f3389b2c6c41b9 100644 (file)
@@ -2925,6 +2925,13 @@ static int __devinit pci230_attach_pci(struct comedi_device *dev,
                        "amplc_pci230: BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in pci230_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via pci230_attach()
+        * has been removed.
+        */
+       pci_dev_get(pci_dev);
        return pci230_attach_common(dev, pci_dev);
 }
 
index 874e02e47668e60a024b350a72822894be801f1a..67a914a10b55fb2333c9ec747ccd907084fc7b6d 100644 (file)
@@ -378,7 +378,7 @@ das08jr_ao_winsn(struct comedi_device *dev, struct comedi_subdevice *s,
        int chan;
 
        lsb = data[0] & 0xff;
-       msb = (data[0] >> 8) & 0xf;
+       msb = (data[0] >> 8) & 0xff;
 
        chan = CR_CHAN(insn->chanspec);
 
@@ -623,7 +623,7 @@ static const struct das08_board_struct das08_boards[] = {
                .ai = das08_ai_rinsn,
                .ai_nbits = 16,
                .ai_pg = das08_pg_none,
-               .ai_encoding = das08_encode12,
+               .ai_encoding = das08_encode16,
                .ao = das08jr_ao_winsn,
                .ao_nbits = 16,
                .di = das08jr_di_rbits,
@@ -922,6 +922,13 @@ das08_attach_pci(struct comedi_device *dev, struct pci_dev *pdev)
                dev_err(dev->class_dev, "BUG! cannot determine board type!\n");
                return -EINVAL;
        }
+       /*
+        * Need to 'get' the PCI device to match the 'put' in das08_detach().
+        * TODO: Remove the pci_dev_get() and matching pci_dev_put() once
+        * support for manual attachment of PCI devices via das08_attach()
+        * has been removed.
+        */
+       pci_dev_get(pdev);
        return das08_pci_attach_common(dev, pdev);
 }
 
index 18d108fd967a908817efa70d1056fcba35d00458..f3da59063ed2e5a8c934ed201f1add435810028a 100644 (file)
@@ -121,8 +121,10 @@ static int lis3l02dq_get_buffer_element(struct iio_dev *indio_dev,
        if (rx_array == NULL)
                return -ENOMEM;
        ret = lis3l02dq_read_all(indio_dev, rx_array);
-       if (ret < 0)
+       if (ret < 0) {
+               kfree(rx_array);
                return ret;
+       }
        for (i = 0; i < scan_count; i++)
                data[i] = combine_8_to_16(rx_array[i*4+1],
                                        rx_array[i*4+3]);
index 095837285f4fb25732b8986f3d6d25458a9a11a2..19a064d649e3f72a783dd2b2ffc2e6a385175216 100644 (file)
@@ -647,6 +647,8 @@ static ssize_t ad7192_write_frequency(struct device *dev,
        ret = strict_strtoul(buf, 10, &lval);
        if (ret)
                return ret;
+       if (lval == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
        if (iio_buffer_enabled(indio_dev)) {
index 93aa431287ac6efb17d9b5172c337f67be30365a..eb8e9d69efd3f39ab42a788f70c8eb1d4b105bf2 100644 (file)
@@ -195,6 +195,8 @@ static ssize_t adis16260_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
        if (spi_get_device_id(st->us)) {
index 1f4c17779b5a64e18f48865aa6ecb0e6d49387f4..a618327e06edf2c3374b38b425771b4a823517f2 100644 (file)
@@ -234,6 +234,8 @@ static ssize_t adis16400_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index f04ece7fbc2fbe3d33b61dd3387e1cb0b53b23c5..3ccff189f258232cd4704acc2d8674029cf190b1 100644 (file)
@@ -425,6 +425,8 @@ static ssize_t ade7753_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index 6cee28a5e87731bee476ab4efc7c0501c89cff45..abb1e9c8d0947adcd1bc6d5567b9620496207c5e 100644 (file)
@@ -445,6 +445,8 @@ static ssize_t ade7754_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index b3f7e0fa96124b6ce8d719d63fce6e45df210d0f..eb0a2a98f3886afe1948b284c2ede98094a95754 100644 (file)
@@ -385,6 +385,8 @@ static ssize_t ade7759_write_frequency(struct device *dev,
        ret = strict_strtol(buf, 10, &val);
        if (ret)
                return ret;
+       if (val == 0)
+               return -EINVAL;
 
        mutex_lock(&indio_dev->mlock);
 
index 4f4b7d6281a7c0624b63cbf3ba7d41ca4d4f0070..427218b8b10f435e5f9dcd7dbc3751a572b0566f 100644 (file)
@@ -25,8 +25,6 @@ source "drivers/staging/media/cxd2099/Kconfig"
 
 source "drivers/staging/media/dt3155v4l/Kconfig"
 
-source "drivers/staging/media/easycap/Kconfig"
-
 source "drivers/staging/media/go7007/Kconfig"
 
 source "drivers/staging/media/solo6x10/Kconfig"
index c69124cdb0d3af91d022af72bda59627ef9e2062..aec6eb96394033c156a9731a5503f813c9193393 100644 (file)
@@ -1,6 +1,5 @@
 obj-$(CONFIG_DVB_AS102)                += as102/
 obj-$(CONFIG_DVB_CXD2099)      += cxd2099/
-obj-$(CONFIG_EASYCAP)          += easycap/
 obj-$(CONFIG_LIRC_STAGING)     += lirc/
 obj-$(CONFIG_SOLO6X10)         += solo6x10/
 obj-$(CONFIG_VIDEO_DT3155)     += dt3155v4l/
index 1bca43e847c7c0c301e6d711ea128e96e7db58c5..d8dfb757f1e2f829ede7f0cd5720542f584aff25 100644 (file)
@@ -3,4 +3,4 @@ dvb-as102-objs := as102_drv.o as102_fw.o as10x_cmd.o as10x_cmd_stream.o \
 
 obj-$(CONFIG_DVB_AS102) += dvb-as102.o
 
-EXTRA_CFLAGS += -Idrivers/media/dvb/dvb-core
+EXTRA_CFLAGS += -Idrivers/media/dvb-core
index 64cfc77be357a223abe90936528657c7962be71b..b2905e65057c78179b3e6f68367614c8e81bb4e6 100644 (file)
@@ -1,5 +1,5 @@
 obj-$(CONFIG_DVB_CXD2099) += cxd2099.o
 
-ccflags-y += -Idrivers/media/dvb/dvb-core/
-ccflags-y += -Idrivers/media/dvb/frontends/
-ccflags-y += -Idrivers/media/common/tuners/
+ccflags-y += -Idrivers/media/dvb-core/
+ccflags-y += -Idrivers/media/dvb-frontends/
+ccflags-y += -Idrivers/media/tuners/
index 1c04185bcfd72d95bfe08a2b426fb9e1c1aaef6e..0ff19724992fbe5de688620d22a4396ea0f381ef 100644 (file)
@@ -683,27 +683,26 @@ struct dvb_ca_en50221 *cxd2099_attach(struct cxd2099_cfg *cfg,
                                      void *priv,
                                      struct i2c_adapter *i2c)
 {
-       struct cxd *ci = 0;
+       struct cxd *ci;
        u8 val;
 
        if (i2c_read_reg(i2c, cfg->adr, 0, &val) < 0) {
                printk(KERN_INFO "No CXD2099 detected at %02x\n", cfg->adr);
-               return 0;
+               return NULL;
        }
 
-       ci = kmalloc(sizeof(struct cxd), GFP_KERNEL);
+       ci = kzalloc(sizeof(struct cxd), GFP_KERNEL);
        if (!ci)
-               return 0;
-       memset(ci, 0, sizeof(*ci));
+               return NULL;
 
        mutex_init(&ci->lock);
-       memcpy(&ci->cfg, cfg, sizeof(struct cxd2099_cfg));
+       ci->cfg = *cfg;
        ci->i2c = i2c;
        ci->lastaddress = 0xff;
        ci->clk_reg_b = 0x4a;
        ci->clk_reg_f = 0x1b;
 
-       memcpy(&ci->en, &en_templ, sizeof(en_templ));
+       ci->en = en_templ;
        ci->en.data = ci;
        init(ci);
        printk(KERN_INFO "Attached CXD2099AR at %02x\n", ci->cfg.adr);
index ebe5a27c06f5b97219f3f306f9f6d16744b402e4..2e7b711c850135053c14a1ff3291ba9d8bac8649 100644 (file)
@@ -381,6 +381,8 @@ dt3155_open(struct file *filp)
        int ret = 0;
        struct dt3155_priv *pd = video_drvdata(filp);
 
+       if (mutex_lock_interruptible(&pd->mux))
+               return -ERESTARTSYS;
        if (!pd->users) {
                pd->q = kzalloc(sizeof(*pd->q), GFP_KERNEL);
                if (!pd->q) {
@@ -411,6 +413,7 @@ err_request_irq:
        kfree(pd->q);
        pd->q = NULL;
 err_alloc_queue:
+       mutex_unlock(&pd->mux);
        return ret;
 }
 
@@ -419,6 +422,7 @@ dt3155_release(struct file *filp)
 {
        struct dt3155_priv *pd = video_drvdata(filp);
 
+       mutex_lock(&pd->mux);
        pd->users--;
        BUG_ON(pd->users < 0);
        if (!pd->users) {
@@ -429,6 +433,7 @@ dt3155_release(struct file *filp)
                kfree(pd->q);
                pd->q = NULL;
        }
+       mutex_unlock(&pd->mux);
        return 0;
 }
 
@@ -436,24 +441,38 @@ static ssize_t
 dt3155_read(struct file *filp, char __user *user, size_t size, loff_t *loff)
 {
        struct dt3155_priv *pd = video_drvdata(filp);
+       ssize_t res;
 
-       return vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
+       if (mutex_lock_interruptible(&pd->mux))
+               return -ERESTARTSYS;
+       res = vb2_read(pd->q, user, size, loff, filp->f_flags & O_NONBLOCK);
+       mutex_unlock(&pd->mux);
+       return res;
 }
 
 static unsigned int
 dt3155_poll(struct file *filp, struct poll_table_struct *polltbl)
 {
        struct dt3155_priv *pd = video_drvdata(filp);
+       unsigned int res;
 
-       return vb2_poll(pd->q, filp, polltbl);
+       mutex_lock(&pd->mux);
+       res = vb2_poll(pd->q, filp, polltbl);
+       mutex_unlock(&pd->mux);
+       return res;
 }
 
 static int
 dt3155_mmap(struct file *filp, struct vm_area_struct *vma)
 {
        struct dt3155_priv *pd = video_drvdata(filp);
+       int res;
 
-       return vb2_mmap(pd->q, vma);
+       if (mutex_lock_interruptible(&pd->mux))
+               return -ERESTARTSYS;
+       res = vb2_mmap(pd->q, vma);
+       mutex_unlock(&pd->mux);
+       return res;
 }
 
 static const struct v4l2_file_operations dt3155_fops = {
@@ -898,10 +917,6 @@ dt3155_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        INIT_LIST_HEAD(&pd->dmaq);
        mutex_init(&pd->mux);
        pd->vdev->lock = &pd->mux; /* for locking v4l2_file_operations */
-       /* Locking in file operations other than ioctl should be done
-          by the driver, not the V4L2 core.
-          This driver needs auditing so that this flag can be removed. */
-       set_bit(V4L2_FL_LOCK_ALL_FOPS, &pd->vdev->flags);
        spin_lock_init(&pd->lock);
        pd->csr2 = csr2_init;
        pd->config = config_init;
diff --git a/drivers/staging/media/easycap/Kconfig b/drivers/staging/media/easycap/Kconfig
deleted file mode 100644 (file)
index a425a6f..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-config EASYCAP
-       tristate "EasyCAP USB ID 05e1:0408 support"
-       depends on USB && VIDEO_DEV && SND
-       select SND_PCM
-
-       ---help---
-         This is an integrated audio/video driver for EasyCAP cards with
-         USB ID 05e1:0408.  It supports two hardware variants:
-
-         *  EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
-            having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
-
-         *  EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
-            1, 2, 3, 4 and an unlabelled input cable for a microphone.
-
-         To compile this driver as a module, choose M here: the
-         module will be called easycap
-
-config EASYCAP_DEBUG
-       bool "Enable EasyCAP driver debugging"
-       depends on EASYCAP
-
-       ---help---
-         This option enables debug printouts
-
-         To enable debug, pass the debug level to the debug module
-          parameter:
-
-          modprobe easycap debug=[0..9]
-
diff --git a/drivers/staging/media/easycap/Makefile b/drivers/staging/media/easycap/Makefile
deleted file mode 100644 (file)
index a34e75f..0000000
+++ /dev/null
@@ -1,10 +0,0 @@
-easycap-objs := easycap_main.o
-easycap-objs += easycap_low.o
-easycap-objs += easycap_ioctl.o
-easycap-objs += easycap_settings.o
-easycap-objs += easycap_testcard.o
-easycap-objs += easycap_sound.o
-obj-$(CONFIG_EASYCAP) += easycap.o
-
-ccflags-y := -Wall
-
diff --git a/drivers/staging/media/easycap/README b/drivers/staging/media/easycap/README
deleted file mode 100644 (file)
index 796b032..0000000
+++ /dev/null
@@ -1,141 +0,0 @@
-
-        ***********************************************************
-        *   EasyCAP USB 2.0 Video Adapter with Audio, Model DC60  *
-        *                            and                          *
-        *             EasyCAP002 4-Channel USB 2.0 DVR            *
-        ***********************************************************
-                     Mike Thomas  <rmthomas@sciolus.org>
-
-
-
-SUPPORTED HARDWARE
-------------------
-
-This driver is intended for use with hardware having USB ID 05e1:0408.
-Two kinds of EasyCAP have this USB ID, namely:
-
-    *  EasyCAP USB 2.0 Video Adapter with Audio, Model DC60,
-       having input cables labelled CVBS, S-VIDEO, AUDIO(L), AUDIO(R)
-
-    *  EasyCAP002 4-Channel USB 2.0 DVR, having input cables labelled
-       1, 2, 3, 4 and an unlabelled input cable for a microphone.
-
-
-BUILD OPTIONS AND DEPENDENCIES
-------------------------------
-
-Unless EASYCAP_DEBUG is defined during compilation it will not be possible
-to select a debug level at the time of module installation.
-
-
-KNOWN RUNTIME ISSUES
---------------------
-
-(1) Intentionally, this driver will not stream material which is unambiguously
-identified by the hardware as copy-protected.  Normal video output will be
-present for about a minute but will then freeze when this situation arises.
-
-(2) The controls for luminance, contrast, saturation, hue and volume may not
-always work properly.
-
-(3) Reduced-resolution S-Video seems to suffer from moire artefacts.
-
-
-INPUT NUMBERING
----------------
-
-For the EasyCAP with S-VIDEO input cable the driver regards a request for
-inputs numbered 0 or 1 as referring to CVBS and a request for input
-numbered 5 as referring to S-VIDEO.
-
-For the EasyCAP with four CVBS inputs the driver expects to be asked for
-any one of inputs numbered 1,2,3,4.  If input 0 is asked for, it is
-interpreted as input 1.
-
-
-MODULE PARAMETERS
------------------
-
-Three module parameters are defined:
-
-debug      the easycap module is configured at diagnostic level n (0 to 9)
-gain       audio gain level n (0 to 31, default is 16)
-bars       whether to display testcard bars when incoming video signal is lost
-           0 => no, 1 => yes (default)
-
-
-SUPPORTED TV STANDARDS AND RESOLUTIONS
---------------------------------------
-
-The following TV standards are natively supported by the hardware and are
-usable as (for example) the "norm=" parameter in the mplayer command:
-
-    PAL_BGHIN,    NTSC_N_443,
-    PAL_Nc,       NTSC_N,
-    SECAM,        NTSC_M,        NTSC_M_JP,
-    PAL_60,       NTSC_443,
-    PAL_M.
-
-In addition, the driver offers "custom" pseudo-standards with a framerate
-which is 20% of the usual framerate.  These pseudo-standards are named:
-
-    PAL_BGHIN_SLOW,    NTSC_N_443_SLOW,
-    PAL_Nc_SLOW,       NTSC_N_SLOW,
-    SECAM_SLOW,        NTSC_M_SLOW,        NTSC_M_JP_SLOW,
-    PAL_60_SLOW,       NTSC_443_SLOW,
-    PAL_M_SLOW.
-
-
-The available picture sizes are:
-
-     at 25 frames per second:   720x576, 704x576, 640x480, 360x288, 320x240;
-     at 30 frames per second:   720x480, 640x480, 360x240, 320x240.
-
-
-WHAT'S TESTED AND WHAT'S NOT
-----------------------------
-
-This driver is known to work with mplayer, mencoder, tvtime, zoneminder,
-xawtv, gstreamer and sufficiently recent versions of vlc.  An interface
-to ffmpeg is implemented, but serious audio-video synchronization problems
-remain.
-
-The driver is designed to support all the TV standards accepted by the
-hardware, but as yet it has actually been tested on only a few of these.
-
-I have been unable to test and calibrate the S-video input myself because I
-do not possess any equipment with S-video output.
-
-
-UDEV RULES
-----------
-
-In order that the special files /dev/easycap0 and /dev/easysnd1 are created
-with conveniently relaxed permissions when the EasyCAP is plugged in, a file
-is preferably to be provided in directory /etc/udev/rules.d with content:
-
-ACTION!="add|change", GOTO="easycap_rules_end"
-ATTRS{idVendor}=="05e1", ATTRS{idProduct}=="0408", \
-       MODE="0666", OWNER="root", GROUP="root"
-LABEL="easycap_rules_end"
-
-
-MODPROBE CONFIGURATION
-----------------------
-
-The easycap module is in competition with the module snd-usb-audio for the
-EasyCAP's audio channel, and its installation can be aided by providing a
-file in directory /etc/modprobe.d with content:
-
-options easycap  gain=16 bars=1
-install easycap /sbin/rmmod snd-usb-audio; /sbin/modprobe --ignore-install easycap
-
-
-ACKNOWLEGEMENTS AND REFERENCES
-------------------------------
-This driver makes use of information contained in the Syntek Semicon DC-1125
-Driver, presently maintained at http://sourceforge.net/projects/syntekdriver/
-by Nicolas Vivien.  Particularly useful has been a patch to the latter driver
-provided by Ivor Hewitt in January 2009.  The NTSC implementation is taken
-from the work of Ben Trask.
-
diff --git a/drivers/staging/media/easycap/easycap.h b/drivers/staging/media/easycap/easycap.h
deleted file mode 100644 (file)
index a007e74..0000000
+++ /dev/null
@@ -1,567 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*  easycap.h                                                                 *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THE FOLLOWING PARAMETERS ARE UNDEFINED:
- *
- *                EASYCAP_DEBUG
- *
- *  IF REQUIRED THEY MUST BE EXTERNALLY DEFINED, FOR EXAMPLE AS COMPILER
- *  OPTIONS.
- */
-/*---------------------------------------------------------------------------*/
-
-#ifndef __EASYCAP_H__
-#define __EASYCAP_H__
-
-/*---------------------------------------------------------------------------*/
-/*
- *  THESE ARE NORMALLY DEFINED
- */
-/*---------------------------------------------------------------------------*/
-#define  PATIENCE  500
-#define  PERSEVERE
-/*---------------------------------------------------------------------------*/
-/*
- *  THESE ARE FOR MAINTENANCE ONLY - NORMALLY UNDEFINED:
- */
-/*---------------------------------------------------------------------------*/
-#undef  EASYCAP_TESTCARD
-/*---------------------------------------------------------------------------*/
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/init.h>
-#include <linux/slab.h>
-#include <linux/module.h>
-#include <linux/kref.h>
-#include <linux/usb.h>
-#include <linux/uaccess.h>
-
-#include <linux/i2c.h>
-#include <linux/workqueue.h>
-#include <linux/poll.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/delay.h>
-#include <linux/types.h>
-
-#include <linux/vmalloc.h>
-#include <linux/sound.h>
-#include <sound/core.h>
-#include <sound/pcm.h>
-#include <sound/pcm_params.h>
-#include <sound/info.h>
-#include <sound/initval.h>
-#include <sound/control.h>
-#include <media/v4l2-dev.h>
-#include <media/v4l2-device.h>
-#include <linux/videodev2.h>
-#include <linux/soundcard.h>
-
-/*---------------------------------------------------------------------------*/
-/*  VENDOR, PRODUCT:  Syntek Semiconductor Co., Ltd
- *
- *      EITHER        EasyCAP USB 2.0 Video Adapter with Audio, Model No. DC60
- *               with input cabling:  AUDIO(L), AUDIO(R), CVBS, S-VIDEO.
- *
- *          OR        EasyCAP 4CHANNEL USB 2.0 DVR, Model No. EasyCAP002
- *               with input cabling:  MICROPHONE, CVBS1, CVBS2, CVBS3, CVBS4.
- */
-/*---------------------------------------------------------------------------*/
-#define USB_EASYCAP_VENDOR_ID  0x05e1
-#define USB_EASYCAP_PRODUCT_ID 0x0408
-
-#define EASYCAP_DRIVER_VERSION "0.9.01"
-#define EASYCAP_DRIVER_DESCRIPTION "easycapdc60"
-
-#define DONGLE_MANY 8
-#define INPUT_MANY 6
-/*---------------------------------------------------------------------------*/
-/*
- *  DEFAULT LUMINANCE, CONTRAST, SATURATION AND HUE
- */
-/*---------------------------------------------------------------------------*/
-#define SAA_0A_DEFAULT 0x7F
-#define SAA_0B_DEFAULT 0x3F
-#define SAA_0C_DEFAULT 0x2F
-#define SAA_0D_DEFAULT 0x00
-/*---------------------------------------------------------------------------*/
-/*
- *  VIDEO STREAMING PARAMETERS:
- *  USB 2.0 PROVIDES FOR HIGH-BANDWIDTH ENDPOINTS WITH AN UPPER LIMIT
- *  OF 3072 BYTES PER MICROFRAME for wMaxPacketSize.
- */
-/*---------------------------------------------------------------------------*/
-#define VIDEO_ISOC_BUFFER_MANY 16
-#define VIDEO_ISOC_ORDER 3
-#define VIDEO_ISOC_FRAMESPERDESC ((unsigned int) 1 << VIDEO_ISOC_ORDER)
-#define USB_2_0_MAXPACKETSIZE 3072
-#if (USB_2_0_MAXPACKETSIZE > PAGE_SIZE)
-#error video_isoc_buffer[.] will not be big enough
-#endif
-#define VIDEO_JUNK_TOLERATE VIDEO_ISOC_BUFFER_MANY
-#define VIDEO_LOST_TOLERATE 50
-/*---------------------------------------------------------------------------*/
-/*
- *  VIDEO BUFFERS
- */
-/*---------------------------------------------------------------------------*/
-#define FIELD_BUFFER_SIZE (203 * PAGE_SIZE)
-#define FRAME_BUFFER_SIZE (405 * PAGE_SIZE)
-#define FIELD_BUFFER_MANY 4
-#define FRAME_BUFFER_MANY 6
-/*---------------------------------------------------------------------------*/
-/*
- *  AUDIO STREAMING PARAMETERS
- */
-/*---------------------------------------------------------------------------*/
-#define AUDIO_ISOC_BUFFER_MANY 16
-#define AUDIO_ISOC_ORDER 1
-#define AUDIO_ISOC_FRAMESPERDESC 32
-#define AUDIO_ISOC_BUFFER_SIZE (PAGE_SIZE << AUDIO_ISOC_ORDER)
-/*---------------------------------------------------------------------------*/
-/*
- *  AUDIO BUFFERS
- */
-/*---------------------------------------------------------------------------*/
-#define AUDIO_FRAGMENT_MANY 32
-#define PAGES_PER_AUDIO_FRAGMENT 4
-/*---------------------------------------------------------------------------*/
-/*
- *  IT IS ESSENTIAL THAT EVEN-NUMBERED STANDARDS ARE 25 FRAMES PER SECOND,
- *                        ODD-NUMBERED STANDARDS ARE 30 FRAMES PER SECOND.
- *  THE NUMBERING OF STANDARDS MUST NOT BE CHANGED WITHOUT DUE CARE.  NOT
- *  ONLY MUST THE PARAMETER
- *                             STANDARD_MANY
- *  BE CHANGED TO CORRESPOND TO THE NEW NUMBER OF STANDARDS, BUT ALSO THE
- *  NUMBERING MUST REMAIN AN UNBROKEN ASCENDING SEQUENCE:  DUMMY STANDARDS
- *  MAY NEED TO BE ADDED.   APPROPRIATE CHANGES WILL ALWAYS BE REQUIRED IN
- *  ROUTINE fillin_formats() AND POSSIBLY ELSEWHERE.  BEWARE.
- */
-/*---------------------------------------------------------------------------*/
-#define  PAL_BGHIN      0
-#define  PAL_Nc         2
-#define  SECAM          4
-#define  NTSC_N         6
-#define  NTSC_N_443     8
-#define  NTSC_M         1
-#define  NTSC_443       3
-#define  NTSC_M_JP      5
-#define  PAL_60         7
-#define  PAL_M          9
-#define  PAL_BGHIN_SLOW    10
-#define  PAL_Nc_SLOW       12
-#define  SECAM_SLOW        14
-#define  NTSC_N_SLOW       16
-#define  NTSC_N_443_SLOW   18
-#define  NTSC_M_SLOW       11
-#define  NTSC_443_SLOW     13
-#define  NTSC_M_JP_SLOW    15
-#define  PAL_60_SLOW       17
-#define  PAL_M_SLOW        19
-#define  STANDARD_MANY 20
-/*---------------------------------------------------------------------------*/
-/*
- *  ENUMS
- */
-/*---------------------------------------------------------------------------*/
-enum {
-       AT_720x576,
-       AT_704x576,
-       AT_640x480,
-       AT_720x480,
-       AT_360x288,
-       AT_320x240,
-       AT_360x240,
-       RESOLUTION_MANY
-};
-enum {
-       FMT_UYVY,
-       FMT_YUY2,
-       FMT_RGB24,
-       FMT_RGB32,
-       FMT_BGR24,
-       FMT_BGR32,
-       PIXELFORMAT_MANY
-};
-enum {
-       FIELD_NONE,
-       FIELD_INTERLACED,
-       INTERLACE_MANY
-};
-#define SETTINGS_MANY  (STANDARD_MANY * \
-                       RESOLUTION_MANY * \
-                       2 * \
-                       PIXELFORMAT_MANY * \
-                       INTERLACE_MANY)
-/*---------------------------------------------------------------------------*/
-/*
- *  STRUCTURE DEFINITIONS
- */
-/*---------------------------------------------------------------------------*/
-struct easycap_dongle {
-       struct easycap *peasycap;
-       struct mutex mutex_video;
-       struct mutex mutex_audio;
-};
-/*---------------------------------------------------------------------------*/
-struct data_buffer {
-       struct list_head list_head;
-       void *pgo;
-       void *pto;
-       u16 kount;
-       u16 input;
-};
-/*---------------------------------------------------------------------------*/
-struct data_urb {
-       struct list_head list_head;
-       struct urb *purb;
-       int isbuf;
-       int length;
-};
-/*---------------------------------------------------------------------------*/
-struct easycap_standard {
-       u16 mask;
-struct v4l2_standard v4l2_standard;
-};
-struct easycap_format {
-       u16 mask;
-       char name[128];
-struct v4l2_format v4l2_format;
-};
-struct inputset {
-       int input;
-       int input_ok;
-       int standard_offset;
-       int standard_offset_ok;
-       int format_offset;
-       int format_offset_ok;
-       int brightness;
-       int brightness_ok;
-       int contrast;
-       int contrast_ok;
-       int saturation;
-       int saturation_ok;
-       int hue;
-       int hue_ok;
-};
-/*---------------------------------------------------------------------------*/
-/*
- *   easycap.ilk == 0   =>  CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=256
- *   easycap.ilk == 2   =>  CVBS+S-VIDEO HARDWARE, AUDIO wMaxPacketSize=9
- *   easycap.ilk == 3   =>     FOUR-CVBS HARDWARE, AUDIO wMaxPacketSize=9
- */
-/*---------------------------------------------------------------------------*/
-struct easycap {
-       int isdongle;
-       int minor;
-
-       struct video_device video_device;
-       struct v4l2_device v4l2_device;
-
-       int status;
-       unsigned int audio_pages_per_fragment;
-       unsigned int audio_bytes_per_fragment;
-       unsigned int audio_buffer_page_many;
-
-#define UPSAMPLE
-#ifdef UPSAMPLE
-       s16 oldaudio;
-#endif /*UPSAMPLE*/
-
-       int ilk;
-       bool microphone;
-
-       struct usb_device *pusb_device;
-       struct usb_interface *pusb_interface;
-
-       struct kref kref;
-
-       int queued[FRAME_BUFFER_MANY];
-       int done[FRAME_BUFFER_MANY];
-
-       wait_queue_head_t wq_video;
-       wait_queue_head_t wq_audio;
-       wait_queue_head_t wq_trigger;
-
-       int input;
-       int polled;
-       int standard_offset;
-       int format_offset;
-       struct inputset inputset[INPUT_MANY];
-
-       bool ntsc;
-       int fps;
-       int usec;
-       int tolerate;
-       int skip;
-       int skipped;
-       int lost[INPUT_MANY];
-       int merit[180];
-
-       int    video_interface;
-       int    video_altsetting_on;
-       int    video_altsetting_off;
-       int    video_endpointnumber;
-       int    video_isoc_maxframesize;
-       int    video_isoc_buffer_size;
-       int    video_isoc_framesperdesc;
-
-       int    video_isoc_streaming;
-       int    video_isoc_sequence;
-       int    video_idle;
-       int    video_eof;
-       int    video_junk;
-
-       struct data_buffer video_isoc_buffer[VIDEO_ISOC_BUFFER_MANY];
-       struct data_buffer field_buffer[FIELD_BUFFER_MANY]
-                                       [(FIELD_BUFFER_SIZE/PAGE_SIZE)];
-       struct data_buffer frame_buffer[FRAME_BUFFER_MANY]
-                                       [(FRAME_BUFFER_SIZE/PAGE_SIZE)];
-
-       struct list_head urb_video_head;
-       struct list_head *purb_video_head;
-
-       u8 cache[8];
-       u8 *pcache;
-       int video_mt;
-       int audio_mt;
-       u32 isequence;
-
-       int vma_many;
-/*---------------------------------------------------------------------------*/
-/*
- *  BUFFER INDICATORS
- */
-/*---------------------------------------------------------------------------*/
-       int field_fill; /* Field buffer being filled by easycap_complete().  */
-                       /*   Bumped only by easycap_complete().              */
-       int field_page; /* Page of field buffer page being filled by         */
-                       /*   easycap_complete().                             */
-       int field_read; /* Field buffer to be read by field2frame().         */
-                       /*   Bumped only by easycap_complete().              */
-       int frame_fill; /* Frame buffer being filled by field2frame().       */
-                       /*   Bumped only by easycap_dqbuf() when             */
-                       /*   field2frame() has created a complete frame.     */
-       int frame_read; /* Frame buffer offered to user by DQBUF.            */
-                       /*   Set only by easycap_dqbuf() to trail frame_fill.*/
-       int frame_lock; /* Flag set to 1 by DQBUF and cleared by QBUF        */
-/*---------------------------------------------------------------------------*/
-/*
- *  IMAGE PROPERTIES
- */
-/*---------------------------------------------------------------------------*/
-       u32                   pixelformat;
-       int                     width;
-       int                     height;
-       int                     bytesperpixel;
-       bool                    byteswaporder;
-       bool                    decimatepixel;
-       bool                    offerfields;
-       int                     frame_buffer_used;
-       int                     frame_buffer_many;
-       int                     videofieldamount;
-
-       int                     brightness;
-       int                     contrast;
-       int                     saturation;
-       int                     hue;
-
-       int allocation_video_urb;
-       int allocation_video_page;
-       int allocation_video_struct;
-       int registered_video;
-/*---------------------------------------------------------------------------*/
-/*
- *  ALSA
- */
-/*---------------------------------------------------------------------------*/
-       struct snd_pcm_hardware alsa_hardware;
-       struct snd_card *psnd_card;
-       struct snd_pcm *psnd_pcm;
-       struct snd_pcm_substream *psubstream;
-       int dma_fill;
-       int dma_next;
-       int dma_read;
-/*---------------------------------------------------------------------------*/
-/*
- *  SOUND PROPERTIES
- */
-/*---------------------------------------------------------------------------*/
-       int audio_interface;
-       int audio_altsetting_on;
-       int audio_altsetting_off;
-       int audio_endpointnumber;
-       int audio_isoc_maxframesize;
-       int audio_isoc_buffer_size;
-       int audio_isoc_framesperdesc;
-
-       int audio_isoc_streaming;
-       int audio_idle;
-       int audio_eof;
-       int volume;
-       int mute;
-       s8 gain;
-
-       struct data_buffer audio_isoc_buffer[AUDIO_ISOC_BUFFER_MANY];
-
-       struct list_head urb_audio_head;
-       struct list_head *purb_audio_head;
-/*---------------------------------------------------------------------------*/
-/*
- *  BUFFER INDICATORS
- */
-/*---------------------------------------------------------------------------*/
-       int audio_fill; /* Audio buffer being filled by easycap_complete().  */
-                       /*   Bumped only by easycap_complete().              */
-       int audio_read; /* Audio buffer page being read by easycap_read().   */
-                       /*   Set by easycap_read() to trail audio_fill by    */
-                       /*   one fragment.                                   */
-/*---------------------------------------------------------------------------*/
-/*
- *  SOUND PROPERTIES
- */
-/*---------------------------------------------------------------------------*/
-       int allocation_audio_urb;
-       int allocation_audio_page;
-       int allocation_audio_struct;
-       int registered_audio;
-
-       long long int audio_sample;
-       long long int audio_niveau;
-       long long int audio_square;
-
-       struct data_buffer audio_buffer[];
-};
-/*---------------------------------------------------------------------------*/
-/*
- *  VIDEO FUNCTION PROTOTYPES
- */
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-int easycap_newinput(struct easycap *, int);
-void easycap_testcard(struct easycap *, int);
-int easycap_isdongle(struct easycap *);
-
-long easycap_unlocked_ioctl(struct file *, unsigned int, unsigned long);
-
-int easycap_video_dqbuf(struct easycap *, int);
-int easycap_video_submit_urbs(struct easycap *);
-int easycap_video_kill_urbs(struct easycap *);
-int easycap_video_fillin_formats(void);
-
-int adjust_standard(struct easycap *, v4l2_std_id);
-int adjust_format(struct easycap *, u32, u32, u32, int, bool);
-int adjust_brightness(struct easycap *, int);
-int adjust_contrast(struct easycap *, int);
-int adjust_saturation(struct easycap *, int);
-int adjust_hue(struct easycap *, int);
-/*---------------------------------------------------------------------------*/
-/*
- *  AUDIO FUNCTION PROTOTYPES
- */
-/*---------------------------------------------------------------------------*/
-int easycap_alsa_probe(struct easycap *);
-int easycap_audio_kill_urbs(struct easycap *);
-void easycap_alsa_complete(struct urb *);
-/*---------------------------------------------------------------------------*/
-/*
- *  LOW-LEVEL FUNCTION PROTOTYPES
- */
-/*---------------------------------------------------------------------------*/
-int easycap_audio_gainset(struct usb_device *, s8);
-int easycap_audio_setup(struct easycap *);
-
-int easycap_wakeup_device(struct usb_device *);
-
-int setup_stk(struct usb_device *, bool);
-int setup_saa(struct usb_device *, bool);
-int ready_saa(struct usb_device *);
-int merit_saa(struct usb_device *);
-int check_vt(struct usb_device *);
-int select_input(struct usb_device *, int, int);
-int set_resolution(struct usb_device *, u16, u16, u16, u16);
-
-int read_saa(struct usb_device *, u16);
-int write_saa(struct usb_device *, u16, u16);
-int start_100(struct usb_device *);
-int stop_100(struct usb_device *);
-/*---------------------------------------------------------------------------*/
-
-
-/*---------------------------------------------------------------------------*/
-/*
- *  MACROS SAM(...) AND JOM(...) ALLOW DIAGNOSTIC OUTPUT TO BE TAGGED WITH
- *  THE IDENTITY OF THE DONGLE TO WHICH IT APPLIES, BUT IF INVOKED WHEN THE
- *  POINTER peasycap IS INVALID AN Oops IS LIKELY, AND ITS CAUSE MAY NOT BE
- *  IMMEDIATELY OBVIOUS FROM A CASUAL READING OF THE SOURCE CODE.  BEWARE.
-*/
-/*---------------------------------------------------------------------------*/
-const char *strerror(int err);
-
-#define SAY(format, args...) do { \
-       printk(KERN_DEBUG "easycap:: %s: " \
-                       format, __func__, ##args); \
-} while (0)
-#define SAM(format, args...) do { \
-       printk(KERN_DEBUG "easycap::%i%s: " \
-                       format, peasycap->isdongle, __func__, ##args);\
-} while (0)
-
-#ifdef CONFIG_EASYCAP_DEBUG
-extern int easycap_debug;
-#define JOT(n, format, args...) do { \
-       if (n <= easycap_debug) { \
-               printk(KERN_DEBUG "easycap:: %s: " \
-                       format, __func__, ##args);\
-       } \
-} while (0)
-#define JOM(n, format, args...) do { \
-       if (n <= easycap_debug) { \
-               printk(KERN_DEBUG "easycap::%i%s: " \
-                       format, peasycap->isdongle, __func__, ##args);\
-       } \
-} while (0)
-
-#else
-#define JOT(n, format, args...) do {} while (0)
-#define JOM(n, format, args...) do {} while (0)
-#endif /* CONFIG_EASYCAP_DEBUG */
-
-/*---------------------------------------------------------------------------*/
-
-/*---------------------------------------------------------------------------*/
-/* globals
- */
-/*---------------------------------------------------------------------------*/
-
-extern bool easycap_readback;
-extern const struct easycap_standard easycap_standard[];
-extern struct easycap_format easycap_format[];
-extern struct v4l2_queryctrl easycap_control[];
-extern struct easycap_dongle easycapdc60_dongle[];
-
-#endif /* !__EASYCAP_H__  */
diff --git a/drivers/staging/media/easycap/easycap_ioctl.c b/drivers/staging/media/easycap/easycap_ioctl.c
deleted file mode 100644 (file)
index 3cee3cd..0000000
+++ /dev/null
@@ -1,2443 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_ioctl.c                                                            *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-#include <linux/version.h>
-
-/*--------------------------------------------------------------------------*/
-/*
- *  UNLESS THERE IS A PREMATURE ERROR RETURN THIS ROUTINE UPDATES THE
- *  FOLLOWING:
- *          peasycap->standard_offset
- *          peasycap->inputset[peasycap->input].standard_offset
- *          peasycap->fps
- *          peasycap->usec
- *          peasycap->tolerate
- *          peasycap->skip
- */
-/*---------------------------------------------------------------------------*/
-int adjust_standard(struct easycap *peasycap, v4l2_std_id std_id)
-{
-       struct easycap_standard const *peasycap_standard;
-       u16 reg, set;
-       int ir, rc, need, k;
-       unsigned int itwas, isnow;
-       bool resubmit;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       peasycap_standard = &easycap_standard[0];
-       while (0xFFFF != peasycap_standard->mask) {
-               if (std_id == peasycap_standard->v4l2_standard.id)
-                       break;
-               peasycap_standard++;
-       }
-       if (0xFFFF == peasycap_standard->mask) {
-               peasycap_standard = &easycap_standard[0];
-               while (0xFFFF != peasycap_standard->mask) {
-                       if (std_id & peasycap_standard->v4l2_standard.id)
-                               break;
-                       peasycap_standard++;
-               }
-       }
-       if (0xFFFF == peasycap_standard->mask) {
-               SAM("ERROR: 0x%08X=std_id: standard not found\n",
-                   (unsigned int)std_id);
-               return -EINVAL;
-       }
-       SAM("selected standard: %s\n",
-           &(peasycap_standard->v4l2_standard.name[0]));
-       if (peasycap->standard_offset == peasycap_standard - easycap_standard) {
-               SAM("requested standard already in effect\n");
-               return 0;
-       }
-       peasycap->standard_offset = peasycap_standard - easycap_standard;
-       for (k = 0; k < INPUT_MANY;  k++) {
-               if (!peasycap->inputset[k].standard_offset_ok) {
-                       peasycap->inputset[k].standard_offset =
-                               peasycap->standard_offset;
-               }
-       }
-       if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-               peasycap->inputset[peasycap->input].standard_offset =
-                       peasycap->standard_offset;
-               peasycap->inputset[peasycap->input].standard_offset_ok = 1;
-       } else
-               JOM(8, "%i=peasycap->input\n", peasycap->input);
-
-       peasycap->fps = peasycap_standard->v4l2_standard.frameperiod.denominator /
-                       peasycap_standard->v4l2_standard.frameperiod.numerator;
-       switch (peasycap->fps) {
-       case 6:
-       case 30: {
-               peasycap->ntsc = true;
-               break;
-       }
-       case 5:
-       case 25: {
-               peasycap->ntsc = false;
-               break;
-       }
-       default: {
-               SAM("MISTAKE: %i=frames-per-second\n", peasycap->fps);
-               return -ENOENT;
-       }
-       }
-       JOM(8, "%i frames-per-second\n", peasycap->fps);
-       if (0x8000 & peasycap_standard->mask) {
-               peasycap->skip = 5;
-               peasycap->usec = 1000000 / (2 * (5 * peasycap->fps));
-               peasycap->tolerate = 1000 * (25 / (5 * peasycap->fps));
-       } else {
-               peasycap->skip = 0;
-               peasycap->usec = 1000000 / (2 * peasycap->fps);
-               peasycap->tolerate = 1000 * (25 / peasycap->fps);
-       }
-       if (peasycap->video_isoc_streaming) {
-               resubmit = true;
-               easycap_video_kill_urbs(peasycap);
-       } else
-               resubmit = false;
-/*--------------------------------------------------------------------------*/
-/*
- *  SAA7113H DATASHEET PAGE 44, TABLE 42
- */
-/*--------------------------------------------------------------------------*/
-       need = 0;
-       itwas = 0;
-       reg = 0x00;
-       set = 0x00;
-       switch (peasycap_standard->mask & 0x000F) {
-       case NTSC_M_JP: {
-               reg = 0x0A;
-               set = 0x95;
-               ir = read_saa(peasycap->pusb_device, reg);
-               if (0 > ir)
-                       SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
-               else
-                       itwas = (unsigned int)ir;
-               rc = write_saa(peasycap->pusb_device, reg, set);
-               if (rc)
-                       SAM("ERROR: failed to set SAA register "
-                           "0x%02X to 0x%02X for JP standard\n", reg, set);
-               else {
-                       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-                       if (0 > ir)
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "to 0x%02X\n", reg, isnow);
-                       else
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-               }
-
-               reg = 0x0B;
-               set = 0x48;
-               ir = read_saa(peasycap->pusb_device, reg);
-               if (0 > ir)
-                       SAM("ERROR: cannot read SAA register 0x%02X\n", reg);
-               else
-                       itwas = (unsigned int)ir;
-               rc = write_saa(peasycap->pusb_device, reg, set);
-               if (rc)
-                       SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X "
-                           "for JP standard\n", reg, set);
-               else {
-                       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-                       if (0 > ir)
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "to 0x%02X\n", reg, isnow);
-                       else
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-               }
-/*--------------------------------------------------------------------------*/
-/*
- *  NOTE:  NO break HERE:  RUN ON TO NEXT CASE
- */
-/*--------------------------------------------------------------------------*/
-       }
-       case NTSC_M:
-       case PAL_BGHIN: {
-               reg = 0x0E;
-               set = 0x01;
-               need = 1;
-               break;
-       }
-       case NTSC_N_443:
-       case PAL_60: {
-               reg = 0x0E;
-               set = 0x11;
-               need = 1;
-               break;
-       }
-       case NTSC_443:
-       case PAL_Nc: {
-               reg = 0x0E;
-               set = 0x21;
-               need = 1;
-               break;
-       }
-       case NTSC_N:
-       case PAL_M: {
-               reg = 0x0E;
-               set = 0x31;
-               need = 1;
-               break;
-       }
-       case SECAM: {
-               reg = 0x0E;
-               set = 0x51;
-               need = 1;
-               break;
-       }
-       default:
-               break;
-       }
-/*--------------------------------------------------------------------------*/
-       if (need) {
-               ir = read_saa(peasycap->pusb_device, reg);
-               if (0 > ir)
-                       SAM("ERROR: failed to read SAA register 0x%02X\n", reg);
-               else
-                       itwas = (unsigned int)ir;
-               rc = write_saa(peasycap->pusb_device, reg, set);
-               if (0 != write_saa(peasycap->pusb_device, reg, set)) {
-                       SAM("ERROR: failed to set SAA register "
-                           "0x%02X to 0x%02X for table 42\n", reg, set);
-               } else {
-                       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-                       if (0 > ir)
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "to 0x%02X\n", reg, isnow);
-                       else
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-               }
-       }
-/*--------------------------------------------------------------------------*/
-/*
-        *  SAA7113H DATASHEET PAGE 41
-        */
-/*--------------------------------------------------------------------------*/
-       reg = 0x08;
-       ir = read_saa(peasycap->pusb_device, reg);
-       if (0 > ir)
-               SAM("ERROR: failed to read SAA register 0x%02X "
-                   "so cannot reset\n", reg);
-       else {
-               itwas = (unsigned int)ir;
-               if (peasycap_standard->mask & 0x0001)
-                       set = itwas | 0x40 ;
-               else
-                       set = itwas & ~0x40 ;
-               rc  = write_saa(peasycap->pusb_device, reg, set);
-               if (rc)
-                       SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
-                           reg, set);
-               else {
-                       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-                       if (0 > ir)
-                               JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
-                                   reg, isnow);
-                       else
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-               }
-       }
-/*--------------------------------------------------------------------------*/
-/*
- *  SAA7113H DATASHEET PAGE 51, TABLE 57
- */
-/*---------------------------------------------------------------------------*/
-       reg = 0x40;
-       ir = read_saa(peasycap->pusb_device, reg);
-       if (0 > ir)
-               SAM("ERROR: failed to read SAA register 0x%02X "
-                   "so cannot reset\n", reg);
-       else {
-               itwas = (unsigned int)ir;
-               if (peasycap_standard->mask & 0x0001)
-                       set = itwas | 0x80 ;
-               else
-                       set = itwas & ~0x80 ;
-               rc = write_saa(peasycap->pusb_device, reg, set);
-               if (rc)
-                       SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
-                           reg, set);
-               else {
-                       isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-                       if (0 > ir)
-                               JOM(8, "SAA register 0x%02X changed to 0x%02X\n",
-                                   reg, isnow);
-                       else
-                               JOM(8, "SAA register 0x%02X changed "
-                                   "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-               }
-       }
-/*--------------------------------------------------------------------------*/
-/*
-        *  SAA7113H DATASHEET PAGE 53, TABLE 66
-        */
-/*--------------------------------------------------------------------------*/
-       reg = 0x5A;
-       ir = read_saa(peasycap->pusb_device, reg);
-       if (0 > ir)
-               SAM("ERROR: failed to read SAA register 0x%02X but continuing\n", reg);
-       itwas = (unsigned int)ir;
-       if (peasycap_standard->mask & 0x0001)
-               set = 0x0A ;
-       else
-               set = 0x07 ;
-       if (0 != write_saa(peasycap->pusb_device, reg, set))
-               SAM("ERROR: failed to set SAA register 0x%02X to 0x%02X\n",
-                   reg, set);
-       else {
-               isnow = (unsigned int)read_saa(peasycap->pusb_device, reg);
-               if (0 > ir)
-                       JOM(8, "SAA register 0x%02X changed "
-                           "to 0x%02X\n", reg, isnow);
-               else
-                       JOM(8, "SAA register 0x%02X changed "
-                           "from 0x%02X to 0x%02X\n", reg, itwas, isnow);
-       }
-       if (resubmit)
-               easycap_video_submit_urbs(peasycap);
-       return 0;
-}
-/*****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  THE ALGORITHM FOR RESPONDING TO THE VIDIO_S_FMT IOCTL REQUIRES
- *  A VALID VALUE OF peasycap->standard_offset, OTHERWISE -EBUSY IS RETURNED.
- *
- *  PROVIDED THE ARGUMENT try IS false AND THERE IS NO PREMATURE ERROR RETURN
- *  THIS ROUTINE UPDATES THE FOLLOWING:
- *          peasycap->format_offset
- *          peasycap->inputset[peasycap->input].format_offset
- *          peasycap->pixelformat
- *          peasycap->height
- *          peasycap->width
- *          peasycap->bytesperpixel
- *          peasycap->byteswaporder
- *          peasycap->decimatepixel
- *          peasycap->frame_buffer_used
- *          peasycap->videofieldamount
- *          peasycap->offerfields
- *
- *  IF SUCCESSFUL THE FUNCTION RETURNS THE OFFSET IN easycap_format[]
- *  IDENTIFYING THE FORMAT WHICH IS TO RETURNED TO THE USER.
- *  ERRORS RETURN A NEGATIVE NUMBER.
- */
-/*--------------------------------------------------------------------------*/
-int adjust_format(struct easycap *peasycap,
-                 u32 width, u32 height, u32 pixelformat, int field, bool try)
-{
-       struct easycap_format *peasycap_format, *peasycap_best_format;
-       u16 mask;
-       struct usb_device *p;
-       int miss, multiplier, best, k;
-       char bf[5], fo[32], *pc;
-       u32 uc;
-       bool resubmit;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (0 > peasycap->standard_offset) {
-               JOM(8, "%i=peasycap->standard_offset\n", peasycap->standard_offset);
-               return -EBUSY;
-       }
-       p = peasycap->pusb_device;
-       if (!p) {
-               SAM("ERROR: peaycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       pc = &bf[0];
-       uc = pixelformat;
-       memcpy((void *)pc, (void *)(&uc), 4);
-       bf[4] = 0;
-       mask = 0xFF & easycap_standard[peasycap->standard_offset].mask;
-       SAM("sought:    %ix%i,%s(0x%08X),%i=field,0x%02X=std mask\n",
-           width, height, pc, pixelformat, field, mask);
-       switch (field) {
-       case V4L2_FIELD_ANY: {
-               strcpy(&fo[0], "V4L2_FIELD_ANY ");
-               break;
-       }
-       case V4L2_FIELD_NONE: {
-               strcpy(&fo[0], "V4L2_FIELD_NONE");
-               break;
-       }
-       case V4L2_FIELD_TOP: {
-               strcpy(&fo[0], "V4L2_FIELD_TOP");
-               break;
-       }
-       case V4L2_FIELD_BOTTOM: {
-               strcpy(&fo[0], "V4L2_FIELD_BOTTOM");
-               break;
-       }
-       case V4L2_FIELD_INTERLACED: {
-               strcpy(&fo[0], "V4L2_FIELD_INTERLACED");
-               break;
-       }
-       case V4L2_FIELD_SEQ_TB: {
-               strcpy(&fo[0], "V4L2_FIELD_SEQ_TB");
-               break;
-       }
-       case V4L2_FIELD_SEQ_BT: {
-               strcpy(&fo[0], "V4L2_FIELD_SEQ_BT");
-               break;
-       }
-       case V4L2_FIELD_ALTERNATE: {
-               strcpy(&fo[0], "V4L2_FIELD_ALTERNATE");
-               break;
-       }
-       case V4L2_FIELD_INTERLACED_TB: {
-               strcpy(&fo[0], "V4L2_FIELD_INTERLACED_TB");
-               break;
-       }
-       case V4L2_FIELD_INTERLACED_BT: {
-               strcpy(&fo[0], "V4L2_FIELD_INTERLACED_BT");
-               break;
-       }
-       default: {
-               strcpy(&fo[0], "V4L2_FIELD_... UNKNOWN  ");
-               break;
-       }
-       }
-       SAM("sought:    %s\n", &fo[0]);
-       if (V4L2_FIELD_ANY == field) {
-               field = V4L2_FIELD_NONE;
-               SAM("prefer:    V4L2_FIELD_NONE=field, was V4L2_FIELD_ANY\n");
-       }
-       peasycap_best_format = NULL;
-       peasycap_format = &easycap_format[0];
-       while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-               JOM(16, ".> %i %i 0x%08X %ix%i\n",
-                   peasycap_format->mask & 0x01,
-                   peasycap_format->v4l2_format.fmt.pix.field,
-                   peasycap_format->v4l2_format.fmt.pix.pixelformat,
-                   peasycap_format->v4l2_format.fmt.pix.width,
-                   peasycap_format->v4l2_format.fmt.pix.height);
-
-               if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
-                   (peasycap_format->v4l2_format.fmt.pix.field == field) &&
-                   (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat) &&
-                   (peasycap_format->v4l2_format.fmt.pix.width  == width) &&
-                   (peasycap_format->v4l2_format.fmt.pix.height == height)) {
-
-                       peasycap_best_format = peasycap_format;
-                       break;
-               }
-               peasycap_format++;
-       }
-       if (0 == peasycap_format->v4l2_format.fmt.pix.width) {
-               SAM("cannot do: %ix%i with standard mask 0x%02X\n",
-                   width, height, mask);
-               peasycap_format = &easycap_format[0];
-               best = -1;
-               while (0 != peasycap_format->v4l2_format.fmt.pix.width) {
-                       if (((peasycap_format->mask & 0x1F) == (mask & 0x1F)) &&
-                           (peasycap_format->v4l2_format.fmt.pix.field == field) &&
-                           (peasycap_format->v4l2_format.fmt.pix.pixelformat == pixelformat)) {
-
-                               miss = abs(peasycap_format->v4l2_format.fmt.pix.width  - width);
-                               if ((best > miss) || (best < 0)) {
-                                       best = miss;
-                                       peasycap_best_format = peasycap_format;
-                                       if (!miss)
-                                               break;
-                               }
-                       }
-                       peasycap_format++;
-               }
-               if (-1 == best) {
-                       SAM("cannot do %ix... with standard mask 0x%02X\n",
-                           width, mask);
-                       SAM("cannot do ...x%i with standard mask 0x%02X\n",
-                           height, mask);
-                       SAM("           %ix%i unmatched\n", width, height);
-                       return peasycap->format_offset;
-               }
-       }
-       if (!peasycap_best_format) {
-               SAM("MISTAKE: peasycap_best_format is NULL");
-               return -EINVAL;
-       }
-       peasycap_format = peasycap_best_format;
-
-/*...........................................................................*/
-       if (try)
-               return peasycap_best_format - easycap_format;
-/*...........................................................................*/
-
-       if (false != try) {
-               SAM("MISTAKE: true==try where is should be false\n");
-               return -EINVAL;
-       }
-       SAM("actioning: %ix%i %s\n",
-           peasycap_format->v4l2_format.fmt.pix.width,
-           peasycap_format->v4l2_format.fmt.pix.height,
-           &peasycap_format->name[0]);
-       peasycap->height        = peasycap_format->v4l2_format.fmt.pix.height;
-       peasycap->width         = peasycap_format->v4l2_format.fmt.pix.width;
-       peasycap->pixelformat   = peasycap_format->v4l2_format.fmt.pix.pixelformat;
-       peasycap->format_offset = peasycap_format - easycap_format;
-
-
-       for (k = 0; k < INPUT_MANY; k++) {
-               if (!peasycap->inputset[k].format_offset_ok) {
-                       peasycap->inputset[k].format_offset =
-                               peasycap->format_offset;
-               }
-       }
-       if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-               peasycap->inputset[peasycap->input].format_offset =
-                       peasycap->format_offset;
-               peasycap->inputset[peasycap->input].format_offset_ok = 1;
-       } else
-               JOM(8, "%i=peasycap->input\n", peasycap->input);
-
-
-
-       peasycap->bytesperpixel = (0x00E0 & peasycap_format->mask) >> 5 ;
-       if (0x0100 & peasycap_format->mask)
-               peasycap->byteswaporder = true;
-       else
-               peasycap->byteswaporder = false;
-       if (0x0200 & peasycap_format->mask)
-               peasycap->skip = 5;
-       else
-               peasycap->skip = 0;
-       if (0x0800 & peasycap_format->mask)
-               peasycap->decimatepixel = true;
-       else
-               peasycap->decimatepixel = false;
-       if (0x1000 & peasycap_format->mask)
-               peasycap->offerfields = true;
-       else
-               peasycap->offerfields = false;
-       if (peasycap->decimatepixel)
-               multiplier = 2;
-       else
-               multiplier = 1;
-       peasycap->videofieldamount =
-               multiplier * peasycap->width * multiplier * peasycap->height;
-       peasycap->frame_buffer_used =
-               peasycap->bytesperpixel * peasycap->width * peasycap->height;
-       if (peasycap->video_isoc_streaming) {
-               resubmit = true;
-               easycap_video_kill_urbs(peasycap);
-       } else
-               resubmit = false;
-/*---------------------------------------------------------------------------*/
-/*
-        *  PAL
-        */
-/*---------------------------------------------------------------------------*/
-       if (0 == (0x01 & peasycap_format->mask)) {
-               if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                    (576 == peasycap_format->v4l2_format.fmt.pix.height)) ||
-                   ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                    (288 == peasycap_format->v4l2_format.fmt.pix.height))) {
-                       if (set_resolution(p, 0x0000, 0x0001, 0x05A0, 0x0121)) {
-                               SAM("ERROR: set_resolution() failed\n");
-                               return -EINVAL;
-                       }
-               } else if ((704 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                          (576 == peasycap_format->v4l2_format.fmt.pix.height)) {
-                       if (set_resolution(p, 0x0004, 0x0001, 0x0584, 0x0121)) {
-                               SAM("ERROR: set_resolution() failed\n");
-                               return -EINVAL;
-                       }
-               } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                           (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
-                          ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                           (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
-                       if (set_resolution(p, 0x0014, 0x0020, 0x0514, 0x0110)) {
-                               SAM("ERROR: set_resolution() failed\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       SAM("MISTAKE: bad format, cannot set resolution\n");
-                       return -EINVAL;
-               }
-/*---------------------------------------------------------------------------*/
-/*
- *  NTSC
- */
-/*---------------------------------------------------------------------------*/
-       } else {
-               if (((720 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                    (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
-                   ((360 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                    (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
-                       if (set_resolution(p, 0x0000, 0x0003, 0x05A0, 0x00F3)) {
-                               SAM("ERROR: set_resolution() failed\n");
-                               return -EINVAL;
-                       }
-               } else if (((640 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                           (480 == peasycap_format->v4l2_format.fmt.pix.height)) ||
-                          ((320 == peasycap_format->v4l2_format.fmt.pix.width) &&
-                           (240 == peasycap_format->v4l2_format.fmt.pix.height))) {
-                       if (set_resolution(p, 0x0014, 0x0003, 0x0514, 0x00F3)) {
-                               SAM("ERROR: set_resolution() failed\n");
-                               return -EINVAL;
-                       }
-               } else {
-                       SAM("MISTAKE: bad format, cannot set resolution\n");
-                       return -EINVAL;
-               }
-       }
-/*---------------------------------------------------------------------------*/
-       if (resubmit)
-               easycap_video_submit_urbs(peasycap);
-
-       return peasycap_best_format - easycap_format;
-}
-/*****************************************************************************/
-int adjust_brightness(struct easycap *peasycap, int value)
-{
-       unsigned int mood;
-       int i1, k;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_BRIGHTNESS == easycap_control[i1].id) {
-                       if ((easycap_control[i1].minimum > value) ||
-                           (easycap_control[i1].maximum < value))
-                               value = easycap_control[i1].default_value;
-
-                       if ((easycap_control[i1].minimum <= peasycap->brightness) &&
-                           (easycap_control[i1].maximum >= peasycap->brightness)) {
-                               if (peasycap->brightness == value) {
-                                       SAM("unchanged brightness at  0x%02X\n",
-                                           value);
-                                       return 0;
-                               }
-                       }
-                       peasycap->brightness = value;
-                       for (k = 0; k < INPUT_MANY; k++) {
-                               if (!peasycap->inputset[k].brightness_ok)
-                                       peasycap->inputset[k].brightness =
-                                               peasycap->brightness;
-                       }
-                       if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-                               peasycap->inputset[peasycap->input].brightness =
-                                       peasycap->brightness;
-                               peasycap->inputset[peasycap->input].brightness_ok = 1;
-                       } else
-                               JOM(8, "%i=peasycap->input\n", peasycap->input);
-
-                       mood = 0x00FF & (unsigned int)peasycap->brightness;
-                       if (write_saa(peasycap->pusb_device, 0x0A, mood)) {
-                               SAM("WARNING: failed to adjust brightness "
-                                   "to 0x%02X\n", mood);
-                               return -ENOENT;
-                       }
-                       SAM("adjusting brightness to  0x%02X\n", mood);
-                       return 0;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust brightness: control not found\n");
-       return -ENOENT;
-}
-/*****************************************************************************/
-int adjust_contrast(struct easycap *peasycap, int value)
-{
-       unsigned int mood;
-       int i1, k;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_CONTRAST == easycap_control[i1].id) {
-                       if ((easycap_control[i1].minimum > value) ||
-                           (easycap_control[i1].maximum < value))
-                               value = easycap_control[i1].default_value;
-
-
-                       if ((easycap_control[i1].minimum <= peasycap->contrast) &&
-                           (easycap_control[i1].maximum >= peasycap->contrast)) {
-                               if (peasycap->contrast == value) {
-                                       SAM("unchanged contrast at  0x%02X\n", value);
-                                       return 0;
-                               }
-                       }
-                       peasycap->contrast = value;
-                       for (k = 0; k < INPUT_MANY; k++) {
-                               if (!peasycap->inputset[k].contrast_ok)
-                                       peasycap->inputset[k].contrast = peasycap->contrast;
-                       }
-
-                       if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-                               peasycap->inputset[peasycap->input].contrast =
-                                               peasycap->contrast;
-                               peasycap->inputset[peasycap->input].contrast_ok = 1;
-                       } else
-                               JOM(8, "%i=peasycap->input\n", peasycap->input);
-
-                       mood = 0x00FF & (unsigned int) (peasycap->contrast - 128);
-                       if (write_saa(peasycap->pusb_device, 0x0B, mood)) {
-                               SAM("WARNING: failed to adjust contrast to "
-                                   "0x%02X\n", mood);
-                               return -ENOENT;
-                       }
-                       SAM("adjusting contrast to  0x%02X\n", mood);
-                       return 0;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust contrast: control not found\n");
-       return -ENOENT;
-}
-/*****************************************************************************/
-int adjust_saturation(struct easycap *peasycap, int value)
-{
-       unsigned int mood;
-       int i1, k;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_SATURATION == easycap_control[i1].id) {
-                       if ((easycap_control[i1].minimum > value) ||
-                           (easycap_control[i1].maximum < value))
-                               value = easycap_control[i1].default_value;
-
-
-                       if ((easycap_control[i1].minimum <= peasycap->saturation) &&
-                           (easycap_control[i1].maximum >= peasycap->saturation)) {
-                               if (peasycap->saturation == value) {
-                                       SAM("unchanged saturation at  0x%02X\n",
-                                           value);
-                                       return 0;
-                               }
-                       }
-                       peasycap->saturation = value;
-                       for (k = 0; k < INPUT_MANY; k++) {
-                               if (!peasycap->inputset[k].saturation_ok)
-                                       peasycap->inputset[k].saturation =
-                                               peasycap->saturation;
-                       }
-                       if ((0 <= peasycap->input) && (INPUT_MANY > peasycap->input)) {
-                               peasycap->inputset[peasycap->input].saturation =
-                                       peasycap->saturation;
-                               peasycap->inputset[peasycap->input].saturation_ok = 1;
-                       } else
-                               JOM(8, "%i=peasycap->input\n", peasycap->input);
-                       mood = 0x00FF & (unsigned int) (peasycap->saturation - 128);
-                       if (write_saa(peasycap->pusb_device, 0x0C, mood)) {
-                               SAM("WARNING: failed to adjust saturation to "
-                                   "0x%02X\n", mood);
-                               return -ENOENT;
-                       }
-                       SAM("adjusting saturation to  0x%02X\n", mood);
-                       return 0;
-                       break;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust saturation: control not found\n");
-       return -ENOENT;
-}
-/*****************************************************************************/
-int adjust_hue(struct easycap *peasycap, int value)
-{
-       unsigned int mood;
-       int i1, i2, k;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_HUE == easycap_control[i1].id) {
-                       if ((easycap_control[i1].minimum > value) ||
-                           (easycap_control[i1].maximum < value))
-                               value = easycap_control[i1].default_value;
-
-                       if ((easycap_control[i1].minimum <= peasycap->hue) &&
-                           (easycap_control[i1].maximum >= peasycap->hue)) {
-                               if (peasycap->hue == value) {
-                                       SAM("unchanged hue at  0x%02X\n", value);
-                                       return 0;
-                               }
-                       }
-                       peasycap->hue = value;
-                       for (k = 0; k < INPUT_MANY; k++) {
-                               if (!peasycap->inputset[k].hue_ok)
-                                       peasycap->inputset[k].hue = peasycap->hue;
-                       }
-                       if (0 <= peasycap->input && INPUT_MANY > peasycap->input) {
-                               peasycap->inputset[peasycap->input].hue = peasycap->hue;
-                               peasycap->inputset[peasycap->input].hue_ok = 1;
-                       } else
-                               JOM(8, "%i=peasycap->input\n", peasycap->input);
-                       i2 = peasycap->hue - 128;
-                       mood = 0x00FF & ((int) i2);
-                       if (write_saa(peasycap->pusb_device, 0x0D, mood)) {
-                               SAM("WARNING: failed to adjust hue to 0x%02X\n", mood);
-                               return -ENOENT;
-                       }
-                       SAM("adjusting hue to  0x%02X\n", mood);
-                       return 0;
-                       break;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust hue: control not found\n");
-       return -ENOENT;
-}
-/*****************************************************************************/
-static int adjust_volume(struct easycap *peasycap, int value)
-{
-       s8 mood;
-       int i1;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_AUDIO_VOLUME == easycap_control[i1].id) {
-                       if ((easycap_control[i1].minimum > value) ||
-                           (easycap_control[i1].maximum < value))
-                               value = easycap_control[i1].default_value;
-
-                       if ((easycap_control[i1].minimum <= peasycap->volume) &&
-                           (easycap_control[i1].maximum >= peasycap->volume)) {
-                               if (peasycap->volume == value) {
-                                       SAM("unchanged volume at  0x%02X\n", value);
-                                       return 0;
-                               }
-                       }
-                       peasycap->volume = value;
-                       mood = (16 > peasycap->volume) ? 16 :
-                               ((31 < peasycap->volume) ? 31 :
-                                 (s8) peasycap->volume);
-                       if (!easycap_audio_gainset(peasycap->pusb_device, mood)) {
-                               SAM("WARNING: failed to adjust volume to "
-                                   "0x%2X\n", mood);
-                               return -ENOENT;
-                       }
-                       SAM("adjusting volume to 0x%02X\n", mood);
-                       return 0;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust volume: control not found\n");
-       return -ENOENT;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  AN ALTERNATIVE METHOD OF MUTING MIGHT SEEM TO BE:
- *            usb_set_interface(peasycap->pusb_device,
- *                              peasycap->audio_interface,
- *                              peasycap->audio_altsetting_off);
- *  HOWEVER, AFTER THIS COMMAND IS ISSUED ALL SUBSEQUENT URBS RECEIVE STATUS
- *  -ESHUTDOWN.  THE HANDLER ROUTINE easyxxx_complete() DECLINES TO RESUBMIT
- *  THE URB AND THE PIPELINE COLLAPSES IRRETRIEVABLY.  BEWARE.
- */
-/*---------------------------------------------------------------------------*/
-static int adjust_mute(struct easycap *peasycap, int value)
-{
-       int i1;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       i1 = 0;
-       while (0xFFFFFFFF != easycap_control[i1].id) {
-               if (V4L2_CID_AUDIO_MUTE == easycap_control[i1].id) {
-                       peasycap->mute = value;
-                       switch (peasycap->mute) {
-                       case 1: {
-                               peasycap->audio_idle = 1;
-                               SAM("adjusting mute: %i=peasycap->audio_idle\n",
-                                   peasycap->audio_idle);
-                               return 0;
-                       }
-                       default: {
-                               peasycap->audio_idle = 0;
-                               SAM("adjusting mute: %i=peasycap->audio_idle\n",
-                                   peasycap->audio_idle);
-                               return 0;
-                       }
-                       }
-                       break;
-               }
-               i1++;
-       }
-       SAM("WARNING: failed to adjust mute: control not found\n");
-       return -ENOENT;
-}
-/*---------------------------------------------------------------------------*/
-long easycap_unlocked_ioctl(struct file *file,
-                           unsigned int cmd, unsigned long arg)
-{
-       struct easycap *peasycap;
-       struct usb_device *p;
-       int kd;
-
-       if (!file) {
-               SAY("ERROR:  file is NULL\n");
-               return -ERESTARTSYS;
-       }
-       peasycap = file->private_data;
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -1;
-       }
-       p = peasycap->pusb_device;
-       if (!p) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       kd = easycap_isdongle(peasycap);
-       if (0 <= kd && DONGLE_MANY > kd) {
-               if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
-                       SAY("ERROR: cannot lock "
-                           "easycapdc60_dongle[%i].mutex_video\n", kd);
-                       return -ERESTARTSYS;
-               }
-               JOM(4, "locked easycapdc60_dongle[%i].mutex_video\n", kd);
-/*---------------------------------------------------------------------------*/
-/*
- *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER peasycap,
- *  IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
- *  IF NECESSARY, BAIL OUT.
- */
-/*---------------------------------------------------------------------------*/
-               if (kd != easycap_isdongle(peasycap))
-                       return -ERESTARTSYS;
-               if (!file) {
-                       SAY("ERROR:  file is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-               peasycap = file->private_data;
-               if (!peasycap) {
-                       SAY("ERROR:  peasycap is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-               if (!peasycap->pusb_device) {
-                       SAM("ERROR: peasycap->pusb_device is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-       } else {
-/*---------------------------------------------------------------------------*/
-/*
- *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap BEFORE THE
- *  ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL HAVE FAILED.  BAIL OUT.
- */
-/*---------------------------------------------------------------------------*/
-               return -ERESTARTSYS;
-       }
-/*---------------------------------------------------------------------------*/
-       switch (cmd) {
-       case VIDIOC_QUERYCAP: {
-               struct v4l2_capability v4l2_capability;
-               char version[16], *p1, *p2;
-               int i, rc, k[3];
-               long lng;
-
-               JOM(8, "VIDIOC_QUERYCAP\n");
-
-               if (16 <= strlen(EASYCAP_DRIVER_VERSION)) {
-                       SAM("ERROR: bad driver version string\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               strcpy(&version[0], EASYCAP_DRIVER_VERSION);
-               for (i = 0; i < 3; i++)
-                       k[i] = 0;
-               p2 = &version[0];
-               i = 0;
-               while (*p2) {
-                       p1 = p2;
-                       while (*p2 && ('.' != *p2))
-                               p2++;
-                       if (*p2)
-                               *p2++ = 0;
-                       if (3 > i) {
-                               rc = (int) strict_strtol(p1, 10, &lng);
-                               if (rc) {
-                                       SAM("ERROR: %i=strict_strtol(%s,.,,)\n",
-                                           rc, p1);
-                                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                                       return -EINVAL;
-                               }
-                               k[i] = (int)lng;
-                       }
-                       i++;
-               }
-
-               memset(&v4l2_capability, 0, sizeof(struct v4l2_capability));
-               strlcpy(&v4l2_capability.driver[0],
-                       "easycap", sizeof(v4l2_capability.driver));
-
-               v4l2_capability.capabilities = V4L2_CAP_VIDEO_CAPTURE |
-                                               V4L2_CAP_STREAMING |
-                                               V4L2_CAP_AUDIO |
-                                               V4L2_CAP_READWRITE;
-
-               v4l2_capability.version = KERNEL_VERSION(k[0], k[1], k[2]);
-               JOM(8, "v4l2_capability.version=(%i,%i,%i)\n", k[0], k[1], k[2]);
-
-               strlcpy(&v4l2_capability.card[0],
-                       "EasyCAP DC60", sizeof(v4l2_capability.card));
-
-               if (usb_make_path(peasycap->pusb_device,
-                               &v4l2_capability.bus_info[0],
-                               sizeof(v4l2_capability.bus_info)) < 0) {
-
-                       strlcpy(&v4l2_capability.bus_info[0], "EasyCAP bus_info",
-                               sizeof(v4l2_capability.bus_info));
-                       JOM(8, "%s=v4l2_capability.bus_info\n",
-                               &v4l2_capability.bus_info[0]);
-               }
-               if (copy_to_user((void __user *)arg, &v4l2_capability,
-                               sizeof(struct v4l2_capability))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUMINPUT: {
-               struct v4l2_input v4l2_input;
-               u32 index;
-
-               JOM(8, "VIDIOC_ENUMINPUT\n");
-
-               if (copy_from_user(&v4l2_input, (void __user *)arg,
-                                       sizeof(struct v4l2_input))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               index = v4l2_input.index;
-               memset(&v4l2_input, 0, sizeof(struct v4l2_input));
-
-               switch (index) {
-               case 0: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "CVBS0");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL |
-                                       V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC ;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               case 1: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "CVBS1");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               case 2: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "CVBS2");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC ;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               case 3: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "CVBS3");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC ;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               case 4: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "CVBS4");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC ;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               case 5: {
-                       v4l2_input.index = index;
-                       strcpy(&v4l2_input.name[0], "S-VIDEO");
-                       v4l2_input.type = V4L2_INPUT_TYPE_CAMERA;
-                       v4l2_input.audioset = 0x01;
-                       v4l2_input.tuner = 0;
-                       v4l2_input.std = V4L2_STD_PAL | V4L2_STD_SECAM |
-                                       V4L2_STD_NTSC ;
-                       v4l2_input.status = 0;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_input.name[0]);
-                       break;
-               }
-               default: {
-                       JOM(8, "%i=index: exhausts inputs\n", index);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               }
-
-               if (copy_to_user((void __user *)arg, &v4l2_input,
-                               sizeof(struct v4l2_input))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_INPUT: {
-               u32 index;
-
-               JOM(8, "VIDIOC_G_INPUT\n");
-               index = (u32)peasycap->input;
-               JOM(8, "user is told: %i\n", index);
-               if (copy_to_user((void __user *)arg, &index, sizeof(u32))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_INPUT:
-       {
-               u32 index;
-               int rc;
-
-               JOM(8, "VIDIOC_S_INPUT\n");
-
-               if (0 != copy_from_user(&index, (void __user *)arg, sizeof(u32))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               JOM(8, "user requests input %i\n", index);
-
-               if ((int)index == peasycap->input) {
-                       SAM("requested input already in effect\n");
-                       break;
-               }
-
-               if ((0 > index) || (INPUT_MANY <= index)) {
-                       JOM(8, "ERROR:  bad requested input: %i\n", index);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-
-               rc = easycap_newinput(peasycap, (int)index);
-               if (0 == rc) {
-                       JOM(8, "newinput(.,%i) OK\n", (int)index);
-               } else {
-                       SAM("ERROR: newinput(.,%i) returned %i\n", (int)index, rc);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUMAUDIO: {
-               JOM(8, "VIDIOC_ENUMAUDIO\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUMAUDOUT: {
-               struct v4l2_audioout v4l2_audioout;
-
-               JOM(8, "VIDIOC_ENUMAUDOUT\n");
-
-               if (copy_from_user(&v4l2_audioout, (void __user *)arg,
-                                       sizeof(struct v4l2_audioout))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (0 != v4l2_audioout.index) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               memset(&v4l2_audioout, 0, sizeof(struct v4l2_audioout));
-               v4l2_audioout.index = 0;
-               strcpy(&v4l2_audioout.name[0], "Soundtrack");
-
-               if (copy_to_user((void __user *)arg, &v4l2_audioout,
-                               sizeof(struct v4l2_audioout))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_QUERYCTRL: {
-               int i1;
-               struct v4l2_queryctrl v4l2_queryctrl;
-
-               JOM(8, "VIDIOC_QUERYCTRL\n");
-
-               if (0 != copy_from_user(&v4l2_queryctrl, (void __user *)arg,
-                               sizeof(struct v4l2_queryctrl))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               i1 = 0;
-               while (0xFFFFFFFF != easycap_control[i1].id) {
-                       if (easycap_control[i1].id == v4l2_queryctrl.id) {
-                               JOM(8, "VIDIOC_QUERYCTRL  %s=easycap_control[%i]"
-                                   ".name\n", &easycap_control[i1].name[0], i1);
-                               memcpy(&v4l2_queryctrl, &easycap_control[i1],
-                                      sizeof(struct v4l2_queryctrl));
-                               break;
-                       }
-                       i1++;
-               }
-               if (0xFFFFFFFF == easycap_control[i1].id) {
-                       JOM(8, "%i=index: exhausts controls\n", i1);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               if (copy_to_user((void __user *)arg, &v4l2_queryctrl,
-                               sizeof(struct v4l2_queryctrl))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_QUERYMENU: {
-               JOM(8, "VIDIOC_QUERYMENU unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_CTRL: {
-               struct v4l2_control *pv4l2_control;
-
-               JOM(8, "VIDIOC_G_CTRL\n");
-               pv4l2_control = memdup_user((void __user *)arg,
-                                           sizeof(struct v4l2_control));
-               if (IS_ERR(pv4l2_control)) {
-                       SAM("ERROR: copy from user failed\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return PTR_ERR(pv4l2_control);
-               }
-
-               switch (pv4l2_control->id) {
-               case V4L2_CID_BRIGHTNESS: {
-                       pv4l2_control->value = peasycap->brightness;
-                       JOM(8, "user enquires brightness: %i\n", pv4l2_control->value);
-                       break;
-               }
-               case V4L2_CID_CONTRAST: {
-                       pv4l2_control->value = peasycap->contrast;
-                       JOM(8, "user enquires contrast: %i\n", pv4l2_control->value);
-                       break;
-               }
-               case V4L2_CID_SATURATION: {
-                       pv4l2_control->value = peasycap->saturation;
-                       JOM(8, "user enquires saturation: %i\n", pv4l2_control->value);
-                       break;
-               }
-               case V4L2_CID_HUE: {
-                       pv4l2_control->value = peasycap->hue;
-                       JOM(8, "user enquires hue: %i\n", pv4l2_control->value);
-                       break;
-               }
-               case V4L2_CID_AUDIO_VOLUME: {
-                       pv4l2_control->value = peasycap->volume;
-                       JOM(8, "user enquires volume: %i\n", pv4l2_control->value);
-                       break;
-               }
-               case V4L2_CID_AUDIO_MUTE: {
-                       if (1 == peasycap->mute)
-                               pv4l2_control->value = true;
-                       else
-                               pv4l2_control->value = false;
-                       JOM(8, "user enquires mute: %i\n", pv4l2_control->value);
-                       break;
-               }
-               default: {
-                       SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
-                           pv4l2_control->id);
-                       kfree(pv4l2_control);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               }
-               if (copy_to_user((void __user *)arg, pv4l2_control,
-                               sizeof(struct v4l2_control))) {
-                       kfree(pv4l2_control);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               kfree(pv4l2_control);
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_CTRL: {
-               struct v4l2_control v4l2_control;
-
-               JOM(8, "VIDIOC_S_CTRL\n");
-
-               if (0 != copy_from_user(&v4l2_control, (void __user *)arg,
-                               sizeof(struct v4l2_control))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               switch (v4l2_control.id) {
-               case V4L2_CID_BRIGHTNESS: {
-                       JOM(8, "user requests brightness %i\n", v4l2_control.value);
-                       if (0 != adjust_brightness(peasycap, v4l2_control.value))
-                               ;
-                       break;
-               }
-               case V4L2_CID_CONTRAST: {
-                       JOM(8, "user requests contrast %i\n", v4l2_control.value);
-                       if (0 != adjust_contrast(peasycap, v4l2_control.value))
-                               ;
-                       break;
-               }
-               case V4L2_CID_SATURATION: {
-                       JOM(8, "user requests saturation %i\n", v4l2_control.value);
-                       if (0 != adjust_saturation(peasycap, v4l2_control.value))
-                               ;
-                       break;
-               }
-               case V4L2_CID_HUE: {
-                       JOM(8, "user requests hue %i\n", v4l2_control.value);
-                       if (0 != adjust_hue(peasycap, v4l2_control.value))
-                               ;
-                       break;
-               }
-               case V4L2_CID_AUDIO_VOLUME: {
-                       JOM(8, "user requests volume %i\n", v4l2_control.value);
-                       if (0 != adjust_volume(peasycap, v4l2_control.value))
-                               ;
-                       break;
-               }
-               case V4L2_CID_AUDIO_MUTE: {
-                       int mute;
-
-                       JOM(8, "user requests mute %i\n", v4l2_control.value);
-                       if (v4l2_control.value)
-                               mute = 1;
-                       else
-                               mute = 0;
-
-                       if (0 != adjust_mute(peasycap, mute))
-                               SAM("WARNING: failed to adjust mute to %i\n", mute);
-                       break;
-               }
-               default: {
-                       SAM("ERROR: unknown V4L2 control: 0x%08X=id\n",
-                           v4l2_control.id);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_EXT_CTRLS: {
-               JOM(8, "VIDIOC_S_EXT_CTRLS unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUM_FMT: {
-               u32 index;
-               struct v4l2_fmtdesc v4l2_fmtdesc;
-
-               JOM(8, "VIDIOC_ENUM_FMT\n");
-
-               if (0 != copy_from_user(&v4l2_fmtdesc, (void __user *)arg,
-                               sizeof(struct v4l2_fmtdesc))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               index = v4l2_fmtdesc.index;
-               memset(&v4l2_fmtdesc, 0, sizeof(struct v4l2_fmtdesc));
-
-               v4l2_fmtdesc.index = index;
-               v4l2_fmtdesc.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-               switch (index) {
-               case 0: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "uyvy");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_UYVY;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               case 1: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "yuy2");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_YUYV;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               case 2: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "rgb24");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB24;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               case 3: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "rgb32");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_RGB32;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               case 4: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "bgr24");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR24;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               case 5: {
-                       v4l2_fmtdesc.flags = 0;
-                       strcpy(&v4l2_fmtdesc.description[0], "bgr32");
-                       v4l2_fmtdesc.pixelformat = V4L2_PIX_FMT_BGR32;
-                       JOM(8, "%i=index: %s\n", index, &v4l2_fmtdesc.description[0]);
-                       break;
-               }
-               default: {
-                       JOM(8, "%i=index: exhausts formats\n", index);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               }
-               if (copy_to_user((void __user *)arg, &v4l2_fmtdesc,
-                               sizeof(struct v4l2_fmtdesc))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
-        *  THE RESPONSE TO VIDIOC_ENUM_FRAMESIZES MUST BE CONDITIONED ON THE
-        *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
-       */
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUM_FRAMESIZES: {
-               u32 index;
-               struct v4l2_frmsizeenum v4l2_frmsizeenum;
-
-               JOM(8, "VIDIOC_ENUM_FRAMESIZES\n");
-
-               if (0 != copy_from_user(&v4l2_frmsizeenum, (void __user *)arg,
-                               sizeof(struct v4l2_frmsizeenum))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               index = v4l2_frmsizeenum.index;
-
-               v4l2_frmsizeenum.type = (u32) V4L2_FRMSIZE_TYPE_DISCRETE;
-
-               if (peasycap->ntsc) {
-                       switch (index) {
-                       case 0: {
-                               v4l2_frmsizeenum.discrete.width = 640;
-                               v4l2_frmsizeenum.discrete.height = 480;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 1: {
-                               v4l2_frmsizeenum.discrete.width = 320;
-                               v4l2_frmsizeenum.discrete.height = 240;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 2: {
-                               v4l2_frmsizeenum.discrete.width = 720;
-                               v4l2_frmsizeenum.discrete.height = 480;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 3: {
-                               v4l2_frmsizeenum.discrete.width = 360;
-                               v4l2_frmsizeenum.discrete.height = 240;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       default: {
-                               JOM(8, "%i=index: exhausts framesizes\n", index);
-                               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                               return -EINVAL;
-                       }
-                       }
-               } else {
-                       switch (index) {
-                       case 0: {
-                               v4l2_frmsizeenum.discrete.width = 640;
-                               v4l2_frmsizeenum.discrete.height = 480;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 1: {
-                               v4l2_frmsizeenum.discrete.width = 320;
-                               v4l2_frmsizeenum.discrete.height = 240;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 2: {
-                               v4l2_frmsizeenum.discrete.width = 704;
-                               v4l2_frmsizeenum.discrete.height = 576;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 3: {
-                               v4l2_frmsizeenum.discrete.width = 720;
-                               v4l2_frmsizeenum.discrete.height = 576;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       case 4: {
-                               v4l2_frmsizeenum.discrete.width = 360;
-                               v4l2_frmsizeenum.discrete.height = 288;
-                               JOM(8, "%i=index: %ix%i\n", index,
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.width),
-                                   (int)(v4l2_frmsizeenum.
-                                         discrete.height));
-                               break;
-                       }
-                       default: {
-                               JOM(8, "%i=index: exhausts framesizes\n", index);
-                               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                               return -EINVAL;
-                       }
-                       }
-               }
-               if (copy_to_user((void __user *)arg, &v4l2_frmsizeenum,
-                               sizeof(struct v4l2_frmsizeenum))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
-        *  THE RESPONSE TO VIDIOC_ENUM_FRAMEINTERVALS MUST BE CONDITIONED ON THE
-        *  THE CURRENT STANDARD, BECAUSE THAT IS WHAT gstreamer EXPECTS.  BEWARE.
-       */
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_ENUM_FRAMEINTERVALS: {
-               u32 index;
-               int denominator;
-               struct v4l2_frmivalenum v4l2_frmivalenum;
-
-               JOM(8, "VIDIOC_ENUM_FRAMEINTERVALS\n");
-
-               if (peasycap->fps)
-                       denominator = peasycap->fps;
-               else {
-                       if (peasycap->ntsc)
-                               denominator = 30;
-                       else
-                               denominator = 25;
-               }
-
-               if (0 != copy_from_user(&v4l2_frmivalenum, (void __user *)arg,
-                               sizeof(struct v4l2_frmivalenum))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               index = v4l2_frmivalenum.index;
-
-               v4l2_frmivalenum.type = (u32) V4L2_FRMIVAL_TYPE_DISCRETE;
-
-               switch (index) {
-               case 0: {
-                       v4l2_frmivalenum.discrete.numerator = 1;
-                       v4l2_frmivalenum.discrete.denominator = denominator;
-                       JOM(8, "%i=index: %i/%i\n", index,
-                           (int)(v4l2_frmivalenum.discrete.numerator),
-                           (int)(v4l2_frmivalenum.discrete.denominator));
-                       break;
-               }
-               case 1: {
-                       v4l2_frmivalenum.discrete.numerator = 1;
-                       v4l2_frmivalenum.discrete.denominator = denominator/5;
-                       JOM(8, "%i=index: %i/%i\n", index,
-                           (int)(v4l2_frmivalenum.discrete.numerator),
-                           (int)(v4l2_frmivalenum.discrete.denominator));
-                       break;
-               }
-               default: {
-                       JOM(8, "%i=index: exhausts frameintervals\n", index);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               }
-               if (copy_to_user((void __user *)arg, &v4l2_frmivalenum,
-                                       sizeof(struct v4l2_frmivalenum))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_FMT: {
-               struct v4l2_format *pv4l2_format;
-               struct v4l2_pix_format *pv4l2_pix_format;
-
-               JOM(8, "VIDIOC_G_FMT\n");
-               pv4l2_format = kzalloc(sizeof(struct v4l2_format), GFP_KERNEL);
-               if (!pv4l2_format) {
-                       SAM("ERROR: out of memory\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ENOMEM;
-               }
-               pv4l2_pix_format = kzalloc(sizeof(struct v4l2_pix_format), GFP_KERNEL);
-               if (!pv4l2_pix_format) {
-                       SAM("ERROR: out of memory\n");
-                       kfree(pv4l2_format);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ENOMEM;
-               }
-               if (0 != copy_from_user(pv4l2_format, (void __user *)arg,
-                                       sizeof(struct v4l2_format))) {
-                       kfree(pv4l2_format);
-                       kfree(pv4l2_pix_format);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (pv4l2_format->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       kfree(pv4l2_format);
-                       kfree(pv4l2_pix_format);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-
-               memset(pv4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
-               pv4l2_format->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               memcpy(&pv4l2_format->fmt.pix,
-                      &easycap_format[peasycap->format_offset]
-                      .v4l2_format.fmt.pix, sizeof(struct v4l2_pix_format));
-               JOM(8, "user is told: %s\n",
-                   &easycap_format[peasycap->format_offset].name[0]);
-
-               if (copy_to_user((void __user *)arg, pv4l2_format,
-                                       sizeof(struct v4l2_format))) {
-                       kfree(pv4l2_format);
-                       kfree(pv4l2_pix_format);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               kfree(pv4l2_format);
-               kfree(pv4l2_pix_format);
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_TRY_FMT:
-       case VIDIOC_S_FMT: {
-               struct v4l2_format v4l2_format;
-               struct v4l2_pix_format v4l2_pix_format;
-               bool try;
-               int best_format;
-
-               if (VIDIOC_TRY_FMT == cmd) {
-                       JOM(8, "VIDIOC_TRY_FMT\n");
-                       try = true;
-               } else {
-                       JOM(8, "VIDIOC_S_FMT\n");
-                       try = false;
-               }
-
-               if (0 != copy_from_user(&v4l2_format, (void __user *)arg,
-                                       sizeof(struct v4l2_format))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               best_format = adjust_format(peasycap,
-                                       v4l2_format.fmt.pix.width,
-                                       v4l2_format.fmt.pix.height,
-                                       v4l2_format.fmt.pix.pixelformat,
-                                       v4l2_format.fmt.pix.field,
-                                       try);
-               if (0 > best_format) {
-                       if (-EBUSY == best_format) {
-                               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                               return -EBUSY;
-                       }
-                       JOM(8, "WARNING: adjust_format() returned %i\n", best_format);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ENOENT;
-               }
-/*...........................................................................*/
-               memset(&v4l2_pix_format, 0, sizeof(struct v4l2_pix_format));
-               v4l2_format.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-
-               memcpy(&(v4l2_format.fmt.pix),
-                       &(easycap_format[best_format].v4l2_format.fmt.pix),
-                       sizeof(v4l2_pix_format));
-               JOM(8, "user is told: %s\n", &easycap_format[best_format].name[0]);
-
-               if (copy_to_user((void __user *)arg, &v4l2_format,
-                                       sizeof(struct v4l2_format))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_CROPCAP: {
-               struct v4l2_cropcap v4l2_cropcap;
-
-               JOM(8, "VIDIOC_CROPCAP\n");
-
-               if (0 != copy_from_user(&v4l2_cropcap, (void __user *)arg,
-                                       sizeof(struct v4l2_cropcap))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
-                       JOM(8, "v4l2_cropcap.type != V4L2_BUF_TYPE_VIDEO_CAPTURE\n");
-
-               memset(&v4l2_cropcap, 0, sizeof(struct v4l2_cropcap));
-               v4l2_cropcap.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               v4l2_cropcap.bounds.left      = 0;
-               v4l2_cropcap.bounds.top       = 0;
-               v4l2_cropcap.bounds.width     = peasycap->width;
-               v4l2_cropcap.bounds.height    = peasycap->height;
-               v4l2_cropcap.defrect.left     = 0;
-               v4l2_cropcap.defrect.top      = 0;
-               v4l2_cropcap.defrect.width    = peasycap->width;
-               v4l2_cropcap.defrect.height   = peasycap->height;
-               v4l2_cropcap.pixelaspect.numerator = 1;
-               v4l2_cropcap.pixelaspect.denominator = 1;
-
-               JOM(8, "user is told: %ix%i\n", peasycap->width, peasycap->height);
-
-               if (copy_to_user((void __user *)arg, &v4l2_cropcap,
-                                       sizeof(struct v4l2_cropcap))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_CROP:
-       case VIDIOC_S_CROP: {
-               JOM(8, "VIDIOC_G_CROP|VIDIOC_S_CROP  unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_QUERYSTD: {
-               JOM(8, "VIDIOC_QUERYSTD: "
-                   "EasyCAP is incapable of detecting standard\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-               break;
-       }
-       /*-------------------------------------------------------------------*/
-       /*
-        *  THE MANIPULATIONS INVOLVING last0,last1,last2,last3
-        *  CONSTITUTE A WORKAROUND *  FOR WHAT APPEARS TO BE
-        *  A BUG IN 64-BIT mplayer.
-        *  NOT NEEDED, BUT HOPEFULLY HARMLESS, FOR 32-BIT mplayer.
-        */
-       /*------------------------------------------------------------------*/
-       case VIDIOC_ENUMSTD: {
-               int last0 = -1, last1 = -1, last2 = -1, last3 = -1;
-               struct v4l2_standard v4l2_standard;
-               u32 index;
-               struct easycap_standard const *peasycap_standard;
-
-               JOM(8, "VIDIOC_ENUMSTD\n");
-
-               if (0 != copy_from_user(&v4l2_standard, (void __user *)arg,
-                                       sizeof(struct v4l2_standard))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               index = v4l2_standard.index;
-
-               last3 = last2;
-               last2 = last1;
-               last1 = last0;
-               last0 = index;
-               if ((index == last3) && (index == last2) &&
-                   (index == last1) && (index == last0)) {
-                       index++;
-                       last3 = last2;
-                       last2 = last1;
-                       last1 = last0;
-                       last0 = index;
-               }
-
-               memset(&v4l2_standard, 0, sizeof(struct v4l2_standard));
-
-               peasycap_standard = &easycap_standard[0];
-               while (0xFFFF != peasycap_standard->mask) {
-                       if ((int)(peasycap_standard - &easycap_standard[0]) == index)
-                               break;
-                       peasycap_standard++;
-               }
-               if (0xFFFF == peasycap_standard->mask) {
-                       JOM(8, "%i=index: exhausts standards\n", index);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               JOM(8, "%i=index: %s\n", index,
-                   &(peasycap_standard->v4l2_standard.name[0]));
-               memcpy(&v4l2_standard, &(peasycap_standard->v4l2_standard),
-                      sizeof(struct v4l2_standard));
-
-               v4l2_standard.index = index;
-
-               if (copy_to_user((void __user *)arg, &v4l2_standard,
-                               sizeof(struct v4l2_standard))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_STD: {
-               v4l2_std_id std_id;
-               struct easycap_standard const *peasycap_standard;
-
-               JOM(8, "VIDIOC_G_STD\n");
-
-               if (0 > peasycap->standard_offset) {
-                       JOM(8, "%i=peasycap->standard_offset\n",
-                           peasycap->standard_offset);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EBUSY;
-               }
-
-               if (0 != copy_from_user(&std_id, (void __user *)arg,
-                                       sizeof(v4l2_std_id))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               peasycap_standard = &easycap_standard[peasycap->standard_offset];
-               std_id = peasycap_standard->v4l2_standard.id;
-
-               JOM(8, "user is told: %s\n",
-                   &peasycap_standard->v4l2_standard.name[0]);
-
-               if (copy_to_user((void __user *)arg, &std_id,
-                                       sizeof(v4l2_std_id))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_STD: {
-               v4l2_std_id std_id;
-               int rc;
-
-               JOM(8, "VIDIOC_S_STD\n");
-
-               if (0 != copy_from_user(&std_id, (void __user *)arg,
-                                       sizeof(v4l2_std_id))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               JOM(8, "User requests standard: 0x%08X%08X\n",
-                   (int)((std_id & (((v4l2_std_id)0xFFFFFFFF) << 32)) >> 32),
-                   (int)(std_id & ((v4l2_std_id)0xFFFFFFFF)));
-
-               rc = adjust_standard(peasycap, std_id);
-               if (0 > rc) {
-                       JOM(8, "WARNING: adjust_standard() returned %i\n", rc);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ENOENT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_REQBUFS: {
-               int nbuffers;
-               struct v4l2_requestbuffers v4l2_requestbuffers;
-
-               JOM(8, "VIDIOC_REQBUFS\n");
-
-               if (0 != copy_from_user(&v4l2_requestbuffers,
-                                       (void __user *)arg,
-                                       sizeof(struct v4l2_requestbuffers))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (v4l2_requestbuffers.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               if (v4l2_requestbuffers.memory != V4L2_MEMORY_MMAP) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               nbuffers = v4l2_requestbuffers.count;
-               JOM(8, "                   User requests %i buffers ...\n", nbuffers);
-               if (nbuffers < 2)
-                       nbuffers = 2;
-               if (nbuffers > FRAME_BUFFER_MANY)
-                       nbuffers = FRAME_BUFFER_MANY;
-               if (v4l2_requestbuffers.count == nbuffers) {
-                       JOM(8, "                   ... agree to  %i buffers\n",
-                           nbuffers);
-               } else {
-                       JOM(8, "                  ... insist on  %i buffers\n",
-                           nbuffers);
-                       v4l2_requestbuffers.count = nbuffers;
-               }
-               peasycap->frame_buffer_many = nbuffers;
-
-               if (copy_to_user((void __user *)arg, &v4l2_requestbuffers,
-                                       sizeof(struct v4l2_requestbuffers))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_QUERYBUF: {
-               u32 index;
-               struct v4l2_buffer v4l2_buffer;
-
-               JOM(8, "VIDIOC_QUERYBUF\n");
-
-               if (peasycap->video_eof) {
-                       JOM(8, "returning -EIO because  %i=video_eof\n",
-                           peasycap->video_eof);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EIO;
-               }
-
-               if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
-                                       sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               index = v4l2_buffer.index;
-               if (index < 0 || index >= peasycap->frame_buffer_many)
-                       return -EINVAL;
-               memset(&v4l2_buffer, 0, sizeof(struct v4l2_buffer));
-               v4l2_buffer.index = index;
-               v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               v4l2_buffer.bytesused = peasycap->frame_buffer_used;
-               v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED |
-                                       peasycap->done[index] |
-                                       peasycap->queued[index];
-               v4l2_buffer.field = V4L2_FIELD_NONE;
-               v4l2_buffer.memory = V4L2_MEMORY_MMAP;
-               v4l2_buffer.m.offset = index * FRAME_BUFFER_SIZE;
-               v4l2_buffer.length = FRAME_BUFFER_SIZE;
-
-               JOM(16, "  %10i=index\n", v4l2_buffer.index);
-               JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
-               JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
-               JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
-               JOM(16, "  %10i=field\n", v4l2_buffer.field);
-               JOM(16, "  %10li=timestamp.tv_usec\n",
-                   (long)v4l2_buffer.timestamp.tv_usec);
-               JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
-               JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
-               JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
-               JOM(16, "  %10i=length\n", v4l2_buffer.length);
-
-               if (copy_to_user((void __user *)arg, &v4l2_buffer,
-                                       sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_QBUF: {
-               struct v4l2_buffer v4l2_buffer;
-
-               JOM(8, "VIDIOC_QBUF\n");
-
-               if (0 != copy_from_user(&v4l2_buffer, (void __user *)arg,
-                                       sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               if (v4l2_buffer.memory != V4L2_MEMORY_MMAP) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               if (v4l2_buffer.index < 0 ||
-                   v4l2_buffer.index >= peasycap->frame_buffer_many) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_QUEUED;
-
-               peasycap->done[v4l2_buffer.index]   = 0;
-               peasycap->queued[v4l2_buffer.index] = V4L2_BUF_FLAG_QUEUED;
-
-               if (copy_to_user((void __user *)arg, &v4l2_buffer,
-                                       sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               JOM(8, ".....   user queueing frame buffer %i\n",
-                   (int)v4l2_buffer.index);
-
-               peasycap->frame_lock = 0;
-
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_DQBUF:
-       {
-               struct timeval timeval, timeval2;
-               int i, j;
-               struct v4l2_buffer v4l2_buffer;
-               int rcdq;
-               u16 input;
-
-               JOM(8, "VIDIOC_DQBUF\n");
-
-               if ((peasycap->video_idle) || (peasycap->video_eof)) {
-                       JOM(8, "returning -EIO because  "
-                           "%i=video_idle  %i=video_eof\n",
-                           peasycap->video_idle, peasycap->video_eof);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EIO;
-               }
-
-               if (copy_from_user(&v4l2_buffer, (void __user *)arg,
-                                 sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               if (v4l2_buffer.type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-
-               if (peasycap->offerfields) {
-                       /*---------------------------------------------------*/
-                       /*
-                        *  IN ITS 50 "fps" MODE tvtime SEEMS ALWAYS TO REQUEST
-                        *  V4L2_FIELD_BOTTOM
-                        */
-                       /*---------------------------------------------------*/
-                       if (V4L2_FIELD_TOP == v4l2_buffer.field)
-                               JOM(8, "user wants V4L2_FIELD_TOP\n");
-                       else if (V4L2_FIELD_BOTTOM == v4l2_buffer.field)
-                               JOM(8, "user wants V4L2_FIELD_BOTTOM\n");
-                       else if (V4L2_FIELD_ANY == v4l2_buffer.field)
-                               JOM(8, "user wants V4L2_FIELD_ANY\n");
-                       else
-                               JOM(8, "user wants V4L2_FIELD_...UNKNOWN: %i\n",
-                                   v4l2_buffer.field);
-               }
-
-               if (!peasycap->video_isoc_streaming) {
-                       JOM(16, "returning -EIO because video urbs not streaming\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EIO;
-               }
-       /*-------------------------------------------------------------------*/
-       /*
-        *  IF THE USER HAS PREVIOUSLY CALLED easycap_poll(),
-        *  AS DETERMINED BY FINDING
-        *  THE FLAG peasycap->polled SET, THERE MUST BE
-        *  NO FURTHER WAIT HERE.  IN THIS
-        *  CASE, JUST CHOOSE THE FRAME INDICATED BY peasycap->frame_read
-        */
-       /*-------------------------------------------------------------------*/
-
-               if (!peasycap->polled) {
-                       do {
-                               rcdq = easycap_video_dqbuf(peasycap, 0);
-                               if (-EIO == rcdq) {
-                                       JOM(8, "returning -EIO because "
-                                           "dqbuf() returned -EIO\n");
-                                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                                       return -EIO;
-                               }
-                       } while (0 != rcdq);
-               } else {
-                       if (peasycap->video_eof) {
-                               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                               return -EIO;
-                       }
-               }
-               if (V4L2_BUF_FLAG_DONE != peasycap->done[peasycap->frame_read]) {
-                       JOM(8, "V4L2_BUF_FLAG_DONE != 0x%08X\n",
-                           peasycap->done[peasycap->frame_read]);
-               }
-               peasycap->polled = 0;
-
-               if (!(peasycap->isequence % 10)) {
-                       for (i = 0; i < 179; i++)
-                               peasycap->merit[i] = peasycap->merit[i+1];
-                       peasycap->merit[179] = merit_saa(peasycap->pusb_device);
-                       j = 0;
-                       for (i = 0; i < 180; i++)
-                               j += peasycap->merit[i];
-                       if (90 < j) {
-                               SAM("easycap driver shutting down "
-                                   "on condition blue\n");
-                               peasycap->video_eof = 1;
-                               peasycap->audio_eof = 1;
-                       }
-               }
-
-               v4l2_buffer.index = peasycap->frame_read;
-               v4l2_buffer.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-               v4l2_buffer.bytesused = peasycap->frame_buffer_used;
-               v4l2_buffer.flags = V4L2_BUF_FLAG_MAPPED | V4L2_BUF_FLAG_DONE;
-               if (peasycap->offerfields)
-                       v4l2_buffer.field = V4L2_FIELD_BOTTOM;
-               else
-                       v4l2_buffer.field = V4L2_FIELD_NONE;
-               do_gettimeofday(&timeval);
-               timeval2 = timeval;
-
-               v4l2_buffer.timestamp = timeval2;
-               v4l2_buffer.sequence = peasycap->isequence++;
-               v4l2_buffer.memory = V4L2_MEMORY_MMAP;
-               v4l2_buffer.m.offset = v4l2_buffer.index * FRAME_BUFFER_SIZE;
-               v4l2_buffer.length = FRAME_BUFFER_SIZE;
-
-               JOM(16, "  %10i=index\n", v4l2_buffer.index);
-               JOM(16, "  0x%08X=type\n", v4l2_buffer.type);
-               JOM(16, "  %10i=bytesused\n", v4l2_buffer.bytesused);
-               JOM(16, "  0x%08X=flags\n", v4l2_buffer.flags);
-               JOM(16, "  %10i=field\n", v4l2_buffer.field);
-               JOM(16, "  %10li=timestamp.tv_sec\n",
-                   (long)v4l2_buffer.timestamp.tv_sec);
-               JOM(16, "  %10li=timestamp.tv_usec\n",
-                   (long)v4l2_buffer.timestamp.tv_usec);
-               JOM(16, "  %10i=sequence\n", v4l2_buffer.sequence);
-               JOM(16, "  0x%08X=memory\n", v4l2_buffer.memory);
-               JOM(16, "  %10i=m.offset\n", v4l2_buffer.m.offset);
-               JOM(16, "  %10i=length\n", v4l2_buffer.length);
-
-               if (copy_to_user((void __user *)arg, &v4l2_buffer,
-                                       sizeof(struct v4l2_buffer))) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               input = peasycap->frame_buffer[peasycap->frame_read][0].input;
-               if (0x08 & input) {
-                       JOM(8, "user is offered frame buffer %i, input %i\n",
-                           peasycap->frame_read, (0x07 & input));
-               } else {
-                       JOM(8, "user is offered frame buffer %i\n",
-                           peasycap->frame_read);
-               }
-               peasycap->frame_lock = 1;
-               JOM(8, "%i=peasycap->frame_fill\n", peasycap->frame_fill);
-               if (peasycap->frame_read == peasycap->frame_fill) {
-                       if (peasycap->frame_lock) {
-                               JOM(8, "WORRY:  filling frame buffer "
-                                   "while offered to user\n");
-                       }
-               }
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_STREAMON: {
-               int i;
-
-               JOM(8, "VIDIOC_STREAMON\n");
-
-               peasycap->isequence = 0;
-               for (i = 0; i < 180; i++)
-                       peasycap->merit[i] = 0;
-               if (!peasycap->pusb_device) {
-                       SAM("ERROR: peasycap->pusb_device is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               easycap_video_submit_urbs(peasycap);
-               peasycap->video_idle = 0;
-               peasycap->audio_idle = 0;
-               peasycap->video_eof = 0;
-               peasycap->audio_eof = 0;
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_STREAMOFF: {
-               JOM(8, "VIDIOC_STREAMOFF\n");
-
-               if (!peasycap->pusb_device) {
-                       SAM("ERROR: peasycap->pusb_device is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-
-               peasycap->video_idle = 1;
-               peasycap->audio_idle = 1;
-/*---------------------------------------------------------------------------*/
-/*
- *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO THE STREAMOFF COMMAND
- *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
- */
-/*---------------------------------------------------------------------------*/
-               JOM(8, "calling wake_up on wq_video and wq_audio\n");
-               wake_up_interruptible(&(peasycap->wq_video));
-               if (peasycap->psubstream)
-                       snd_pcm_period_elapsed(peasycap->psubstream);
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_PARM: {
-               struct v4l2_streamparm *pv4l2_streamparm;
-
-               JOM(8, "VIDIOC_G_PARM\n");
-               pv4l2_streamparm = memdup_user((void __user *)arg,
-                                              sizeof(struct v4l2_streamparm));
-               if (IS_ERR(pv4l2_streamparm)) {
-                       SAM("ERROR: copy from user failed\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return PTR_ERR(pv4l2_streamparm);
-               }
-
-               if (pv4l2_streamparm->type != V4L2_BUF_TYPE_VIDEO_CAPTURE) {
-                       kfree(pv4l2_streamparm);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EINVAL;
-               }
-               pv4l2_streamparm->parm.capture.capability = 0;
-               pv4l2_streamparm->parm.capture.capturemode = 0;
-               pv4l2_streamparm->parm.capture.timeperframe.numerator = 1;
-
-               if (peasycap->fps) {
-                       pv4l2_streamparm->parm.capture.timeperframe.
-                       denominator = peasycap->fps;
-               } else {
-                       if (peasycap->ntsc) {
-                               pv4l2_streamparm->parm.capture.timeperframe.
-                               denominator = 30;
-                       } else {
-                               pv4l2_streamparm->parm.capture.timeperframe.
-                               denominator = 25;
-                       }
-               }
-
-               pv4l2_streamparm->parm.capture.readbuffers =
-                       peasycap->frame_buffer_many;
-               pv4l2_streamparm->parm.capture.extendedmode = 0;
-               if (copy_to_user((void __user *)arg,
-                               pv4l2_streamparm,
-                               sizeof(struct v4l2_streamparm))) {
-                       kfree(pv4l2_streamparm);
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -EFAULT;
-               }
-               kfree(pv4l2_streamparm);
-               break;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_PARM: {
-               JOM(8, "VIDIOC_S_PARM unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_AUDIO: {
-               JOM(8, "VIDIOC_G_AUDIO unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_AUDIO: {
-               JOM(8, "VIDIOC_S_AUDIO unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_S_TUNER: {
-               JOM(8, "VIDIOC_S_TUNER unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_FBUF:
-       case VIDIOC_S_FBUF:
-       case VIDIOC_OVERLAY: {
-               JOM(8, "VIDIOC_G_FBUF|VIDIOC_S_FBUF|VIDIOC_OVERLAY unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       case VIDIOC_G_TUNER: {
-               JOM(8, "VIDIOC_G_TUNER unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-       case VIDIOC_G_FREQUENCY:
-       case VIDIOC_S_FREQUENCY: {
-               JOM(8, "VIDIOC_G_FREQUENCY|VIDIOC_S_FREQUENCY unsupported\n");
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -EINVAL;
-       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       default: {
-               JOM(8, "ERROR: unrecognized V4L2 IOCTL command: 0x%08X\n", cmd);
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               return -ENOIOCTLCMD;
-       }
-       }
-       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-       JOM(4, "unlocked easycapdc60_dongle[%i].mutex_video\n", kd);
-       return 0;
-}
-/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_low.c b/drivers/staging/media/easycap/easycap_low.c
deleted file mode 100644 (file)
index 0380bab..0000000
+++ /dev/null
@@ -1,968 +0,0 @@
-/*****************************************************************************
-*                                                                            *
-*                                                                            *
-*  easycap_low.c                                                             *
-*                                                                            *
-*                                                                            *
-*****************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-/*
- *  ACKNOWLEGEMENTS AND REFERENCES
- *  ------------------------------
- *  This driver makes use of register information contained in the Syntek
- *  Semicon DC-1125 driver hosted at
- *               http://sourceforge.net/projects/syntekdriver/.
- *  Particularly useful has been a patch to the latter driver provided by
- *  Ivor Hewitt in January 2009.  The NTSC implementation is taken from the
- *  work of Ben Trask.
-*/
-/****************************************************************************/
-
-#include "easycap.h"
-
-
-#define GET(X, Y, Z) do { \
-       int __rc; \
-       *(Z) = (u16)0; \
-       __rc = regget(X, Y, Z, sizeof(u8)); \
-       if (0 > __rc) { \
-               JOT(8, ":-(%i\n", __LINE__);  return __rc; \
-       } \
-} while (0)
-
-#define SET(X, Y, Z) do { \
-       int __rc; \
-       __rc = regset(X, Y, Z); \
-       if (0 > __rc) { \
-               JOT(8, ":-(%i\n", __LINE__);  return __rc; \
-       } \
-} while (0)
-
-/*--------------------------------------------------------------------------*/
-static const struct stk1160config {
-       u16 reg;
-       u16 set;
-} stk1160configPAL[] = {
-               {0x000, 0x0098},
-               {0x002, 0x0093},
-
-               {0x001, 0x0003},
-               {0x003, 0x0080},
-               {0x00D, 0x0000},
-               {0x00F, 0x0002},
-               {0x018, 0x0010},
-               {0x019, 0x0000},
-               {0x01A, 0x0014},
-               {0x01B, 0x000E},
-               {0x01C, 0x0046},
-
-               {0x100, 0x0033},
-               {0x103, 0x0000},
-               {0x104, 0x0000},
-               {0x105, 0x0000},
-               {0x106, 0x0000},
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
- *  RESOLUTION 640x480
-*/
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-               {0x110, 0x0008},
-               {0x111, 0x0000},
-               {0x112, 0x0020},
-               {0x113, 0x0000},
-               {0x114, 0x0508},
-               {0x115, 0x0005},
-               {0x116, 0x0110},
-               {0x117, 0x0001},
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-               {0x202, 0x000F},
-               {0x203, 0x004A},
-               {0x2FF, 0x0000},
-
-               {0xFFF, 0xFFFF}
-};
-/*--------------------------------------------------------------------------*/
-static const struct stk1160config stk1160configNTSC[] = {
-               {0x000, 0x0098},
-               {0x002, 0x0093},
-
-               {0x001, 0x0003},
-               {0x003, 0x0080},
-               {0x00D, 0x0000},
-               {0x00F, 0x0002},
-               {0x018, 0x0010},
-               {0x019, 0x0000},
-               {0x01A, 0x0014},
-               {0x01B, 0x000E},
-               {0x01C, 0x0046},
-
-               {0x100, 0x0033},
-               {0x103, 0x0000},
-               {0x104, 0x0000},
-               {0x105, 0x0000},
-               {0x106, 0x0000},
-
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-/*
- *  RESOLUTION 640x480
-*/
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-               {0x110, 0x0008},
-               {0x111, 0x0000},
-               {0x112, 0x0003},
-               {0x113, 0x0000},
-               {0x114, 0x0508},
-               {0x115, 0x0005},
-               {0x116, 0x00F3},
-               {0x117, 0x0000},
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-
-               {0x202, 0x000F},
-               {0x203, 0x004A},
-               {0x2FF, 0x0000},
-
-               {0xFFF, 0xFFFF}
-};
-/*--------------------------------------------------------------------------*/
-static const struct saa7113config {
-       u8 reg;
-       u8 set;
-} saa7113configPAL[] = {
-               {0x01, 0x08},
-               {0x02, 0x80},
-               {0x03, 0x33},
-               {0x04, 0x00},
-               {0x05, 0x00},
-               {0x06, 0xE9},
-               {0x07, 0x0D},
-               {0x08, 0x38},
-               {0x09, 0x00},
-               {0x0A, SAA_0A_DEFAULT},
-               {0x0B, SAA_0B_DEFAULT},
-               {0x0C, SAA_0C_DEFAULT},
-               {0x0D, SAA_0D_DEFAULT},
-               {0x0E, 0x01},
-               {0x0F, 0x36},
-               {0x10, 0x00},
-               {0x11, 0x0C},
-               {0x12, 0xE7},
-               {0x13, 0x00},
-               {0x15, 0x00},
-               {0x16, 0x00},
-               {0x40, 0x02},
-               {0x41, 0xFF},
-               {0x42, 0xFF},
-               {0x43, 0xFF},
-               {0x44, 0xFF},
-               {0x45, 0xFF},
-               {0x46, 0xFF},
-               {0x47, 0xFF},
-               {0x48, 0xFF},
-               {0x49, 0xFF},
-               {0x4A, 0xFF},
-               {0x4B, 0xFF},
-               {0x4C, 0xFF},
-               {0x4D, 0xFF},
-               {0x4E, 0xFF},
-               {0x4F, 0xFF},
-               {0x50, 0xFF},
-               {0x51, 0xFF},
-               {0x52, 0xFF},
-               {0x53, 0xFF},
-               {0x54, 0xFF},
-               {0x55, 0xFF},
-               {0x56, 0xFF},
-               {0x57, 0xFF},
-               {0x58, 0x40},
-               {0x59, 0x54},
-               {0x5A, 0x07},
-               {0x5B, 0x83},
-
-               {0xFF, 0xFF}
-};
-/*--------------------------------------------------------------------------*/
-static const struct saa7113config saa7113configNTSC[] = {
-               {0x01, 0x08},
-               {0x02, 0x80},
-               {0x03, 0x33},
-               {0x04, 0x00},
-               {0x05, 0x00},
-               {0x06, 0xE9},
-               {0x07, 0x0D},
-               {0x08, 0x78},
-               {0x09, 0x00},
-               {0x0A, SAA_0A_DEFAULT},
-               {0x0B, SAA_0B_DEFAULT},
-               {0x0C, SAA_0C_DEFAULT},
-               {0x0D, SAA_0D_DEFAULT},
-               {0x0E, 0x01},
-               {0x0F, 0x36},
-               {0x10, 0x00},
-               {0x11, 0x0C},
-               {0x12, 0xE7},
-               {0x13, 0x00},
-               {0x15, 0x00},
-               {0x16, 0x00},
-               {0x40, 0x82},
-               {0x41, 0xFF},
-               {0x42, 0xFF},
-               {0x43, 0xFF},
-               {0x44, 0xFF},
-               {0x45, 0xFF},
-               {0x46, 0xFF},
-               {0x47, 0xFF},
-               {0x48, 0xFF},
-               {0x49, 0xFF},
-               {0x4A, 0xFF},
-               {0x4B, 0xFF},
-               {0x4C, 0xFF},
-               {0x4D, 0xFF},
-               {0x4E, 0xFF},
-               {0x4F, 0xFF},
-               {0x50, 0xFF},
-               {0x51, 0xFF},
-               {0x52, 0xFF},
-               {0x53, 0xFF},
-               {0x54, 0xFF},
-               {0x55, 0xFF},
-               {0x56, 0xFF},
-               {0x57, 0xFF},
-               {0x58, 0x40},
-               {0x59, 0x54},
-               {0x5A, 0x0A},
-               {0x5B, 0x83},
-
-               {0xFF, 0xFF}
-};
-
-static int regget(struct usb_device *pusb_device,
-               u16 index, void *reg, int reg_size)
-{
-       int rc;
-
-       if (!pusb_device)
-               return -ENODEV;
-
-       rc = usb_control_msg(pusb_device, usb_rcvctrlpipe(pusb_device, 0),
-                       0x00,
-                       (USB_DIR_IN | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
-                       0x00,
-                       index, reg, reg_size, 50000);
-
-       return rc;
-}
-
-static int regset(struct usb_device *pusb_device, u16 index, u16 value)
-{
-       int rc;
-
-       if (!pusb_device)
-               return -ENODEV;
-
-       rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
-                       0x01,
-                       (USB_DIR_OUT | USB_TYPE_VENDOR | USB_RECIP_DEVICE),
-                       value, index, NULL, 0, 500);
-
-       if (rc < 0)
-               return rc;
-
-       if (easycap_readback) {
-               u16 igot = 0;
-               rc = regget(pusb_device, index, &igot, sizeof(igot));
-               igot = 0xFF & igot;
-               switch (index) {
-               case 0x000:
-               case 0x500:
-               case 0x502:
-               case 0x503:
-               case 0x504:
-               case 0x506:
-               case 0x507:
-                       break;
-
-               case 0x204:
-               case 0x205:
-               case 0x350:
-               case 0x351:
-                       if (igot)
-                               JOT(8, "unexpected 0x%02X "
-                                       "for STK register 0x%03X\n",
-                                       igot, index);
-                       break;
-
-               default:
-                       if ((0xFF & value) != igot)
-                               JOT(8, "unexpected 0x%02X != 0x%02X "
-                                       "for STK register 0x%03X\n",
-                                               igot, value, index);
-                       break;
-               }
-       }
-
-       return rc;
-}
-/*--------------------------------------------------------------------------*/
-/*
- *  FUNCTION wait_i2c() RETURNS 0 ON SUCCESS
-*/
-/*--------------------------------------------------------------------------*/
-static int wait_i2c(struct usb_device *p)
-{
-       u16 get0;
-       u8 igot;
-       const int max = 2;
-       int k;
-
-       if (!p)
-               return -ENODEV;
-
-       for (k = 0;  k < max;  k++) {
-               GET(p, 0x0201, &igot);  get0 = igot;
-               switch (get0) {
-               case 0x04:
-               case 0x01:
-                       return 0;
-               case 0x00:
-                       msleep(20);
-                       continue;
-               default:
-                       return get0 - 1;
-               }
-       }
-       return -1;
-}
-
-/****************************************************************************/
-int write_saa(struct usb_device *p, u16 reg0, u16 set0)
-{
-       if (!p)
-               return -ENODEV;
-       SET(p, 0x200, 0x00);
-       SET(p, 0x204, reg0);
-       SET(p, 0x205, set0);
-       SET(p, 0x200, 0x01);
-       return wait_i2c(p);
-}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  REGISTER 500:  SETTING VALUE TO 0x008B READS FROM VT1612A (?)
- *  REGISTER 500:  SETTING VALUE TO 0x008C WRITES TO  VT1612A
- *  REGISTER 502:  LEAST SIGNIFICANT BYTE OF VALUE TO SET
- *  REGISTER 503:  MOST SIGNIFICANT BYTE OF VALUE TO SET
- *  REGISTER 504:  TARGET ADDRESS ON VT1612A
- */
-/*--------------------------------------------------------------------------*/
-static int write_vt(struct usb_device *p, u16 reg0, u16 set0)
-{
-       u8 igot;
-       u16 got502, got503;
-       u16 set502, set503;
-
-       if (!p)
-               return -ENODEV;
-       SET(p, 0x0504, reg0);
-       SET(p, 0x0500, 0x008B);
-
-       GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
-       GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
-
-       JOT(16, "write_vt(., 0x%04X, 0x%04X): was 0x%04X\n",
-                               reg0, set0, ((got503 << 8) | got502));
-
-       set502 =  (0x00FF & set0);
-       set503 = ((0xFF00 & set0) >> 8);
-
-       SET(p, 0x0504, reg0);
-       SET(p, 0x0502, set502);
-       SET(p, 0x0503, set503);
-       SET(p, 0x0500, 0x008C);
-
-       return 0;
-}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  REGISTER 500:  SETTING VALUE TO 0x008B READS FROM VT1612A (?)
- *  REGISTER 500:  SETTING VALUE TO 0x008C WRITES TO  VT1612A
- *  REGISTER 502:  LEAST SIGNIFICANT BYTE OF VALUE TO GET
- *  REGISTER 503:  MOST SIGNIFICANT BYTE OF VALUE TO GET
- *  REGISTER 504:  TARGET ADDRESS ON VT1612A
- */
-/*--------------------------------------------------------------------------*/
-static int read_vt(struct usb_device *p, u16 reg0)
-{
-       u8 igot;
-       u16 got502, got503;
-
-       if (!p)
-               return -ENODEV;
-       SET(p, 0x0504, reg0);
-       SET(p, 0x0500, 0x008B);
-
-       GET(p, 0x0502, &igot);  got502 = (0xFF & igot);
-       GET(p, 0x0503, &igot);  got503 = (0xFF & igot);
-
-       JOT(16, "read_vt(., 0x%04X): has 0x%04X\n",
-                       reg0, ((got503 << 8) | got502));
-
-       return (got503 << 8) | got502;
-}
-/****************************************************************************/
-/*--------------------------------------------------------------------------*/
-/*
- *  THESE APPEAR TO HAVE NO EFFECT ON EITHER VIDEO OR AUDIO.
- */
-/*--------------------------------------------------------------------------*/
-static int write_300(struct usb_device *p)
-{
-       if (!p)
-               return -ENODEV;
-       SET(p, 0x300, 0x0012);
-       SET(p, 0x350, 0x002D);
-       SET(p, 0x351, 0x0001);
-       SET(p, 0x352, 0x0000);
-       SET(p, 0x353, 0x0000);
-       SET(p, 0x300, 0x0080);
-       return 0;
-}
-/****************************************************************************/
-/****************************************************************************/
-int setup_stk(struct usb_device *p, bool ntsc)
-{
-       int i;
-       const struct stk1160config *cfg;
-       if (!p)
-               return -ENODEV;
-       cfg = (ntsc) ? stk1160configNTSC : stk1160configPAL;
-       for (i = 0; cfg[i].reg != 0xFFF; i++)
-               SET(p, cfg[i].reg, cfg[i].set);
-
-       write_300(p);
-
-       return 0;
-}
-/****************************************************************************/
-int setup_saa(struct usb_device *p, bool ntsc)
-{
-       int i, rc;
-       const struct saa7113config *cfg;
-       if (!p)
-               return -ENODEV;
-       cfg = (ntsc) ?  saa7113configNTSC : saa7113configPAL;
-       for (i = 0; cfg[i].reg != 0xFF; i++) {
-               rc = write_saa(p, cfg[i].reg, cfg[i].set);
-               if (rc)
-                       dev_err(&p->dev,
-                               "Failed to set SAA register %d", cfg[i].reg);
-       }
-       return 0;
-}
-/****************************************************************************/
-int merit_saa(struct usb_device *p)
-{
-       int rc;
-
-       if (!p)
-               return -ENODEV;
-       rc = read_saa(p, 0x1F);
-       return ((0 > rc) || (0x02 & rc)) ? 1 : 0;
-}
-/****************************************************************************/
-int ready_saa(struct usb_device *p)
-{
-       int j, rc, rate;
-       const int max = 5, marktime = PATIENCE/5;
-/*--------------------------------------------------------------------------*/
-/*
- *   RETURNS    0     FOR INTERLACED       50 Hz
- *              1     FOR NON-INTERLACED   50 Hz
- *              2     FOR INTERLACED       60 Hz
- *              3     FOR NON-INTERLACED   60 Hz
-*/
-/*--------------------------------------------------------------------------*/
-       if (!p)
-               return -ENODEV;
-       j = 0;
-       while (max > j) {
-               rc = read_saa(p, 0x1F);
-               if (0 <= rc) {
-                       if (0 == (0x40 & rc))
-                               break;
-                       if (1 == (0x01 & rc))
-                               break;
-               }
-               msleep(marktime);
-               j++;
-       }
-
-       if (max == j)
-               return -1;
-
-       if (0x20 & rc) {
-               rate = 2;
-               JOT(8, "hardware detects 60 Hz\n");
-       } else {
-               rate = 0;
-               JOT(8, "hardware detects 50 Hz\n");
-       }
-       if (0x80 & rc)
-               JOT(8, "hardware detects interlacing\n");
-       else {
-               rate++;
-               JOT(8, "hardware detects no interlacing\n");
-       }
-       return 0;
-}
-/****************************************************************************/
-int read_saa(struct usb_device *p, u16 reg0)
-{
-       u8 igot;
-
-       if (!p)
-               return -ENODEV;
-       SET(p, 0x208, reg0);
-       SET(p, 0x200, 0x20);
-       if (0 != wait_i2c(p))
-               return -1;
-       igot = 0;
-       GET(p, 0x0209, &igot);
-       return igot;
-}
-/****************************************************************************/
-static int read_stk(struct usb_device *p, u32 reg0)
-{
-       u8 igot;
-
-       if (!p)
-               return -ENODEV;
-       igot = 0;
-       GET(p, reg0, &igot);
-       return igot;
-}
-int select_input(struct usb_device *p, int input, int mode)
-{
-       int ir;
-
-       if (!p)
-               return -ENODEV;
-       stop_100(p);
-       switch (input) {
-       case 0:
-       case 1: {
-               if (0 != write_saa(p, 0x02, 0x80))
-                       SAY("ERROR: failed to set SAA register 0x02 "
-                                               "for input %i\n", input);
-
-               SET(p, 0x0000, 0x0098);
-               SET(p, 0x0002, 0x0078);
-               break;
-       }
-       case 2: {
-               if (0 != write_saa(p, 0x02, 0x80))
-                       SAY("ERROR: failed to set SAA register 0x02 "
-                                               "for input %i\n", input);
-
-               SET(p, 0x0000, 0x0090);
-               SET(p, 0x0002, 0x0078);
-               break;
-       }
-       case 3: {
-               if (0 != write_saa(p, 0x02, 0x80))
-                       SAY("ERROR: failed to set SAA register 0x02 "
-                                       " for input %i\n", input);
-
-               SET(p, 0x0000, 0x0088);
-               SET(p, 0x0002, 0x0078);
-               break;
-       }
-       case 4: {
-               if (0 != write_saa(p, 0x02, 0x80)) {
-                       SAY("ERROR: failed to set SAA register 0x02 "
-                                               "for input %i\n", input);
-               }
-               SET(p, 0x0000, 0x0080);
-               SET(p, 0x0002, 0x0078);
-               break;
-       }
-       case 5: {
-               if (9 != mode)
-                       mode = 7;
-               switch (mode) {
-               case 7: {
-                       if (0 != write_saa(p, 0x02, 0x87))
-                               SAY("ERROR: failed to set SAA register 0x02 "
-                                               "for input %i\n", input);
-
-                       if (0 != write_saa(p, 0x05, 0xFF))
-                               SAY("ERROR: failed to set SAA register 0x05 "
-                                               "for input %i\n", input);
-
-                       break;
-               }
-               case 9: {
-                       if (0 != write_saa(p, 0x02, 0x89))
-                               SAY("ERROR: failed to set SAA register 0x02 "
-                                               "for input %i\n", input);
-
-                       if (0 != write_saa(p, 0x05, 0x00))
-                               SAY("ERROR: failed to set SAA register 0x05 "
-                                               "for input %i\n", input);
-
-                       break;
-               }
-               default:
-                       SAY("MISTAKE:  bad mode: %i\n", mode);
-                       return -1;
-               }
-
-               if (0 != write_saa(p, 0x04, 0x00))
-                       SAY("ERROR: failed to set SAA register 0x04 "
-                                       "for input %i\n", input);
-
-               if (0 != write_saa(p, 0x09, 0x80))
-                       SAY("ERROR: failed to set SAA register 0x09 "
-                                               "for input %i\n", input);
-
-               SET(p, 0x0002, 0x0093);
-               break;
-       }
-       default:
-               SAY("ERROR:  bad input: %i\n", input);
-               return -1;
-       }
-
-       ir = read_stk(p, 0x00);
-       JOT(8, "STK register 0x00 has 0x%02X\n", ir);
-       ir = read_saa(p, 0x02);
-       JOT(8, "SAA register 0x02 has 0x%02X\n", ir);
-
-       start_100(p);
-
-       return 0;
-}
-/****************************************************************************/
-int set_resolution(struct usb_device *p,
-                  u16 set0, u16 set1, u16 set2, u16 set3)
-{
-       u16 u0x0111, u0x0113, u0x0115, u0x0117;
-
-       if (!p)
-               return -ENODEV;
-       u0x0111 = ((0xFF00 & set0) >> 8);
-       u0x0113 = ((0xFF00 & set1) >> 8);
-       u0x0115 = ((0xFF00 & set2) >> 8);
-       u0x0117 = ((0xFF00 & set3) >> 8);
-
-       SET(p, 0x0110, (0x00FF & set0));
-       SET(p, 0x0111, u0x0111);
-       SET(p, 0x0112, (0x00FF & set1));
-       SET(p, 0x0113, u0x0113);
-       SET(p, 0x0114, (0x00FF & set2));
-       SET(p, 0x0115, u0x0115);
-       SET(p, 0x0116, (0x00FF & set3));
-       SET(p, 0x0117, u0x0117);
-
-       return 0;
-}
-/****************************************************************************/
-int start_100(struct usb_device *p)
-{
-       u16 get116, get117, get0;
-       u8 igot116, igot117, igot;
-
-       if (!p)
-               return -ENODEV;
-       GET(p, 0x0116, &igot116);
-       get116 = igot116;
-       GET(p, 0x0117, &igot117);
-       get117 = igot117;
-       SET(p, 0x0116, 0x0000);
-       SET(p, 0x0117, 0x0000);
-
-       GET(p, 0x0100, &igot);
-       get0 = igot;
-       SET(p, 0x0100, (0x80 | get0));
-
-       SET(p, 0x0116, get116);
-       SET(p, 0x0117, get117);
-
-       return 0;
-}
-/****************************************************************************/
-int stop_100(struct usb_device *p)
-{
-       u16 get0;
-       u8 igot;
-
-       if (!p)
-               return -ENODEV;
-       GET(p, 0x0100, &igot);
-       get0 = igot;
-       SET(p, 0x0100, (0x7F & get0));
-       return 0;
-}
-/****************************************************************************/
-/****************************************************************************/
-/*****************************************************************************/
-int easycap_wakeup_device(struct usb_device *pusb_device)
-{
-       if (!pusb_device)
-               return -ENODEV;
-
-       return usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
-                       USB_REQ_SET_FEATURE,
-                       USB_DIR_OUT | USB_TYPE_STANDARD | USB_RECIP_DEVICE,
-                       USB_DEVICE_REMOTE_WAKEUP,
-                       0, NULL, 0, 50000);
-}
-/*****************************************************************************/
-int easycap_audio_setup(struct easycap *peasycap)
-{
-       struct usb_device *pusb_device;
-       u8 buffer[1];
-       int rc, id1, id2;
-/*---------------------------------------------------------------------------*/
-/*
- *                                IMPORTANT:
- *  THE MESSAGE OF TYPE (USB_DIR_OUT | USB_TYPE_CLASS | USB_RECIP_INTERFACE)
- *  CAUSES MUTING IF THE VALUE 0x0100 IS SENT.
- *  TO ENABLE AUDIO  THE VALUE 0x0200 MUST BE SENT.
- */
-/*---------------------------------------------------------------------------*/
-       const u8 request = 0x01;
-       const u8 requesttype = USB_DIR_OUT |
-                              USB_TYPE_CLASS |
-                              USB_RECIP_INTERFACE;
-       const u16 value_unmute = 0x0200;
-       const u16 index = 0x0301;
-       const u16 length = 1;
-
-       if (!peasycap)
-               return -EFAULT;
-
-       pusb_device = peasycap->pusb_device;
-       if (!pusb_device)
-               return -ENODEV;
-
-       JOM(8, "%02X %02X %02X %02X %02X %02X %02X %02X\n",
-                               requesttype, request,
-                               (0x00FF & value_unmute),
-                               (0xFF00 & value_unmute) >> 8,
-                               (0x00FF & index),
-                               (0xFF00 & index) >> 8,
-                               (0x00FF & length),
-                               (0xFF00 & length) >> 8);
-
-       buffer[0] = 0x01;
-
-       rc = usb_control_msg(pusb_device, usb_sndctrlpipe(pusb_device, 0),
-                               request, requesttype, value_unmute,
-                               index, &buffer[0], length, 50000);
-
-       JOT(8, "0x%02X=buffer\n", buffer[0]);
-       if (rc != (int)length) {
-               switch (rc) {
-               case -EPIPE:
-                       SAY("usb_control_msg returned -EPIPE\n");
-                       break;
-               default:
-                       SAY("ERROR: usb_control_msg returned %i\n", rc);
-                       break;
-               }
-       }
-/*--------------------------------------------------------------------------*/
-/*
- *  REGISTER 500:  SETTING VALUE TO 0x0094 RESETS AUDIO CONFIGURATION ???
- *  REGISTER 506:  ANALOGUE AUDIO ATTENTUATOR ???
- *                 FOR THE CVBS+S-VIDEO HARDWARE:
- *                    SETTING VALUE TO 0x0000 GIVES QUIET SOUND.
- *                    THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
- *                 FOR THE FOUR-CVBS HARDWARE:
- *                    SETTING VALUE TO 0x0000 SEEMS TO HAVE NO EFFECT.
- *  REGISTER 507:  ANALOGUE AUDIO PREAMPLIFIER ON/OFF ???
- *                 FOR THE CVBS-S-VIDEO HARDWARE:
- *                    SETTING VALUE TO 0x0001 GIVES VERY LOUD, DISTORTED SOUND.
- *                    THE UPPER BYTE SEEMS TO HAVE NO EFFECT.
- */
-/*--------------------------------------------------------------------------*/
-       SET(pusb_device, 0x0500, 0x0094);
-       SET(pusb_device, 0x0500, 0x008C);
-       SET(pusb_device, 0x0506, 0x0001);
-       SET(pusb_device, 0x0507, 0x0000);
-       id1 = read_vt(pusb_device, 0x007C);
-       id2 = read_vt(pusb_device, 0x007E);
-       SAM("0x%04X:0x%04X is audio vendor id\n", id1, id2);
-/*---------------------------------------------------------------------------*/
-/*
- *  SELECT AUDIO SOURCE "LINE IN" AND SET THE AUDIO GAIN.
-*/
-/*---------------------------------------------------------------------------*/
-       if (easycap_audio_gainset(pusb_device, peasycap->gain))
-               SAY("ERROR: audio_gainset() failed\n");
-       check_vt(pusb_device);
-       return 0;
-}
-/*****************************************************************************/
-int check_vt(struct usb_device *pusb_device)
-{
-       int igot;
-
-       if (!pusb_device)
-               return -ENODEV;
-       igot = read_vt(pusb_device, 0x0002);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x02\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x02);
-
-       igot = read_vt(pusb_device, 0x000E);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x0E\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x0E);
-
-       igot = read_vt(pusb_device, 0x0010);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x10\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x10);
-
-       igot = read_vt(pusb_device, 0x0012);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x12\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x12);
-
-       igot = read_vt(pusb_device, 0x0014);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x14\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x14);
-
-       igot = read_vt(pusb_device, 0x0016);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x16\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x16);
-
-       igot = read_vt(pusb_device, 0x0018);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x18\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x18);
-
-       igot = read_vt(pusb_device, 0x001C);
-       if (0 > igot)
-               SAY("ERROR: failed to read VT1612A register 0x1C\n");
-       if (0x8000 & igot)
-               SAY("register 0x%02X muted\n", 0x1C);
-
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*  NOTE:  THIS DOES INCREASE THE VOLUME DRAMATICALLY:
- *                      audio_gainset(pusb_device, 0x000F);
- *
- *       loud        dB  register 0x10      dB register 0x1C    dB total
- *         0               -34.5                   0             -34.5
- *        ..                ....                   .              ....
- *        15                10.5                   0              10.5
- *        16                12.0                   0              12.0
- *        17                12.0                   1.5            13.5
- *        ..                ....                  ....            ....
- *        31                12.0                  22.5            34.5
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_audio_gainset(struct usb_device *pusb_device, s8 loud)
-{
-       int igot;
-       u8 tmp;
-       u16 mute;
-
-       if (!pusb_device)
-               return -ENODEV;
-       if (0 > loud)
-               loud = 0;
-       if (31 < loud)
-               loud = 31;
-
-       write_vt(pusb_device, 0x0002, 0x8000);
-/*---------------------------------------------------------------------------*/
-       igot = read_vt(pusb_device, 0x000E);
-       if (0 > igot) {
-               SAY("ERROR: failed to read VT1612A register 0x0E\n");
-               mute = 0x0000;
-       } else
-               mute = 0x8000 & ((unsigned int)igot);
-       mute = 0;
-
-       if (16 > loud)
-               tmp = 0x01 | (0x001F & (((u8)(15 - loud)) << 1));
-       else
-               tmp = 0;
-
-       JOT(8, "0x%04X=(mute|tmp) for VT1612A register 0x0E\n", mute | tmp);
-       write_vt(pusb_device, 0x000E, (mute | tmp));
-/*---------------------------------------------------------------------------*/
-       igot = read_vt(pusb_device, 0x0010);
-       if (0 > igot) {
-               SAY("ERROR: failed to read VT1612A register 0x10\n");
-               mute = 0x0000;
-       } else
-               mute = 0x8000 & ((unsigned int)igot);
-       mute = 0;
-
-       JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x10,...0x18\n",
-                                               mute | tmp | (tmp << 8));
-       write_vt(pusb_device, 0x0010, (mute | tmp | (tmp << 8)));
-       write_vt(pusb_device, 0x0012, (mute | tmp | (tmp << 8)));
-       write_vt(pusb_device, 0x0014, (mute | tmp | (tmp << 8)));
-       write_vt(pusb_device, 0x0016, (mute | tmp | (tmp << 8)));
-       write_vt(pusb_device, 0x0018, (mute | tmp | (tmp << 8)));
-/*---------------------------------------------------------------------------*/
-       igot = read_vt(pusb_device, 0x001C);
-       if (0 > igot) {
-               SAY("ERROR: failed to read VT1612A register 0x1C\n");
-               mute = 0x0000;
-       } else
-               mute = 0x8000 & ((unsigned int)igot);
-       mute = 0;
-
-       if (16 <= loud)
-               tmp = 0x000F & (u8)(loud - 16);
-       else
-               tmp = 0;
-
-       JOT(8, "0x%04X=(mute|tmp|(tmp<<8)) for VT1612A register 0x1C\n",
-                                               mute | tmp | (tmp << 8));
-       write_vt(pusb_device, 0x001C, (mute | tmp | (tmp << 8)));
-       write_vt(pusb_device, 0x001A, 0x0404);
-       write_vt(pusb_device, 0x0002, 0x0000);
-       return 0;
-}
-/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_main.c b/drivers/staging/media/easycap/easycap_main.c
deleted file mode 100644 (file)
index 8269c77..0000000
+++ /dev/null
@@ -1,4239 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_main.c                                                             *
-*                                                                             *
-*  Video driver for EasyCAP USB2.0 Video Capture Device DC60                  *
-*                                                                             *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-#include <linux/usb/audio.h>
-
-
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("R.M. Thomas <rmthomas@sciolus.org>");
-MODULE_DESCRIPTION(EASYCAP_DRIVER_DESCRIPTION);
-MODULE_VERSION(EASYCAP_DRIVER_VERSION);
-
-#ifdef CONFIG_EASYCAP_DEBUG
-int easycap_debug;
-module_param_named(debug, easycap_debug, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(debug, "Debug level: 0(default),1,2,...,9");
-#endif /* CONFIG_EASYCAP_DEBUG */
-
-bool easycap_readback;
-module_param_named(readback, easycap_readback, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(readback, "read back written registers: (default false)");
-
-static int easycap_bars = 1;
-module_param_named(bars, easycap_bars, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(bars,
-       "Testcard bars on input signal failure: 0=>no, 1=>yes(default)");
-
-static int easycap_gain = 16;
-module_param_named(gain, easycap_gain, int, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(gain, "Audio gain: 0,...,16(default),...31");
-
-static bool easycap_ntsc;
-module_param_named(ntsc, easycap_ntsc, bool, S_IRUGO | S_IWUSR);
-MODULE_PARM_DESC(ntsc, "NTSC default encoding (default PAL)");
-
-
-
-struct easycap_dongle easycapdc60_dongle[DONGLE_MANY];
-static struct mutex mutex_dongle;
-static void easycap_complete(struct urb *purb);
-static int reset(struct easycap *peasycap);
-static int field2frame(struct easycap *peasycap);
-static int redaub(struct easycap *peasycap,
-               void *pad, void *pex, int much, int more,
-               u8 mask, u8 margin, bool isuy);
-
-const char *strerror(int err)
-{
-#define ERRNOSTR(_e) case _e: return # _e
-       switch (err) {
-       case 0: return "OK";
-       ERRNOSTR(ENOMEM);
-       ERRNOSTR(ENODEV);
-       ERRNOSTR(ENXIO);
-       ERRNOSTR(EINVAL);
-       ERRNOSTR(EAGAIN);
-       ERRNOSTR(EFBIG);
-       ERRNOSTR(EPIPE);
-       ERRNOSTR(EMSGSIZE);
-       ERRNOSTR(ENOSPC);
-       ERRNOSTR(EINPROGRESS);
-       ERRNOSTR(ENOSR);
-       ERRNOSTR(EOVERFLOW);
-       ERRNOSTR(EPROTO);
-       ERRNOSTR(EILSEQ);
-       ERRNOSTR(ETIMEDOUT);
-       ERRNOSTR(EOPNOTSUPP);
-       ERRNOSTR(EPFNOSUPPORT);
-       ERRNOSTR(EAFNOSUPPORT);
-       ERRNOSTR(EADDRINUSE);
-       ERRNOSTR(EADDRNOTAVAIL);
-       ERRNOSTR(ENOBUFS);
-       ERRNOSTR(EISCONN);
-       ERRNOSTR(ENOTCONN);
-       ERRNOSTR(ESHUTDOWN);
-       ERRNOSTR(ENOENT);
-       ERRNOSTR(ECONNRESET);
-       ERRNOSTR(ETIME);
-       ERRNOSTR(ECOMM);
-       ERRNOSTR(EREMOTEIO);
-       ERRNOSTR(EXDEV);
-       ERRNOSTR(EPERM);
-       default: return "unknown";
-       }
-
-#undef ERRNOSTR
-}
-
-/****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THIS ROUTINE DOES NOT DETECT DUPLICATE OCCURRENCES OF POINTER peasycap
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_isdongle(struct easycap *peasycap)
-{
-       int k;
-       if (!peasycap)
-               return -2;
-       for (k = 0; k < DONGLE_MANY; k++) {
-               if (easycapdc60_dongle[k].peasycap == peasycap) {
-                       peasycap->isdongle = k;
-                       return k;
-               }
-       }
-       return -1;
-}
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-static int easycap_open(struct inode *inode, struct file *file)
-{
-       struct video_device *pvideo_device;
-       struct easycap *peasycap;
-       int rc;
-
-       JOT(4, "\n");
-       SAY("==========OPEN=========\n");
-
-       pvideo_device = video_devdata(file);
-       if (!pvideo_device) {
-               SAY("ERROR: pvideo_device is NULL.\n");
-               return -EFAULT;
-       }
-       peasycap = (struct easycap *)video_get_drvdata(pvideo_device);
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-
-       JOM(16, "peasycap->pusb_device=%p\n", peasycap->pusb_device);
-
-       file->private_data = peasycap;
-       rc = easycap_wakeup_device(peasycap->pusb_device);
-       if (rc) {
-               SAM("ERROR: wakeup_device() rc = %i\n", rc);
-               if (-ENODEV == rc)
-                       SAM("ERROR: wakeup_device() returned -ENODEV\n");
-               else
-                       SAM("ERROR: wakeup_device() rc = %i\n", rc);
-               return rc;
-       }
-       JOM(8, "wakeup_device() OK\n");
-       peasycap->input = 0;
-       rc = reset(peasycap);
-       if (rc) {
-               SAM("ERROR: reset() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       return 0;
-}
-
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  RESET THE HARDWARE TO ITS REFERENCE STATE.
- *
- *  THIS ROUTINE MAY BE CALLED REPEATEDLY IF easycap_complete() DETECTS
- *  A BAD VIDEO FRAME SIZE.
-*/
-/*---------------------------------------------------------------------------*/
-static int reset(struct easycap *peasycap)
-{
-       struct easycap_standard const *peasycap_standard;
-       int fmtidx, input, rate;
-       bool ntsc, other;
-       int rc;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       input = peasycap->input;
-
-/*---------------------------------------------------------------------------*/
-/*
- *  IF THE SAA7113H HAS ALREADY ACQUIRED SYNC, USE ITS HARDWARE-DETECTED
- *  FIELD FREQUENCY TO DISTINGUISH NTSC FROM PAL.  THIS IS ESSENTIAL FOR
- *  gstreamer AND OTHER USERSPACE PROGRAMS WHICH MAY NOT ATTEMPT TO INITIATE
- *  A SWITCH BETWEEN PAL AND NTSC.
- *
- *  FUNCTION ready_saa() MAY REQUIRE A SUBSTANTIAL FRACTION OF A SECOND TO
- *  COMPLETE, SO SHOULD NOT BE INVOKED WITHOUT GOOD REASON.
-*/
-/*---------------------------------------------------------------------------*/
-       other = false;
-       JOM(8, "peasycap->ntsc=%d\n", peasycap->ntsc);
-
-       rate = ready_saa(peasycap->pusb_device);
-       if (rate < 0) {
-               JOM(8, "not ready to capture after %i ms ...\n", PATIENCE);
-               ntsc = !peasycap->ntsc;
-               JOM(8, "... trying  %s ..\n", ntsc ? "NTSC" : "PAL");
-               rc = setup_stk(peasycap->pusb_device, ntsc);
-               if (rc) {
-                       SAM("ERROR: setup_stk() rc = %i\n", rc);
-                       return -EFAULT;
-               }
-               rc = setup_saa(peasycap->pusb_device, ntsc);
-               if (rc) {
-                       SAM("ERROR: setup_saa() rc = %i\n", rc);
-                       return -EFAULT;
-               }
-
-               rate = ready_saa(peasycap->pusb_device);
-               if (rate < 0) {
-                       JOM(8, "not ready to capture after %i ms\n", PATIENCE);
-                       JOM(8, "... saa register 0x1F has 0x%02X\n",
-                                       read_saa(peasycap->pusb_device, 0x1F));
-                       ntsc = peasycap->ntsc;
-               } else {
-                       JOM(8, "... success at second try:  %i=rate\n", rate);
-                       ntsc = (0 < (rate/2)) ? true : false ;
-                       other = true;
-               }
-       } else {
-               JOM(8, "... success at first try:  %i=rate\n", rate);
-               ntsc = (0 < rate/2) ? true : false ;
-       }
-       JOM(8, "ntsc=%d\n", ntsc);
-/*---------------------------------------------------------------------------*/
-
-       rc = setup_stk(peasycap->pusb_device, ntsc);
-       if (rc) {
-               SAM("ERROR: setup_stk() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       rc = setup_saa(peasycap->pusb_device, ntsc);
-       if (rc) {
-               SAM("ERROR: setup_saa() rc = %i\n", rc);
-               return -EFAULT;
-       }
-
-       memset(peasycap->merit, 0, sizeof(peasycap->merit));
-
-       peasycap->video_eof = 0;
-       peasycap->audio_eof = 0;
-/*---------------------------------------------------------------------------*/
-/*
- * RESTORE INPUT AND FORCE REFRESH OF STANDARD, FORMAT, ETC.
- *
- * WHILE THIS PROCEDURE IS IN PROGRESS, SOME IOCTL COMMANDS WILL RETURN -EBUSY.
-*/
-/*---------------------------------------------------------------------------*/
-       peasycap->input = -8192;
-       peasycap->standard_offset = -8192;
-       fmtidx = ntsc ? NTSC_M : PAL_BGHIN;
-       if (other) {
-               peasycap_standard = &easycap_standard[0];
-               while (0xFFFF != peasycap_standard->mask) {
-                       if (fmtidx == peasycap_standard->v4l2_standard.index) {
-                               peasycap->inputset[input].standard_offset =
-                                       peasycap_standard - easycap_standard;
-                               break;
-                       }
-                       peasycap_standard++;
-               }
-               if (0xFFFF == peasycap_standard->mask) {
-                       SAM("ERROR: standard not found\n");
-                       return -EINVAL;
-               }
-               JOM(8, "%i=peasycap->inputset[%i].standard_offset\n",
-                       peasycap->inputset[input].standard_offset, input);
-       }
-       peasycap->format_offset = -8192;
-       peasycap->brightness = -8192;
-       peasycap->contrast = -8192;
-       peasycap->saturation = -8192;
-       peasycap->hue = -8192;
-
-       rc = easycap_newinput(peasycap, input);
-
-       if (rc) {
-               SAM("ERROR: newinput(.,%i) rc = %i\n", rc, input);
-               return -EFAULT;
-       }
-       JOM(4, "restored input, standard and format\n");
-
-       JOM(8, "true=peasycap->ntsc %d\n", peasycap->ntsc);
-
-       if (0 > peasycap->input) {
-               SAM("MISTAKE:  %i=peasycap->input\n", peasycap->input);
-               return -ENOENT;
-       }
-       if (0 > peasycap->standard_offset) {
-               SAM("MISTAKE:  %i=peasycap->standard_offset\n",
-                               peasycap->standard_offset);
-               return -ENOENT;
-       }
-       if (0 > peasycap->format_offset) {
-               SAM("MISTAKE:  %i=peasycap->format_offset\n",
-                               peasycap->format_offset);
-               return -ENOENT;
-       }
-       if (0 > peasycap->brightness) {
-               SAM("MISTAKE:  %i=peasycap->brightness\n",
-                               peasycap->brightness);
-               return -ENOENT;
-       }
-       if (0 > peasycap->contrast) {
-               SAM("MISTAKE:  %i=peasycap->contrast\n", peasycap->contrast);
-               return -ENOENT;
-       }
-       if (0 > peasycap->saturation) {
-               SAM("MISTAKE:  %i=peasycap->saturation\n",
-                               peasycap->saturation);
-               return -ENOENT;
-       }
-       if (0 > peasycap->hue) {
-               SAM("MISTAKE:  %i=peasycap->hue\n", peasycap->hue);
-               return -ENOENT;
-       }
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  IF THE REQUESTED INPUT IS THE SAME AS THE EXISTING INPUT, DO NOTHING.
- *  OTHERWISE:
- *      KILL URBS, CLEAR FIELD AND FRAME BUFFERS AND RESET THEIR
- *           _read AND _fill POINTERS.
- *      SELECT THE NEW INPUT.
- *      ADJUST THE STANDARD, FORMAT, BRIGHTNESS, CONTRAST, SATURATION AND HUE
- *          ON THE BASIS OF INFORMATION IN STRUCTURE easycap.inputset[input].
- *      RESUBMIT THE URBS IF STREAMING WAS ALREADY IN PROGRESS.
- *
- *  NOTE:
- *      THIS ROUTINE MAY BE CALLED FREQUENTLY BY ZONEMINDER VIA IOCTL,
- *      SO IT SHOULD WRITE ONLY SPARINGLY TO THE LOGFILE.
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_newinput(struct easycap *peasycap, int input)
-{
-       int rc, k, m, mood, off;
-       int inputnow, video_idlenow, audio_idlenow;
-       bool resubmit;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-       JOM(8, "%i=input sought\n", input);
-
-       if (0 > input && INPUT_MANY <= input)
-               return -ENOENT;
-       inputnow = peasycap->input;
-       if (input == inputnow)
-               return 0;
-/*---------------------------------------------------------------------------*/
-/*
- *  IF STREAMING IS IN PROGRESS THE URBS ARE KILLED AT THIS
- *  STAGE AND WILL BE RESUBMITTED PRIOR TO EXIT FROM THE ROUTINE.
- *  IF NO STREAMING IS IN PROGRESS NO URBS WILL BE SUBMITTED BY THE
- *  ROUTINE.
-*/
-/*---------------------------------------------------------------------------*/
-       video_idlenow = peasycap->video_idle;
-       audio_idlenow = peasycap->audio_idle;
-
-       peasycap->video_idle = 1;
-       peasycap->audio_idle = 1;
-       if (peasycap->video_isoc_streaming) {
-               resubmit = true;
-               easycap_video_kill_urbs(peasycap);
-       } else {
-               resubmit = false;
-       }
-/*---------------------------------------------------------------------------*/
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -ENODEV;
-       }
-       rc = usb_set_interface(peasycap->pusb_device,
-                               peasycap->video_interface,
-                               peasycap->video_altsetting_off);
-       if (rc) {
-               SAM("ERROR: usb_set_interface() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       rc = stop_100(peasycap->pusb_device);
-       if (rc) {
-               SAM("ERROR: stop_100() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       for (k = 0; k < FIELD_BUFFER_MANY; k++) {
-               for (m = 0; m < FIELD_BUFFER_SIZE/PAGE_SIZE; m++)
-                       memset(peasycap->field_buffer[k][m].pgo, 0, PAGE_SIZE);
-       }
-       for (k = 0; k < FRAME_BUFFER_MANY; k++) {
-               for (m = 0; m < FRAME_BUFFER_SIZE/PAGE_SIZE; m++)
-                       memset(peasycap->frame_buffer[k][m].pgo, 0, PAGE_SIZE);
-       }
-       peasycap->field_page = 0;
-       peasycap->field_read = 0;
-       peasycap->field_fill = 0;
-
-       peasycap->frame_read = 0;
-       peasycap->frame_fill = 0;
-       for (k = 0; k < peasycap->input; k++) {
-               (peasycap->frame_fill)++;
-               if (peasycap->frame_buffer_many <= peasycap->frame_fill)
-                       peasycap->frame_fill = 0;
-       }
-       peasycap->input = input;
-       select_input(peasycap->pusb_device, peasycap->input, 9);
-/*---------------------------------------------------------------------------*/
-       if (input == peasycap->inputset[input].input) {
-               off = peasycap->inputset[input].standard_offset;
-               if (off != peasycap->standard_offset) {
-                       rc = adjust_standard(peasycap,
-                               easycap_standard[off].v4l2_standard.id);
-                       if (rc) {
-                               SAM("ERROR: adjust_standard() rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->standard_offset\n",
-                               peasycap->standard_offset);
-               } else {
-                       JOM(8, "%i=peasycap->standard_offset unchanged\n",
-                                               peasycap->standard_offset);
-               }
-               off = peasycap->inputset[input].format_offset;
-               if (off != peasycap->format_offset) {
-                       struct v4l2_pix_format *pix =
-                               &easycap_format[off].v4l2_format.fmt.pix;
-                       rc = adjust_format(peasycap,
-                               pix->width, pix->height,
-                               pix->pixelformat, pix->field, false);
-                       if (0 > rc) {
-                               SAM("ERROR: adjust_format() rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->format_offset\n",
-                                       peasycap->format_offset);
-               } else {
-                       JOM(8, "%i=peasycap->format_offset unchanged\n",
-                                       peasycap->format_offset);
-               }
-               mood = peasycap->inputset[input].brightness;
-               if (mood != peasycap->brightness) {
-                       rc = adjust_brightness(peasycap, mood);
-                       if (rc) {
-                               SAM("ERROR: adjust_brightness rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->brightness\n",
-                                       peasycap->brightness);
-               }
-               mood = peasycap->inputset[input].contrast;
-               if (mood != peasycap->contrast) {
-                       rc = adjust_contrast(peasycap, mood);
-                       if (rc) {
-                               SAM("ERROR: adjust_contrast rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->contrast\n", peasycap->contrast);
-               }
-               mood = peasycap->inputset[input].saturation;
-               if (mood != peasycap->saturation) {
-                       rc = adjust_saturation(peasycap, mood);
-                       if (rc) {
-                               SAM("ERROR: adjust_saturation rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->saturation\n",
-                                       peasycap->saturation);
-               }
-               mood = peasycap->inputset[input].hue;
-               if (mood != peasycap->hue) {
-                       rc = adjust_hue(peasycap, mood);
-                       if (rc) {
-                               SAM("ERROR: adjust_hue rc = %i\n", rc);
-                               return -EFAULT;
-                       }
-                       JOM(8, "%i=peasycap->hue\n", peasycap->hue);
-               }
-       } else {
-               SAM("MISTAKE: easycap.inputset[%i] unpopulated\n", input);
-               return -ENOENT;
-       }
-/*---------------------------------------------------------------------------*/
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -ENODEV;
-       }
-       rc = usb_set_interface(peasycap->pusb_device,
-                               peasycap->video_interface,
-                               peasycap->video_altsetting_on);
-       if (rc) {
-               SAM("ERROR: usb_set_interface() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       rc = start_100(peasycap->pusb_device);
-       if (rc) {
-               SAM("ERROR: start_100() rc = %i\n", rc);
-               return -EFAULT;
-       }
-       if (resubmit)
-               easycap_video_submit_urbs(peasycap);
-
-       peasycap->video_isoc_sequence = VIDEO_ISOC_BUFFER_MANY - 1;
-       peasycap->video_idle = video_idlenow;
-       peasycap->audio_idle = audio_idlenow;
-       peasycap->video_junk = 0;
-
-       return 0;
-}
-/*****************************************************************************/
-int easycap_video_submit_urbs(struct easycap *peasycap)
-{
-       struct data_urb *pdata_urb;
-       struct urb *purb;
-       struct list_head *plist_head;
-       int j, isbad, nospc, m, rc;
-       int isbuf;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-
-       if (!peasycap->purb_video_head) {
-               SAY("ERROR: peasycap->urb_video_head uninitialized\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAY("ERROR: peasycap->pusb_device is NULL\n");
-               return -ENODEV;
-       }
-       if (!peasycap->video_isoc_streaming) {
-               JOM(4, "submission of all video urbs\n");
-               isbad = 0;  nospc = 0;  m = 0;
-               list_for_each(plist_head, (peasycap->purb_video_head)) {
-                       pdata_urb = list_entry(plist_head,
-                                               struct data_urb, list_head);
-                       if (pdata_urb && pdata_urb->purb) {
-                               purb = pdata_urb->purb;
-                               isbuf = pdata_urb->isbuf;
-                               purb->interval = 1;
-                               purb->dev = peasycap->pusb_device;
-                               purb->pipe =
-                                       usb_rcvisocpipe(peasycap->pusb_device,
-                                       peasycap->video_endpointnumber);
-                               purb->transfer_flags = URB_ISO_ASAP;
-                               purb->transfer_buffer =
-                                       peasycap->video_isoc_buffer[isbuf].pgo;
-                               purb->transfer_buffer_length =
-                                       peasycap->video_isoc_buffer_size;
-                               purb->complete = easycap_complete;
-                               purb->context = peasycap;
-                               purb->start_frame = 0;
-                               purb->number_of_packets =
-                                       peasycap->video_isoc_framesperdesc;
-
-                               for (j = 0;  j < peasycap->video_isoc_framesperdesc; j++) {
-                                       purb->iso_frame_desc[j]. offset =
-                                               j * peasycap->video_isoc_maxframesize;
-                                       purb->iso_frame_desc[j]. length =
-                                               peasycap->video_isoc_maxframesize;
-                               }
-
-                               rc = usb_submit_urb(purb, GFP_KERNEL);
-                               if (rc) {
-                                       isbad++;
-                                       SAM("ERROR: usb_submit_urb() failed "
-                                               "for urb with rc:-%s\n",
-                                                       strerror(rc));
-                                       if (rc == -ENOSPC)
-                                               nospc++;
-                               } else {
-                                       m++;
-                               }
-                       } else {
-                               isbad++;
-                       }
-               }
-               if (nospc) {
-                       SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
-                       SAM(".....  possibly inadequate USB bandwidth\n");
-                       peasycap->video_eof = 1;
-               }
-
-               if (isbad)
-                       easycap_video_kill_urbs(peasycap);
-               else
-                       peasycap->video_isoc_streaming = 1;
-       } else {
-               JOM(4, "already streaming video urbs\n");
-       }
-       return 0;
-}
-/*****************************************************************************/
-int easycap_audio_kill_urbs(struct easycap *peasycap)
-{
-       int m;
-       struct list_head *plist_head;
-       struct data_urb *pdata_urb;
-
-       if (!peasycap->audio_isoc_streaming)
-               return 0;
-
-       if (!peasycap->purb_audio_head) {
-               SAM("ERROR: peasycap->purb_audio_head is NULL\n");
-               return -EFAULT;
-       }
-
-       peasycap->audio_isoc_streaming = 0;
-       m = 0;
-       list_for_each(plist_head, peasycap->purb_audio_head) {
-               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-               if (pdata_urb && pdata_urb->purb) {
-                       usb_kill_urb(pdata_urb->purb);
-                       m++;
-               }
-       }
-
-       JOM(4, "%i audio urbs killed\n", m);
-
-       return 0;
-}
-int easycap_video_kill_urbs(struct easycap *peasycap)
-{
-       int m;
-       struct list_head *plist_head;
-       struct data_urb *pdata_urb;
-
-       if (!peasycap->video_isoc_streaming)
-               return 0;
-
-       if (!peasycap->purb_video_head) {
-               SAM("ERROR: peasycap->purb_video_head is NULL\n");
-               return -EFAULT;
-       }
-
-       peasycap->video_isoc_streaming = 0;
-       JOM(4, "killing video urbs\n");
-       m = 0;
-       list_for_each(plist_head, (peasycap->purb_video_head)) {
-               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-               if (pdata_urb && pdata_urb->purb) {
-                       usb_kill_urb(pdata_urb->purb);
-                       m++;
-               }
-       }
-       JOM(4, "%i video urbs killed\n", m);
-
-       return 0;
-}
-/****************************************************************************/
-/*^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^*/
-/*--------------------------------------------------------------------------*/
-static int easycap_open_noinode(struct file *file)
-{
-       return easycap_open(NULL, file);
-}
-
-static int videodev_release(struct video_device *pvideo_device)
-{
-       struct easycap *peasycap;
-
-       peasycap = video_get_drvdata(pvideo_device);
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               SAY("ending unsuccessfully\n");
-               return -EFAULT;
-       }
-       if (easycap_video_kill_urbs(peasycap)) {
-               SAM("ERROR: easycap_video_kill_urbs() failed\n");
-               return -EFAULT;
-       }
-       JOM(4, "ending successfully\n");
-       return 0;
-}
-
-/*****************************************************************************/
-static unsigned int easycap_poll(struct file *file, poll_table *wait)
-{
-       struct easycap *peasycap;
-       int rc, kd;
-
-       JOT(8, "\n");
-
-       if (NULL == ((poll_table *)wait))
-               JOT(8, "WARNING:  poll table pointer is NULL ... continuing\n");
-       if (!file) {
-               SAY("ERROR:  file pointer is NULL\n");
-               return -ERESTARTSYS;
-       }
-       peasycap = file->private_data;
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAY("ERROR:  peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-/*---------------------------------------------------------------------------*/
-       kd = easycap_isdongle(peasycap);
-       if (0 <= kd && DONGLE_MANY > kd) {
-               if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
-                       SAY("ERROR: cannot down dongle[%i].mutex_video\n", kd);
-                       return -ERESTARTSYS;
-               }
-               JOM(4, "locked dongle[%i].mutex_video\n", kd);
-       /*
-        *  MEANWHILE, easycap_usb_disconnect() MAY HAVE FREED POINTER
-        *  peasycap, IN WHICH CASE A REPEAT CALL TO isdongle() WILL FAIL.
-        *  IF NECESSARY, BAIL OUT.
-        */
-               if (kd != easycap_isdongle(peasycap)) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-               if (!file) {
-                       SAY("ERROR:  file is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-               peasycap = file->private_data;
-               if (!peasycap) {
-                       SAY("ERROR:  peasycap is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-               if (!peasycap->pusb_device) {
-                       SAM("ERROR: peasycap->pusb_device is NULL\n");
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return -ERESTARTSYS;
-               }
-       } else
-       /*
-        *  IF easycap_usb_disconnect() HAS ALREADY FREED POINTER peasycap
-        *  BEFORE THE ATTEMPT TO ACQUIRE THE SEMAPHORE, isdongle() WILL
-        *  HAVE FAILED.  BAIL OUT.
-       */
-               return -ERESTARTSYS;
-/*---------------------------------------------------------------------------*/
-       rc = easycap_video_dqbuf(peasycap, 0);
-       peasycap->polled = 1;
-       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-       if (rc)
-               return POLLERR;
-
-       return POLLIN | POLLRDNORM;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  IF mode IS NONZERO THIS ROUTINE RETURNS -EAGAIN RATHER THAN BLOCKING.
- */
-/*---------------------------------------------------------------------------*/
-int easycap_video_dqbuf(struct easycap *peasycap, int mode)
-{
-       int input, ifield, miss, rc;
-
-
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAY("ERROR:  peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-       ifield = 0;
-       JOM(8, "%i=ifield\n", ifield);
-/*---------------------------------------------------------------------------*/
-/*
- *  CHECK FOR LOST INPUT SIGNAL.
- *
- *  FOR THE FOUR-CVBS EasyCAP, THIS DOES NOT WORK AS EXPECTED.
- *  IF INPUT 0 IS PRESENT AND SYNC ACQUIRED, UNPLUGGING INPUT 4 DOES NOT
- *  RESULT IN SETTING BIT 0x40 ON REGISTER 0x1F, PRESUMABLY BECAUSE THERE
- *  IS FLYWHEELING ON INPUT 0.  THE UPSHOT IS:
- *
- *    INPUT 0   PLUGGED, INPUT 4   PLUGGED => SCREEN 0 OK,   SCREEN 4 OK
- *    INPUT 0   PLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 OK,   SCREEN 4 BLACK
- *    INPUT 0 UNPLUGGED, INPUT 4   PLUGGED => SCREEN 0 BARS, SCREEN 4 OK
- *    INPUT 0 UNPLUGGED, INPUT 4 UNPLUGGED => SCREEN 0 BARS, SCREEN 4 BARS
-*/
-/*---------------------------------------------------------------------------*/
-       input = peasycap->input;
-       if (0 <= input && INPUT_MANY > input) {
-               rc = read_saa(peasycap->pusb_device, 0x1F);
-               if (0 <= rc) {
-                       if (rc & 0x40)
-                               peasycap->lost[input] += 1;
-                       else
-                               peasycap->lost[input] -= 2;
-
-               if (0 > peasycap->lost[input])
-                       peasycap->lost[input] = 0;
-               else if ((2 * VIDEO_LOST_TOLERATE) < peasycap->lost[input])
-                       peasycap->lost[input] = (2 * VIDEO_LOST_TOLERATE);
-               }
-       }
-/*---------------------------------------------------------------------------*/
-/*
- *  WAIT FOR FIELD ifield  (0 => TOP, 1 => BOTTOM)
- */
-/*---------------------------------------------------------------------------*/
-       miss = 0;
-       while ((peasycap->field_read == peasycap->field_fill) ||
-              (0 != (0xFF00 & peasycap->field_buffer
-                                       [peasycap->field_read][0].kount)) ||
-             (ifield != (0x00FF & peasycap->field_buffer
-                                       [peasycap->field_read][0].kount))) {
-               if (mode)
-                       return -EAGAIN;
-
-               JOM(8, "first wait  on wq_video, %i=field_read %i=field_fill\n",
-                               peasycap->field_read, peasycap->field_fill);
-
-               if (0 != (wait_event_interruptible(peasycap->wq_video,
-                               (peasycap->video_idle || peasycap->video_eof  ||
-                               ((peasycap->field_read != peasycap->field_fill) &&
-                               (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
-                               (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
-                       SAM("aborted by signal\n");
-                       return -EIO;
-               }
-               if (peasycap->video_idle) {
-                       JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
-                                                       peasycap->video_idle);
-                       return -EAGAIN;
-               }
-               if (peasycap->video_eof) {
-                       JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
-                       #if defined(PERSEVERE)
-                       if (1 == peasycap->status) {
-                               JOM(8, "persevering ...\n");
-                               peasycap->video_eof = 0;
-                               peasycap->audio_eof = 0;
-                               if (0 != reset(peasycap)) {
-                                       JOM(8, " ... failed  returning -EIO\n");
-                                       peasycap->video_eof = 1;
-                                       peasycap->audio_eof = 1;
-                                       easycap_video_kill_urbs(peasycap);
-                                       return -EIO;
-                               }
-                               peasycap->status = 0;
-                               JOM(8, " ... OK  returning -EAGAIN\n");
-                               return -EAGAIN;
-                       }
-                       #endif /*PERSEVERE*/
-                       peasycap->video_eof = 1;
-                       peasycap->audio_eof = 1;
-                       easycap_video_kill_urbs(peasycap);
-                       JOM(8, "returning -EIO\n");
-                       return -EIO;
-               }
-               miss++;
-       }
-       JOM(8, "first awakening on wq_video after %i waits\n", miss);
-
-       rc = field2frame(peasycap);
-       if (rc)
-               SAM("ERROR: field2frame() rc = %i\n", rc);
-/*---------------------------------------------------------------------------*/
-/*
- *  WAIT FOR THE OTHER FIELD
- */
-/*---------------------------------------------------------------------------*/
-       if (ifield)
-               ifield = 0;
-       else
-               ifield = 1;
-       miss = 0;
-       while ((peasycap->field_read == peasycap->field_fill) ||
-              (0 != (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) ||
-              (ifield != (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))) {
-               if (mode)
-                       return -EAGAIN;
-
-               JOM(8, "second wait on wq_video %i=field_read  %i=field_fill\n",
-                               peasycap->field_read, peasycap->field_fill);
-               if (0 != (wait_event_interruptible(peasycap->wq_video,
-                       (peasycap->video_idle || peasycap->video_eof  ||
-                       ((peasycap->field_read != peasycap->field_fill) &&
-                        (0 == (0xFF00 & peasycap->field_buffer[peasycap->field_read][0].kount)) &&
-                        (ifield == (0x00FF & peasycap->field_buffer[peasycap->field_read][0].kount))))))) {
-                       SAM("aborted by signal\n");
-                       return -EIO;
-               }
-               if (peasycap->video_idle) {
-                       JOM(8, "%i=peasycap->video_idle returning -EAGAIN\n",
-                                                       peasycap->video_idle);
-                       return -EAGAIN;
-               }
-               if (peasycap->video_eof) {
-                       JOM(8, "%i=peasycap->video_eof\n", peasycap->video_eof);
-#if defined(PERSEVERE)
-                       if (1 == peasycap->status) {
-                               JOM(8, "persevering ...\n");
-                               peasycap->video_eof = 0;
-                               peasycap->audio_eof = 0;
-                               if (0 != reset(peasycap)) {
-                                       JOM(8, " ... failed returning -EIO\n");
-                                       peasycap->video_eof = 1;
-                                       peasycap->audio_eof = 1;
-                                       easycap_video_kill_urbs(peasycap);
-                                       return -EIO;
-                               }
-                               peasycap->status = 0;
-                               JOM(8, " ... OK ... returning -EAGAIN\n");
-                               return -EAGAIN;
-                       }
-#endif /*PERSEVERE*/
-                       peasycap->video_eof = 1;
-                       peasycap->audio_eof = 1;
-                       easycap_video_kill_urbs(peasycap);
-                       JOM(8, "returning -EIO\n");
-                       return -EIO;
-               }
-               miss++;
-       }
-       JOM(8, "second awakening on wq_video after %i waits\n", miss);
-
-       rc = field2frame(peasycap);
-       if (rc)
-               SAM("ERROR: field2frame() rc = %i\n", rc);
-/*---------------------------------------------------------------------------*/
-/*
- *  WASTE THIS FRAME
-*/
-/*---------------------------------------------------------------------------*/
-       if (peasycap->skip) {
-               peasycap->skipped++;
-               if (peasycap->skip != peasycap->skipped)
-                       return peasycap->skip - peasycap->skipped;
-               else
-                       peasycap->skipped = 0;
-       }
-/*---------------------------------------------------------------------------*/
-       peasycap->frame_read = peasycap->frame_fill;
-       peasycap->queued[peasycap->frame_read] = 0;
-       peasycap->done[peasycap->frame_read]   = V4L2_BUF_FLAG_DONE;
-
-       peasycap->frame_fill++;
-       if (peasycap->frame_buffer_many <= peasycap->frame_fill)
-               peasycap->frame_fill = 0;
-
-       if (0x01 & easycap_standard[peasycap->standard_offset].mask)
-               peasycap->frame_buffer[peasycap->frame_read][0].kount =
-                                                       V4L2_FIELD_TOP;
-       else
-               peasycap->frame_buffer[peasycap->frame_read][0].kount =
-                                                       V4L2_FIELD_BOTTOM;
-
-
-       JOM(8, "setting:    %i=peasycap->frame_read\n", peasycap->frame_read);
-       JOM(8, "bumped to:  %i=peasycap->frame_fill\n", peasycap->frame_fill);
-
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  BY DEFINITION, odd IS true  FOR THE FIELD OCCUPYING LINES 1,3,5,...,479
- *                 odd IS false FOR THE FIELD OCCUPYING LINES 0,2,4,...,478
- *
- *  WHEN BOOLEAN PARAMETER decimatepixel IS true, ONLY THE FIELD FOR WHICH
- *  odd==false IS TRANSFERRED TO THE FRAME BUFFER.
- *
- */
-/*---------------------------------------------------------------------------*/
-static int field2frame(struct easycap *peasycap)
-{
-
-       void *pex, *pad;
-       int kex, kad, mex, mad, rex, rad, rad2;
-       int c2, c3, w2, w3, cz, wz;
-       int rc, bytesperpixel, multiplier;
-       int  much, more, over, rump, caches, input;
-       u8 mask, margin;
-       bool odd, isuy, decimatepixel, badinput;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -EFAULT;
-       }
-
-       badinput = false;
-       input = 0x07 & peasycap->field_buffer[peasycap->field_read][0].input;
-
-       JOM(8, "=====  parity %i, input 0x%02X, field buffer %i --> "
-                                                       "frame buffer %i\n",
-                       peasycap->field_buffer[peasycap->field_read][0].kount,
-                       peasycap->field_buffer[peasycap->field_read][0].input,
-                       peasycap->field_read, peasycap->frame_fill);
-       JOM(8, "=====  %i=bytesperpixel\n", peasycap->bytesperpixel);
-
-/*---------------------------------------------------------------------------*/
-/*
- *  REJECT OR CLEAN BAD FIELDS
- */
-/*---------------------------------------------------------------------------*/
-       if (peasycap->field_read == peasycap->field_fill) {
-               SAM("ERROR: on entry, still filling field buffer %i\n",
-                                               peasycap->field_read);
-               return 0;
-       }
-#ifdef EASYCAP_TESTCARD
-       easycap_testcard(peasycap, peasycap->field_read);
-#else
-       if (0 <= input && INPUT_MANY > input) {
-               if (easycap_bars && VIDEO_LOST_TOLERATE <= peasycap->lost[input])
-                       easycap_testcard(peasycap, peasycap->field_read);
-       }
-#endif /*EASYCAP_TESTCARD*/
-/*---------------------------------------------------------------------------*/
-
-       bytesperpixel = peasycap->bytesperpixel;
-       decimatepixel = peasycap->decimatepixel;
-
-       if ((2 != bytesperpixel) &&
-           (3 != bytesperpixel) &&
-           (4 != bytesperpixel)) {
-               SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
-               return -EFAULT;
-       }
-       if (decimatepixel)
-               multiplier = 2;
-       else
-               multiplier = 1;
-
-       w2 = 2 * multiplier * (peasycap->width);
-       w3 = bytesperpixel * multiplier * (peasycap->width);
-       wz = multiplier * (peasycap->height) *
-               multiplier * (peasycap->width);
-
-       kex = peasycap->field_read;  mex = 0;
-       kad = peasycap->frame_fill;  mad = 0;
-
-       pex = peasycap->field_buffer[kex][0].pgo;  rex = PAGE_SIZE;
-       pad = peasycap->frame_buffer[kad][0].pgo;  rad = PAGE_SIZE;
-       odd = !!(peasycap->field_buffer[kex][0].kount);
-
-       if (odd && (!decimatepixel)) {
-               JOM(8, "initial skipping %4i bytes p.%4i\n",
-                                       w3/multiplier, mad);
-               pad += (w3 / multiplier); rad -= (w3 / multiplier);
-       }
-       isuy = true;
-       mask = 0;  rump = 0;  caches = 0;
-
-       cz = 0;
-       while (cz < wz) {
-               /*
-                *  PROCESS ONE LINE OF FRAME AT FULL RESOLUTION:
-                *  READ   w2   BYTES FROM FIELD BUFFER,
-                *  WRITE  w3   BYTES TO FRAME BUFFER
-                */
-               if (!decimatepixel) {
-                       over = w2;
-                       do {
-                               much = over;  more = 0;
-                               margin = 0;  mask = 0x00;
-                               if (rex < much)
-                                       much = rex;
-                               rump = 0;
-
-                               if (much % 2) {
-                                       SAM("MISTAKE: much is odd\n");
-                                       return -EFAULT;
-                               }
-
-                               more = (bytesperpixel *
-                                               much) / 2;
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-                               if (1 < bytesperpixel) {
-                                       if (rad * 2 < much * bytesperpixel) {
-                                               /*
-                                                * INJUDICIOUS ALTERATION OF
-                                                * THIS STATEMENT BLOCK WILL
-                                                * CAUSE BREAKAGE.  BEWARE.
-                                                */
-                                               rad2 = rad + bytesperpixel - 1;
-                                               much = ((((2 * rad2)/bytesperpixel)/2) * 2);
-                                               rump = ((bytesperpixel * much) / 2) - rad;
-                                               more = rad;
-                                       }
-                                       mask = (u8)rump;
-                                       margin = 0;
-                                       if (much == rex) {
-                                               mask |= 0x04;
-                                               if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
-                                                       margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
-                                               else
-                                                       mask |= 0x08;
-                                       }
-                               } else {
-                                       SAM("MISTAKE: %i=bytesperpixel\n",
-                                                       bytesperpixel);
-                                       return -EFAULT;
-                               }
-                               if (rump)
-                                       caches++;
-                                       if (badinput) {
-                                               JOM(8, "ERROR: 0x%02X=->field_buffer"
-                                                       "[%i][%i].input, "
-                                                       "0x%02X=(0x08|->input)\n",
-                                                       peasycap->field_buffer
-                                                       [kex][mex].input, kex, mex,
-                                                       (0x08|peasycap->input));
-                                       }
-                               rc = redaub(peasycap, pad, pex, much, more,
-                                                               mask, margin, isuy);
-                               if (0 > rc) {
-                                       SAM("ERROR: redaub() failed\n");
-                                       return -EFAULT;
-                               }
-                               if (much % 4)
-                                       isuy = !isuy;
-
-                               over -= much;   cz += much;
-                               pex  += much;  rex -= much;
-                               if (!rex) {
-                                       mex++;
-                                       pex = peasycap->field_buffer[kex][mex].pgo;
-                                       rex = PAGE_SIZE;
-                                       if (peasycap->field_buffer[kex][mex].input != (0x08|peasycap->input))
-                                               badinput = true;
-                               }
-                               pad  += more;
-                               rad -= more;
-                               if (!rad) {
-                                       mad++;
-                                       pad = peasycap->frame_buffer[kad][mad].pgo;
-                                       rad = PAGE_SIZE;
-                                       if (rump) {
-                                               pad += rump;
-                                               rad -= rump;
-                                       }
-                               }
-                       } while (over);
-/*---------------------------------------------------------------------------*/
-/*
- *  SKIP  w3 BYTES IN TARGET FRAME BUFFER,
- *  UNLESS IT IS THE LAST LINE OF AN ODD FRAME
- */
-/*---------------------------------------------------------------------------*/
-                       if (!odd || (cz != wz)) {
-                               over = w3;
-                               do {
-                                       if (!rad) {
-                                               mad++;
-                                               pad = peasycap->frame_buffer
-                                                       [kad][mad].pgo;
-                                               rad = PAGE_SIZE;
-                                       }
-                                       more = over;
-                                       if (rad < more)
-                                               more = rad;
-                                       over -= more;
-                                       pad  += more;
-                                       rad  -= more;
-                               } while (over);
-                       }
-/*---------------------------------------------------------------------------*/
-/*
- *  PROCESS ONE LINE OF FRAME AT REDUCED RESOLUTION:
- *  ONLY IF false==odd,
- *  READ   w2   BYTES FROM FIELD BUFFER,
- *  WRITE  w3 / 2  BYTES TO FRAME BUFFER
- */
-/*---------------------------------------------------------------------------*/
-               } else if (!odd) {
-                       over = w2;
-                       do {
-                               much = over;  more = 0;  margin = 0;  mask = 0x00;
-                               if (rex < much)
-                                       much = rex;
-                               rump = 0;
-
-                               if (much % 2) {
-                                       SAM("MISTAKE: much is odd\n");
-                                       return -EFAULT;
-                               }
-
-                               more = (bytesperpixel * much) / 4;
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-                               if (1 < bytesperpixel) {
-                                       if (rad * 4 < much * bytesperpixel) {
-                                               /*
-                                                * INJUDICIOUS ALTERATION OF
-                                                * THIS STATEMENT BLOCK
-                                                * WILL CAUSE BREAKAGE.
-                                                * BEWARE.
-                                                */
-                                               rad2 = rad + bytesperpixel - 1;
-                                               much = ((((2 * rad2) / bytesperpixel) / 2) * 4);
-                                               rump = ((bytesperpixel * much) / 4) - rad;
-                                               more = rad;
-                                       }
-                                       mask = (u8)rump;
-                                       margin = 0;
-                                       if (much == rex) {
-                                               mask |= 0x04;
-                                               if ((mex + 1) < FIELD_BUFFER_SIZE / PAGE_SIZE)
-                                                       margin = *((u8 *)(peasycap->field_buffer[kex][mex + 1].pgo));
-                                               else
-                                                       mask |= 0x08;
-                                       }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-                               } else {
-                                       SAM("MISTAKE: %i=bytesperpixel\n",
-                                               bytesperpixel);
-                                       return -EFAULT;
-                               }
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-                               if (rump)
-                                       caches++;
-
-                                       if (badinput) {
-                                               JOM(8, "ERROR: 0x%02X=->field_buffer"
-                                                       "[%i][%i].input, "
-                                                       "0x%02X=(0x08|->input)\n",
-                                                       peasycap->field_buffer
-                                                       [kex][mex].input, kex, mex,
-                                                       (0x08|peasycap->input));
-                                       }
-                               rc = redaub(peasycap, pad, pex, much, more,
-                                                       mask, margin, isuy);
-                               if (0 > rc) {
-                                       SAM("ERROR: redaub() failed\n");
-                                       return -EFAULT;
-                               }
-                               over -= much;   cz += much;
-                               pex  += much;  rex -= much;
-                               if (!rex) {
-                                       mex++;
-                                       pex = peasycap->field_buffer[kex][mex].pgo;
-                                       rex = PAGE_SIZE;
-                                       if (peasycap->field_buffer[kex][mex].input !=
-                                                       (0x08|peasycap->input))
-                                               badinput = true;
-                               }
-                               pad  += more;
-                               rad -= more;
-                               if (!rad) {
-                                       mad++;
-                                       pad = peasycap->frame_buffer[kad][mad].pgo;
-                                       rad = PAGE_SIZE;
-                                       if (rump) {
-                                               pad += rump;
-                                               rad -= rump;
-                                       }
-                               }
-                       } while (over);
-/*---------------------------------------------------------------------------*/
-/*
- *  OTHERWISE JUST
- *  READ   w2   BYTES FROM FIELD BUFFER AND DISCARD THEM
- */
-/*---------------------------------------------------------------------------*/
-               } else {
-                       over = w2;
-                       do {
-                               if (!rex) {
-                                       mex++;
-                                       pex = peasycap->field_buffer[kex][mex].pgo;
-                                       rex = PAGE_SIZE;
-                                       if (peasycap->field_buffer[kex][mex].input !=
-                                                       (0x08|peasycap->input)) {
-                                               JOM(8, "ERROR: 0x%02X=->field_buffer"
-                                                       "[%i][%i].input, "
-                                                       "0x%02X=(0x08|->input)\n",
-                                                       peasycap->field_buffer
-                                                       [kex][mex].input, kex, mex,
-                                                       (0x08|peasycap->input));
-                                               badinput = true;
-                                       }
-                               }
-                               much = over;
-                               if (rex < much)
-                                       much = rex;
-                               over -= much;
-                               cz += much;
-                               pex  += much;
-                               rex -= much;
-                       } while (over);
-               }
-       }
-/*---------------------------------------------------------------------------*/
-/*
- *  SANITY CHECKS
- */
-/*---------------------------------------------------------------------------*/
-       c2 = (mex + 1)*PAGE_SIZE - rex;
-       if (cz != c2)
-               SAM("ERROR: discrepancy %i in bytes read\n", c2 - cz);
-       c3 = (mad + 1)*PAGE_SIZE - rad;
-
-       if (!decimatepixel) {
-               if (bytesperpixel * cz != c3)
-                       SAM("ERROR: discrepancy %i in bytes written\n",
-                                       c3 - (bytesperpixel * cz));
-       } else {
-               if (!odd) {
-                       if (bytesperpixel *
-                               cz != (4 * c3))
-                               SAM("ERROR: discrepancy %i in bytes written\n",
-                                       (2*c3)-(bytesperpixel * cz));
-                       } else {
-                               if (0 != c3)
-                                       SAM("ERROR: discrepancy %i "
-                                           "in bytes written\n", c3);
-                       }
-       }
-       if (rump)
-               SAM("WORRY: undischarged cache at end of line in frame buffer\n");
-
-       JOM(8, "===== field2frame(): %i bytes --> %i bytes (incl skip)\n", c2, c3);
-       JOM(8, "===== field2frame(): %i=mad  %i=rad\n", mad, rad);
-
-       if (odd)
-               JOM(8, "+++++ field2frame():  frame buffer %i is full\n", kad);
-
-       if (peasycap->field_read == peasycap->field_fill)
-               SAM("WARNING: on exit, filling field buffer %i\n",
-                                               peasycap->field_read);
-
-       if (caches)
-               JOM(8, "%i=caches\n", caches);
-       return 0;
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  DECIMATION AND COLOURSPACE CONVERSION.
- *
- *  THIS ROUTINE REQUIRES THAT ALL THE DATA TO BE READ RESIDES ON ONE PAGE
- *  AND THAT ALL THE DATA TO BE WRITTEN RESIDES ON ONE (DIFFERENT) PAGE.
- *  THE CALLING ROUTINE MUST ENSURE THAT THIS REQUIREMENT IS MET, AND MUST
- *  ALSO ENSURE THAT much IS EVEN.
- *
- *  much BYTES ARE READ, AT LEAST (bytesperpixel * much)/2 BYTES ARE WRITTEN
- *  IF THERE IS NO DECIMATION, HALF THIS AMOUNT IF THERE IS DECIMATION.
- *
- *  mask IS ZERO WHEN NO SPECIAL BEHAVIOUR REQUIRED. OTHERWISE IT IS SET THUS:
- *     0x03 & mask =  number of bytes to be written to cache instead of to
- *                    frame buffer
- *     0x04 & mask => use argument margin to set the chrominance for last pixel
- *     0x08 & mask => do not set the chrominance for last pixel
- *
- *  YUV to RGB CONVERSION IS (OR SHOULD BE) ITU-R BT 601.
- *
- *  THERE IS A LOT OF CODE REPETITION IN THIS ROUTINE IN ORDER TO AVOID
- *  INEFFICIENT SWITCHING INSIDE INNER LOOPS.  REARRANGING THE LOGIC TO
- *  REDUCE CODE LENGTH WILL GENERALLY IMPAIR RUNTIME PERFORMANCE.  BEWARE.
- */
-/*---------------------------------------------------------------------------*/
-static int redaub(struct easycap *peasycap,
-               void *pad, void *pex, int much, int more,
-               u8 mask, u8 margin, bool isuy)
-{
-       static s32 ay[256], bu[256], rv[256], gu[256], gv[256];
-       u8 *pcache;
-       u8 r, g, b, y, u, v, c, *p2, *p3, *pz, *pr;
-       int  bytesperpixel;
-       bool byteswaporder, decimatepixel, last;
-       int j, rump;
-       s32 tmp;
-
-       if (much % 2) {
-               SAM("MISTAKE: much is odd\n");
-               return -EFAULT;
-       }
-       bytesperpixel = peasycap->bytesperpixel;
-       byteswaporder = peasycap->byteswaporder;
-       decimatepixel = peasycap->decimatepixel;
-
-/*---------------------------------------------------------------------------*/
-       if (!bu[255]) {
-               for (j = 0; j < 112; j++) {
-                       tmp = (0xFF00 & (453 * j)) >> 8;
-                       bu[j + 128] =  tmp; bu[127 - j] = -tmp;
-                       tmp = (0xFF00 & (359 * j)) >> 8;
-                       rv[j + 128] =  tmp; rv[127 - j] = -tmp;
-                       tmp = (0xFF00 & (88 * j)) >> 8;
-                       gu[j + 128] =  tmp; gu[127 - j] = -tmp;
-                       tmp = (0xFF00 & (183 * j)) >> 8;
-                       gv[j + 128] =  tmp; gv[127 - j] = -tmp;
-               }
-               for (j = 0; j < 16; j++) {
-                       bu[j] = bu[16]; rv[j] = rv[16];
-                       gu[j] = gu[16]; gv[j] = gv[16];
-               }
-               for (j = 240; j < 256; j++) {
-                       bu[j] = bu[239]; rv[j] = rv[239];
-                       gu[j] = gu[239]; gv[j] = gv[239];
-               }
-               for (j =  16; j < 236; j++)
-                       ay[j] = j;
-               for (j =   0; j <  16; j++)
-                       ay[j] = ay[16];
-               for (j = 236; j < 256; j++)
-                       ay[j] = ay[235];
-               JOM(8, "lookup tables are prepared\n");
-       }
-       pcache = peasycap->pcache;
-       if (!pcache)
-               pcache = &peasycap->cache[0];
-/*---------------------------------------------------------------------------*/
-/*
- *  TRANSFER CONTENTS OF CACHE TO THE FRAME BUFFER
- */
-/*---------------------------------------------------------------------------*/
-       if (!pcache) {
-               SAM("MISTAKE: pcache is NULL\n");
-               return -EFAULT;
-       }
-
-       if (pcache != &peasycap->cache[0])
-               JOM(16, "cache has %i bytes\n", (int)(pcache - &peasycap->cache[0]));
-       p2 = &peasycap->cache[0];
-       p3 = (u8 *)pad - (int)(pcache - &peasycap->cache[0]);
-       while (p2 < pcache) {
-               *p3++ = *p2;  p2++;
-       }
-       pcache = &peasycap->cache[0];
-       if (p3 != pad) {
-               SAM("MISTAKE: pointer misalignment\n");
-               return -EFAULT;
-       }
-/*---------------------------------------------------------------------------*/
-       rump = (int)(0x03 & mask);
-       u = 0; v = 0;
-       p2 = (u8 *)pex;  pz = p2 + much;  pr = p3 + more;  last = false;
-       p2++;
-
-       if (isuy)
-               u = *(p2 - 1);
-       else
-               v = *(p2 - 1);
-
-       if (rump)
-               JOM(16, "%4i=much  %4i=more  %i=rump\n", much, more, rump);
-
-/*---------------------------------------------------------------------------*/
-       switch (bytesperpixel) {
-       case 2: {
-               if (!decimatepixel) {
-                       memcpy(pad, pex, (size_t)much);
-                       if (!byteswaporder) {
-                               /* UYVY */
-                               return 0;
-                       } else {
-                               /* YUYV */
-                               p3 = (u8 *)pad;  pz = p3 + much;
-                               while  (pz > p3) {
-                                       c = *p3;
-                                       *p3 = *(p3 + 1);
-                                       *(p3 + 1) = c;
-                                       p3 += 2;
-                               }
-                               return 0;
-                       }
-               } else {
-                       if (!byteswaporder) {
-                               /*  UYVY DECIMATED */
-                               p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
-                               while (pz > p2) {
-                                       *p3 = *p2;
-                                       *(p3 + 1) = *(p2 + 1);
-                                       *(p3 + 2) = *(p2 + 2);
-                                       *(p3 + 3) = *(p2 + 3);
-                                       p3 += 4;  p2 += 8;
-                               }
-                               return 0;
-                       } else {
-                               /* YUYV DECIMATED */
-                               p2 = (u8 *)pex;  p3 = (u8 *)pad;  pz = p2 + much;
-                               while (pz > p2) {
-                                       *p3 = *(p2 + 1);
-                                       *(p3 + 1) = *p2;
-                                       *(p3 + 2) = *(p2 + 3);
-                                       *(p3 + 3) = *(p2 + 2);
-                                       p3 += 4;  p2 += 8;
-                               }
-                               return 0;
-                       }
-               }
-               break;
-               }
-       case 3:
-               {
-               if (!decimatepixel) {
-                       if (!byteswaporder) {
-                               /* RGB */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                       if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       tmp = ay[(int)y] + rv[(int)v];
-                                       r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                               0 : (u8)tmp);
-                                       tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
-                                       g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                               0 : (u8)tmp);
-                                       tmp = ay[(int)y] + bu[(int)u];
-                                       b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                               0 : (u8)tmp);
-
-                                       if (last && rump) {
-                                               pcache = &peasycap->cache[0];
-                                               switch (bytesperpixel - rump) {
-                                               case 1: {
-                                                       *p3 = r;
-                                                       *pcache++ = g;
-                                                       *pcache++ = b;
-                                                       break;
-                                               }
-                                               case 2: {
-                                                       *p3 = r;
-                                                       *(p3 + 1) = g;
-                                                       *pcache++ = b;
-                                                       break;
-                                               }
-                                               default: {
-                                                       SAM("MISTAKE: %i=rump\n",
-                                                               bytesperpixel - rump);
-                                                       return -EFAULT;
-                                               }
-                                               }
-                                       } else {
-                                               *p3 = r;
-                                               *(p3 + 1) = g;
-                                               *(p3 + 2) = b;
-                                       }
-                                       p2 += 2;
-                                       if (isuy)
-                                               isuy = false;
-                                       else
-                                               isuy = true;
-                                       p3 += bytesperpixel;
-                               }
-                               return 0;
-                       } else {
-                               /* BGR */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               }
-                                       else
-                                               if (0x08 & mask)
-                                                       ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       tmp = ay[(int)y] + rv[(int)v];
-                                       r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
-                                       g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] + bu[(int)u];
-                                       b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                       if (last && rump) {
-                                               pcache = &peasycap->cache[0];
-                                               switch (bytesperpixel - rump) {
-                                               case 1: {
-                                                       *p3 = b;
-                                                       *pcache++ = g;
-                                                       *pcache++ = r;
-                                                       break;
-                                               }
-                                               case 2: {
-                                                       *p3 = b;
-                                                       *(p3 + 1) = g;
-                                                       *pcache++ = r;
-                                                       break;
-                                               }
-                                               default: {
-                                                       SAM("MISTAKE: %i=rump\n",
-                                                               bytesperpixel - rump);
-                                                       return -EFAULT;
-                                               }
-                                               }
-                                       } else {
-                                               *p3 = b;
-                                               *(p3 + 1) = g;
-                                               *(p3 + 2) = r;
-                                               }
-                                       p2 += 2;
-                                       if (isuy)
-                                               isuy = false;
-                                       else
-                                               isuy = true;
-                                       p3 += bytesperpixel;
-                                       }
-                               }
-                       return 0;
-               } else {
-                       if (!byteswaporder) {
-                               /*  RGB DECIMATED */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                       if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       if (isuy) {
-                                               tmp = ay[(int)y] + rv[(int)v];
-                                               r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] - gu[(int)u] -
-                                                                       gv[(int)v];
-                                               g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] + bu[(int)u];
-                                               b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                               if (last && rump) {
-                                                       pcache = &peasycap->cache[0];
-                                                       switch (bytesperpixel - rump) {
-                                                       case 1: {
-                                                               *p3 = r;
-                                                               *pcache++ = g;
-                                                               *pcache++ = b;
-                                                               break;
-                                                       }
-                                                       case 2: {
-                                                               *p3 = r;
-                                                               *(p3 + 1) = g;
-                                                               *pcache++ = b;
-                                                               break;
-                                                       }
-                                                       default: {
-                                                               SAM("MISTAKE: "
-                                                               "%i=rump\n",
-                                                               bytesperpixel - rump);
-                                                               return -EFAULT;
-                                                       }
-                                                       }
-                                               } else {
-                                                       *p3 = r;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = b;
-                                               }
-                                               isuy = false;
-                                               p3 += bytesperpixel;
-                                       } else {
-                                               isuy = true;
-                                       }
-                                       p2 += 2;
-                               }
-                               return 0;
-                       } else {
-                               /* BGR DECIMATED */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                       if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       if (isuy) {
-
-                                               tmp = ay[(int)y] + rv[(int)v];
-                                               r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] - gu[(int)u] -
-                                                                       gv[(int)v];
-                                               g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] + bu[(int)u];
-                                               b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                               if (last && rump) {
-                                                       pcache = &peasycap->cache[0];
-                                                       switch (bytesperpixel - rump) {
-                                                       case 1: {
-                                                               *p3 = b;
-                                                               *pcache++ = g;
-                                                               *pcache++ = r;
-                                                               break;
-                                                       }
-                                                       case 2: {
-                                                               *p3 = b;
-                                                               *(p3 + 1) = g;
-                                                               *pcache++ = r;
-                                                               break;
-                                                       }
-                                                       default: {
-                                                               SAM("MISTAKE: "
-                                                               "%i=rump\n",
-                                                               bytesperpixel - rump);
-                                                               return -EFAULT;
-                                                       }
-                                                       }
-                                               } else {
-                                                       *p3 = b;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = r;
-                                                       }
-                                               isuy = false;
-                                               p3 += bytesperpixel;
-                                               }
-                                       else
-                                               isuy = true;
-                                       p2 += 2;
-                                       }
-                               return 0;
-                               }
-                       }
-               break;
-               }
-       case 4:
-               {
-               if (!decimatepixel) {
-                       if (!byteswaporder) {
-                               /* RGBA */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                        if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       tmp = ay[(int)y] + rv[(int)v];
-                                       r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
-                                       g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] + bu[(int)u];
-                                       b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                       if (last && rump) {
-                                               pcache = &peasycap->cache[0];
-                                               switch (bytesperpixel - rump) {
-                                               case 1: {
-                                                       *p3 = r;
-                                                       *pcache++ = g;
-                                                       *pcache++ = b;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               case 2: {
-                                                       *p3 = r;
-                                                       *(p3 + 1) = g;
-                                                       *pcache++ = b;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               case 3: {
-                                                       *p3 = r;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = b;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               default: {
-                                                       SAM("MISTAKE: %i=rump\n",
-                                                               bytesperpixel - rump);
-                                                       return -EFAULT;
-                                               }
-                                               }
-                                       } else {
-                                               *p3 = r;
-                                               *(p3 + 1) = g;
-                                               *(p3 + 2) = b;
-                                               *(p3 + 3) = 0;
-                                       }
-                                       p2 += 2;
-                                       if (isuy)
-                                               isuy = false;
-                                       else
-                                               isuy = true;
-                                       p3 += bytesperpixel;
-                               }
-                               return 0;
-                       } else {
-                               /*
-                                *  BGRA
-                                */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                        if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       tmp = ay[(int)y] + rv[(int)v];
-                                       r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] - gu[(int)u] - gv[(int)v];
-                                       g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                       tmp = ay[(int)y] + bu[(int)u];
-                                       b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                       if (last && rump) {
-                                               pcache = &peasycap->cache[0];
-                                               switch (bytesperpixel - rump) {
-                                               case 1: {
-                                                       *p3 = b;
-                                                       *pcache++ = g;
-                                                       *pcache++ = r;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               case 2: {
-                                                       *p3 = b;
-                                                       *(p3 + 1) = g;
-                                                       *pcache++ = r;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               case 3: {
-                                                       *p3 = b;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = r;
-                                                       *pcache++ = 0;
-                                                       break;
-                                               }
-                                               default:
-                                                       SAM("MISTAKE: %i=rump\n",
-                                                               bytesperpixel - rump);
-                                                       return -EFAULT;
-                                               }
-                                       } else {
-                                               *p3 = b;
-                                               *(p3 + 1) = g;
-                                               *(p3 + 2) = r;
-                                               *(p3 + 3) = 0;
-                                       }
-                                       p2 += 2;
-                                       if (isuy)
-                                               isuy = false;
-                                       else
-                                               isuy = true;
-                                       p3 += bytesperpixel;
-                               }
-                       }
-                       return 0;
-               } else {
-                       if (!byteswaporder) {
-                               /*
-                                *  RGBA DECIMATED
-                                */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                       if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       if (isuy) {
-
-                                               tmp = ay[(int)y] + rv[(int)v];
-                                               r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] - gu[(int)u] -
-                                                                       gv[(int)v];
-                                               g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] + bu[(int)u];
-                                               b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                               if (last && rump) {
-                                                       pcache = &peasycap->cache[0];
-                                                       switch (bytesperpixel - rump) {
-                                                       case 1: {
-                                                               *p3 = r;
-                                                               *pcache++ = g;
-                                                               *pcache++ = b;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       case 2: {
-                                                               *p3 = r;
-                                                               *(p3 + 1) = g;
-                                                               *pcache++ = b;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       case 3: {
-                                                               *p3 = r;
-                                                               *(p3 + 1) = g;
-                                                               *(p3 + 2) = b;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       default: {
-                                                               SAM("MISTAKE: "
-                                                               "%i=rump\n",
-                                                               bytesperpixel -
-                                                               rump);
-                                                               return -EFAULT;
-                                                               }
-                                                       }
-                                               } else {
-                                                       *p3 = r;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = b;
-                                                       *(p3 + 3) = 0;
-                                                       }
-                                               isuy = false;
-                                               p3 += bytesperpixel;
-                                       } else
-                                               isuy = true;
-                                       p2 += 2;
-                               }
-                               return 0;
-                       } else {
-                               /*
-                                *  BGRA DECIMATED
-                                */
-                               while (pz > p2) {
-                                       if (pr <= (p3 + bytesperpixel))
-                                               last = true;
-                                       else
-                                               last = false;
-                                       y = *p2;
-                                       if (last && (0x0C & mask)) {
-                                               if (0x04 & mask) {
-                                                       if (isuy)
-                                                               v = margin;
-                                                       else
-                                                               u = margin;
-                                               } else
-                                                       if (0x08 & mask)
-                                                               ;
-                                       } else {
-                                               if (isuy)
-                                                       v = *(p2 + 1);
-                                               else
-                                                       u = *(p2 + 1);
-                                       }
-
-                                       if (isuy) {
-                                               tmp = ay[(int)y] + rv[(int)v];
-                                               r = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] - gu[(int)u] -
-                                                                       gv[(int)v];
-                                               g = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-                                               tmp = ay[(int)y] + bu[(int)u];
-                                               b = (255 < tmp) ? 255 : ((0 > tmp) ?
-                                                                       0 : (u8)tmp);
-
-                                               if (last && rump) {
-                                                       pcache = &peasycap->cache[0];
-                                                       switch (bytesperpixel - rump) {
-                                                       case 1: {
-                                                               *p3 = b;
-                                                               *pcache++ = g;
-                                                               *pcache++ = r;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       case 2: {
-                                                               *p3 = b;
-                                                               *(p3 + 1) = g;
-                                                               *pcache++ = r;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       case 3: {
-                                                               *p3 = b;
-                                                               *(p3 + 1) = g;
-                                                               *(p3 + 2) = r;
-                                                               *pcache++ = 0;
-                                                               break;
-                                                       }
-                                                       default: {
-                                                               SAM("MISTAKE: "
-                                                               "%i=rump\n",
-                                                               bytesperpixel - rump);
-                                                               return -EFAULT;
-                                                       }
-                                                       }
-                                               } else {
-                                                       *p3 = b;
-                                                       *(p3 + 1) = g;
-                                                       *(p3 + 2) = r;
-                                                       *(p3 + 3) = 0;
-                                               }
-                                               isuy = false;
-                                               p3 += bytesperpixel;
-                                       } else
-                                               isuy = true;
-                                               p2 += 2;
-                                       }
-                                       return 0;
-                               }
-                       }
-               break;
-               }
-       default: {
-               SAM("MISTAKE: %i=bytesperpixel\n", bytesperpixel);
-               return -EFAULT;
-               }
-       }
-       return 0;
-}
-/*****************************************************************************/
-/*
- *  SEE CORBET ET AL. "LINUX DEVICE DRIVERS", 3rd EDITION, PAGES 430-434
- */
-/*****************************************************************************/
-static void easycap_vma_open(struct vm_area_struct *pvma)
-{
-       struct easycap *peasycap;
-
-       peasycap = pvma->vm_private_data;
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return;
-       }
-       peasycap->vma_many++;
-       JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
-       return;
-}
-/*****************************************************************************/
-static void easycap_vma_close(struct vm_area_struct *pvma)
-{
-       struct easycap *peasycap;
-
-       peasycap = pvma->vm_private_data;
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return;
-       }
-       peasycap->vma_many--;
-       JOT(8, "%i=peasycap->vma_many\n", peasycap->vma_many);
-       return;
-}
-/*****************************************************************************/
-static int easycap_vma_fault(struct vm_area_struct *pvma, struct vm_fault *pvmf)
-{
-       int k, m, retcode;
-       void *pbuf;
-       struct page *page;
-       struct easycap *peasycap;
-
-       retcode = VM_FAULT_NOPAGE;
-
-       if (!pvma) {
-               SAY("pvma is NULL\n");
-               return retcode;
-       }
-       if (!pvmf) {
-               SAY("pvmf is NULL\n");
-               return retcode;
-       }
-
-       k = (pvmf->pgoff) / (FRAME_BUFFER_SIZE/PAGE_SIZE);
-       m = (pvmf->pgoff) % (FRAME_BUFFER_SIZE/PAGE_SIZE);
-
-       if (!m)
-               JOT(4, "%4i=k, %4i=m\n", k, m);
-       else
-               JOT(16, "%4i=k, %4i=m\n", k, m);
-
-       if ((0 > k) || (FRAME_BUFFER_MANY <= k)) {
-               SAY("ERROR: buffer index %i out of range\n", k);
-               return retcode;
-       }
-       if ((0 > m) || (FRAME_BUFFER_SIZE/PAGE_SIZE <= m)) {
-               SAY("ERROR: page number  %i out of range\n", m);
-               return retcode;
-       }
-       peasycap = pvma->vm_private_data;
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return retcode;
-       }
-/*---------------------------------------------------------------------------*/
-       pbuf = peasycap->frame_buffer[k][m].pgo;
-       if (!pbuf) {
-               SAM("ERROR:  pbuf is NULL\n");
-               return retcode;
-       }
-       page = virt_to_page(pbuf);
-       if (!page) {
-               SAM("ERROR:  page is NULL\n");
-               return retcode;
-       }
-       get_page(page);
-/*---------------------------------------------------------------------------*/
-       if (!page) {
-               SAM("ERROR:  page is NULL after get_page(page)\n");
-       } else {
-               pvmf->page = page;
-               retcode = VM_FAULT_MINOR;
-       }
-       return retcode;
-}
-
-static const struct vm_operations_struct easycap_vm_ops = {
-       .open  = easycap_vma_open,
-       .close = easycap_vma_close,
-       .fault = easycap_vma_fault,
-};
-
-static int easycap_mmap(struct file *file, struct vm_area_struct *pvma)
-{
-       JOT(8, "\n");
-
-       pvma->vm_ops = &easycap_vm_ops;
-       pvma->vm_flags |= VM_RESERVED;
-       if (file)
-               pvma->vm_private_data = file->private_data;
-       easycap_vma_open(pvma);
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  ON COMPLETION OF A VIDEO URB ITS DATA IS COPIED TO THE FIELD BUFFERS
- *  PROVIDED peasycap->video_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
- *  IT IS RESUBMITTED PROVIDED peasycap->video_isoc_streaming IS NOT ZERO.
- *
- *  THIS FUNCTION IS AN INTERRUPT SERVICE ROUTINE AND MUST NOT SLEEP.
- *
- *  INFORMATION ABOUT THE VALIDITY OF THE CONTENTS OF THE FIELD BUFFER ARE
- *  STORED IN THE TWO-BYTE STATUS PARAMETER
- *        peasycap->field_buffer[peasycap->field_fill][0].kount
- *  NOTICE THAT THE INFORMATION IS STORED ONLY WITH PAGE 0 OF THE FIELD BUFFER.
- *
- *  THE LOWER BYTE CONTAINS THE FIELD PARITY BYTE FURNISHED BY THE SAA7113H
- *  CHIP.
- *
- *  THE UPPER BYTE IS ZERO IF NO PROBLEMS, OTHERWISE:
- *      0 != (kount & 0x8000)   => AT LEAST ONE URB COMPLETED WITH ERRORS
- *      0 != (kount & 0x4000)   => BUFFER HAS TOO MUCH DATA
- *      0 != (kount & 0x2000)   => BUFFER HAS NOT ENOUGH DATA
- *      0 != (kount & 0x1000)   => BUFFER HAS DATA FROM DISPARATE INPUTS
- *      0 != (kount & 0x0400)   => RESERVED
- *      0 != (kount & 0x0200)   => FIELD BUFFER NOT YET CHECKED
- *      0 != (kount & 0x0100)   => BUFFER HAS TWO EXTRA BYTES - WHY?
- */
-/*---------------------------------------------------------------------------*/
-static void easycap_complete(struct urb *purb)
-{
-       struct easycap *peasycap;
-       struct data_buffer *pfield_buffer;
-       char errbuf[16];
-       int i, more, much, leap, rc, last;
-       int videofieldamount;
-       unsigned int override, bad;
-       int framestatus, framelength, frameactual, frameoffset;
-       u8 *pu;
-
-       if (!purb) {
-               SAY("ERROR: easycap_complete(): purb is NULL\n");
-               return;
-       }
-       peasycap = purb->context;
-       if (!peasycap) {
-               SAY("ERROR: easycap_complete(): peasycap is NULL\n");
-               return;
-       }
-       if (peasycap->video_eof)
-               return;
-       for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++)
-               if (purb->transfer_buffer == peasycap->video_isoc_buffer[i].pgo)
-                       break;
-       JOM(16, "%2i=urb\n", i);
-       last = peasycap->video_isoc_sequence;
-       if ((((VIDEO_ISOC_BUFFER_MANY - 1) == last) && (0 != i)) ||
-            (((VIDEO_ISOC_BUFFER_MANY - 1) != last) && ((last + 1) != i))) {
-               JOM(16, "ERROR: out-of-order urbs %i,%i ... continuing\n",
-                                               last, i);
-       }
-       peasycap->video_isoc_sequence = i;
-
-       if (peasycap->video_idle) {
-               JOM(16, "%i=video_idle  %i=video_isoc_streaming\n",
-                               peasycap->video_idle, peasycap->video_isoc_streaming);
-               if (peasycap->video_isoc_streaming) {
-                       rc = usb_submit_urb(purb, GFP_ATOMIC);
-                       if (rc) {
-                               SAM("%s:%d ENOMEM\n", strerror(rc), rc);
-                               if (-ENODEV != rc)
-                                       SAM("ERROR: while %i=video_idle, "
-                                                               "usb_submit_urb() "
-                                                               "failed with rc:\n",
-                                                               peasycap->video_idle);
-                       }
-               }
-       return;
-       }
-       override = 0;
-/*---------------------------------------------------------------------------*/
-       if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-               SAM("ERROR: bad peasycap->field_fill\n");
-               return;
-       }
-       if (purb->status) {
-               if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
-                       JOM(8, "urb status -ESHUTDOWN or -ENOENT\n");
-                       return;
-               }
-
-               (peasycap->field_buffer[peasycap->field_fill][0].kount) |= 0x8000 ;
-               SAM("ERROR: bad urb status -%s: %d\n",
-                               strerror(purb->status), purb->status);
-/*---------------------------------------------------------------------------*/
-       } else {
-               for (i = 0;  i < purb->number_of_packets; i++) {
-                       if (0 != purb->iso_frame_desc[i].status) {
-                               (peasycap->field_buffer
-                                       [peasycap->field_fill][0].kount) |= 0x8000 ;
-                               /* FIXME: 1. missing '-' check boundaries */
-                               strcpy(&errbuf[0],
-                                       strerror(purb->iso_frame_desc[i].status));
-                       }
-                       framestatus = purb->iso_frame_desc[i].status;
-                       framelength = purb->iso_frame_desc[i].length;
-                       frameactual = purb->iso_frame_desc[i].actual_length;
-                       frameoffset = purb->iso_frame_desc[i].offset;
-
-                       JOM(16, "frame[%2i]:"
-                                       "%4i=status "
-                                       "%4i=actual "
-                                       "%4i=length "
-                                       "%5i=offset\n",
-                               i, framestatus, frameactual, framelength, frameoffset);
-                       if (!purb->iso_frame_desc[i].status) {
-                               more = purb->iso_frame_desc[i].actual_length;
-                               pfield_buffer = &peasycap->field_buffer
-                                         [peasycap->field_fill][peasycap->field_page];
-                               videofieldamount = (peasycap->field_page *
-                                       PAGE_SIZE) +
-                                       (int)(pfield_buffer->pto - pfield_buffer->pgo);
-                       if (4 == more)
-                               peasycap->video_mt++;
-                       if (4 < more) {
-                               if (peasycap->video_mt) {
-                                       JOM(8, "%4i empty video urb frames\n",
-                                                               peasycap->video_mt);
-                                       peasycap->video_mt = 0;
-                               }
-                               if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-                                       SAM("ERROR: bad peasycap->field_fill\n");
-                                       return;
-                               }
-                               if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
-                                                               peasycap->field_page) {
-                                       SAM("ERROR: bad peasycap->field_page\n");
-                                       return;
-                               }
-                               pfield_buffer = &peasycap->field_buffer
-                                       [peasycap->field_fill][peasycap->field_page];
-                               pu = (u8 *)(purb->transfer_buffer +
-                                               purb->iso_frame_desc[i].offset);
-                               if (0x80 & *pu)
-                                       leap = 8;
-                               else
-                                       leap = 4;
-/*--------------------------------------------------------------------------*/
-/*
- *  EIGHT-BYTE END-OF-VIDEOFIELD MARKER.
- *  NOTE:  A SUCCESSION OF URB FRAMES FOLLOWING THIS ARE EMPTY,
- *         CORRESPONDING TO THE FIELD FLYBACK (VERTICAL BLANKING) PERIOD.
- *
- *  PROVIDED THE FIELD BUFFER CONTAINS GOOD DATA AS INDICATED BY A ZERO UPPER
- *  BYTE OF
- *        peasycap->field_buffer[peasycap->field_fill][0].kount
- *  THE CONTENTS OF THE FIELD BUFFER ARE OFFERED TO dqbuf(), field_read IS
- *  UPDATED AND field_fill IS BUMPED.  IF THE FIELD BUFFER CONTAINS BAD DATA
- *  NOTHING IS OFFERED TO dqbuf().
- *
- *  THE DECISION ON WHETHER THE PARITY OF THE OFFERED FIELD BUFFER IS RIGHT
- *  RESTS WITH dqbuf().
- */
-/*---------------------------------------------------------------------------*/
-                               if ((8 == more) || override) {
-                                       if (videofieldamount >
-                                                       peasycap->videofieldamount) {
-                                               if (2 == videofieldamount -
-                                                               peasycap->
-                                                               videofieldamount) {
-                                                       (peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                               [0].kount) |= 0x0100;
-                                                       peasycap->video_junk += (1 +
-                                                               VIDEO_JUNK_TOLERATE);
-                                               } else
-                                                       (peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                               [0].kount) |= 0x4000;
-                                               } else if (videofieldamount <
-                                                               peasycap->
-                                                               videofieldamount) {
-                                                       (peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                               [0].kount) |= 0x2000;
-                                               }
-                                               bad = 0xFF00 & peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                       [0].kount;
-                                               if (!bad) {
-                                                       (peasycap->video_junk)--;
-                                                       if (-VIDEO_JUNK_TOLERATE >
-                                                               peasycap->video_junk)
-                                                               peasycap->video_junk =
-                                                               -VIDEO_JUNK_TOLERATE;
-                                                       peasycap->field_read =
-                                                               (peasycap->
-                                                                       field_fill)++;
-                                                       if (FIELD_BUFFER_MANY <=
-                                                                       peasycap->
-                                                                       field_fill)
-                                                               peasycap->
-                                                                       field_fill = 0;
-                                                       peasycap->field_page = 0;
-                                                       pfield_buffer = &peasycap->
-                                                               field_buffer
-                                                               [peasycap->
-                                                               field_fill]
-                                                               [peasycap->
-                                                               field_page];
-                                                       pfield_buffer->pto =
-                                                               pfield_buffer->pgo;
-                                                       JOM(8, "bumped to: %i="
-                                                               "peasycap->"
-                                                               "field_fill  %i="
-                                                               "parity\n",
-                                                               peasycap->field_fill,
-                                                               0x00FF &
-                                                               pfield_buffer->kount);
-                                                       JOM(8, "field buffer %i has "
-                                                               "%i bytes fit to be "
-                                                               "read\n",
-                                                               peasycap->field_read,
-                                                               videofieldamount);
-                                                       JOM(8, "wakeup call to "
-                                                               "wq_video, "
-                                                               "%i=field_read "
-                                                               "%i=field_fill "
-                                                               "%i=parity\n",
-                                                               peasycap->field_read,
-                                                               peasycap->field_fill,
-                                                               0x00FF & peasycap->
-                                                               field_buffer
-                                                               [peasycap->
-                                                               field_read][0].kount);
-                                                       wake_up_interruptible
-                                                               (&(peasycap->
-                                                                        wq_video));
-                                               } else {
-                                               peasycap->video_junk++;
-                                               if (bad & 0x0010)
-                                                       peasycap->video_junk +=
-                                                       (1 + VIDEO_JUNK_TOLERATE/2);
-                                               JOM(8, "field buffer %i had %i "
-                                                       "bytes, now discarded: "
-                                                       "0x%04X\n",
-                                                       peasycap->field_fill,
-                                                       videofieldamount,
-                                                       (0xFF00 &
-                                                       peasycap->field_buffer
-                                                       [peasycap->field_fill][0].
-                                                       kount));
-                                               (peasycap->field_fill)++;
-
-                                               if (FIELD_BUFFER_MANY <=
-                                                               peasycap->field_fill)
-                                                       peasycap->field_fill = 0;
-                                               peasycap->field_page = 0;
-                                               pfield_buffer =
-                                                       &peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                       [peasycap->field_page];
-                                               pfield_buffer->pto =
-                                                               pfield_buffer->pgo;
-
-                                               JOM(8, "bumped to: %i=peasycap->"
-                                                       "field_fill  %i=parity\n",
-                                                       peasycap->field_fill,
-                                                       0x00FF & pfield_buffer->kount);
-                                       }
-                                       if (8 == more) {
-                                               JOM(8, "end-of-field: received "
-                                                       "parity byte 0x%02X\n",
-                                                       (0xFF & *pu));
-                                               if (0x40 & *pu)
-                                                       pfield_buffer->kount = 0x0000;
-                                               else
-                                                       pfield_buffer->kount = 0x0001;
-                                               pfield_buffer->input = 0x08 |
-                                                       (0x07 & peasycap->input);
-                                               JOM(8, "end-of-field: 0x%02X=kount\n",
-                                                       0xFF & pfield_buffer->kount);
-                                       }
-                               }
-/*---------------------------------------------------------------------------*/
-/*
- *  COPY more BYTES FROM ISOC BUFFER TO FIELD BUFFER
- */
-/*---------------------------------------------------------------------------*/
-                               pu += leap;
-                               more -= leap;
-
-                               if (FIELD_BUFFER_MANY <= peasycap->field_fill) {
-                                       SAM("ERROR: bad peasycap->field_fill\n");
-                                       return;
-                               }
-                               if (FIELD_BUFFER_SIZE/PAGE_SIZE <= peasycap->field_page) {
-                                       SAM("ERROR: bad peasycap->field_page\n");
-                                       return;
-                               }
-                               pfield_buffer = &peasycap->field_buffer
-                                       [peasycap->field_fill][peasycap->field_page];
-                               while (more) {
-                                       pfield_buffer = &peasycap->field_buffer
-                                                       [peasycap->field_fill]
-                                                       [peasycap->field_page];
-                                       if (PAGE_SIZE < (pfield_buffer->pto -
-                                                               pfield_buffer->pgo)) {
-                                               SAM("ERROR: bad pfield_buffer->pto\n");
-                                               return;
-                                       }
-                                       if (PAGE_SIZE == (pfield_buffer->pto -
-                                                               pfield_buffer->pgo)) {
-                                               (peasycap->field_page)++;
-                                               if (FIELD_BUFFER_SIZE/PAGE_SIZE <=
-                                                               peasycap->field_page) {
-                                                       JOM(16, "wrapping peasycap->"
-                                                               "field_page\n");
-                                                       peasycap->field_page = 0;
-                                               }
-                                               pfield_buffer = &peasycap->
-                                                               field_buffer
-                                                               [peasycap->field_fill]
-                                                               [peasycap->field_page];
-                                               pfield_buffer->pto = pfield_buffer->pgo;
-                                               pfield_buffer->input = 0x08 |
-                                                       (0x07 & peasycap->input);
-                                               if ((peasycap->field_buffer[peasycap->
-                                                               field_fill][0]).
-                                                                       input !=
-                                                               pfield_buffer->input)
-                                                       (peasycap->field_buffer
-                                                               [peasycap->field_fill]
-                                                               [0]).kount |= 0x1000;
-                                       }
-
-                                       much = PAGE_SIZE -
-                                               (int)(pfield_buffer->pto -
-                                                       pfield_buffer->pgo);
-
-                                       if (much > more)
-                                               much = more;
-                                       memcpy(pfield_buffer->pto, pu, much);
-                                       pu += much;
-                                       (pfield_buffer->pto) += much;
-                                       more -= much;
-                                       }
-                               }
-                       }
-               }
-       }
-/*---------------------------------------------------------------------------*/
-/*
- *  RESUBMIT THIS URB, UNLESS A SEVERE PERSISTENT ERROR CONDITION EXISTS.
- *
- *  IF THE WAIT QUEUES ARE NOT CLEARED IN RESPONSE TO AN ERROR CONDITION
- *  THE USERSPACE PROGRAM, E.G. mplayer, MAY HANG ON EXIT.   BEWARE.
- */
-/*---------------------------------------------------------------------------*/
-       if (VIDEO_ISOC_BUFFER_MANY <= peasycap->video_junk) {
-               SAM("easycap driver shutting down on condition green\n");
-               peasycap->status = 1;
-               peasycap->video_eof = 1;
-               peasycap->video_junk = 0;
-               wake_up_interruptible(&peasycap->wq_video);
-#if !defined(PERSEVERE)
-               peasycap->audio_eof = 1;
-               wake_up_interruptible(&peasycap->wq_audio);
-#endif /*PERSEVERE*/
-               return;
-       }
-       if (peasycap->video_isoc_streaming) {
-               rc = usb_submit_urb(purb, GFP_ATOMIC);
-               if (rc) {
-                       SAM("%s: %d\n", strerror(rc), rc);
-                       if (-ENODEV != rc)
-                               SAM("ERROR: while %i=video_idle, "
-                                       "usb_submit_urb() "
-                                       "failed with rc:\n",
-                                       peasycap->video_idle);
-               }
-       }
-       return;
-}
-
-static struct easycap *alloc_easycap(u8 bInterfaceNumber)
-{
-       struct easycap *peasycap;
-       int i;
-
-       peasycap = kzalloc(sizeof(struct easycap), GFP_KERNEL);
-       if (!peasycap) {
-               SAY("ERROR: Could not allocate peasycap\n");
-               return NULL;
-       }
-
-       if (mutex_lock_interruptible(&mutex_dongle)) {
-               SAY("ERROR: cannot lock mutex_dongle\n");
-               kfree(peasycap);
-               return NULL;
-       }
-
-       /* Find a free dongle in easycapdc60_dongle array */
-       for (i = 0; i < DONGLE_MANY; i++) {
-
-               if ((!easycapdc60_dongle[i].peasycap) &&
-                   (!mutex_is_locked(&easycapdc60_dongle[i].mutex_video)) &&
-                   (!mutex_is_locked(&easycapdc60_dongle[i].mutex_audio))) {
-
-                       easycapdc60_dongle[i].peasycap = peasycap;
-                       peasycap->isdongle = i;
-                       JOM(8, "intf[%i]: peasycap-->easycap"
-                               "_dongle[%i].peasycap\n",
-                               bInterfaceNumber, i);
-                       break;
-               }
-       }
-
-       mutex_unlock(&mutex_dongle);
-
-       if (i >= DONGLE_MANY) {
-               SAM("ERROR: too many dongles\n");
-               kfree(peasycap);
-               return NULL;
-       }
-
-       return peasycap;
-}
-
-static void free_easycap(struct easycap *peasycap)
-{
-       int allocation_video_urb;
-       int allocation_video_page;
-       int allocation_video_struct;
-       int allocation_audio_urb;
-       int allocation_audio_page;
-       int allocation_audio_struct;
-       int registered_video, registered_audio;
-       int kd;
-
-       JOM(4, "freeing easycap structure.\n");
-       allocation_video_urb    = peasycap->allocation_video_urb;
-       allocation_video_page   = peasycap->allocation_video_page;
-       allocation_video_struct = peasycap->allocation_video_struct;
-       registered_video        = peasycap->registered_video;
-       allocation_audio_urb    = peasycap->allocation_audio_urb;
-       allocation_audio_page   = peasycap->allocation_audio_page;
-       allocation_audio_struct = peasycap->allocation_audio_struct;
-       registered_audio        = peasycap->registered_audio;
-
-       kd = easycap_isdongle(peasycap);
-       if (0 <= kd && DONGLE_MANY > kd) {
-               if (mutex_lock_interruptible(&mutex_dongle)) {
-                       SAY("ERROR: cannot down mutex_dongle\n");
-               } else {
-                       JOM(4, "locked mutex_dongle\n");
-                       easycapdc60_dongle[kd].peasycap = NULL;
-                       mutex_unlock(&mutex_dongle);
-                       JOM(4, "unlocked mutex_dongle\n");
-                       JOT(4, "   null-->dongle[%i].peasycap\n", kd);
-                       allocation_video_struct -= sizeof(struct easycap);
-               }
-       } else {
-               SAY("ERROR: cannot purge dongle[].peasycap");
-       }
-
-       /* Free device structure */
-       kfree(peasycap);
-
-       SAY("%8i=video urbs    after all deletions\n", allocation_video_urb);
-       SAY("%8i=video pages   after all deletions\n", allocation_video_page);
-       SAY("%8i=video structs after all deletions\n", allocation_video_struct);
-       SAY("%8i=video devices after all deletions\n", registered_video);
-       SAY("%8i=audio urbs    after all deletions\n", allocation_audio_urb);
-       SAY("%8i=audio pages   after all deletions\n", allocation_audio_page);
-       SAY("%8i=audio structs after all deletions\n", allocation_audio_struct);
-       SAY("%8i=audio devices after all deletions\n", registered_audio);
-}
-
-/*
- * FIXME: Identify the appropriate pointer peasycap for interfaces
- * 1 and 2. The address of peasycap->pusb_device is reluctantly used
- * for this purpose.
- */
-static struct easycap *get_easycap(struct usb_device *usbdev,
-                                  u8 bInterfaceNumber)
-{
-       int i;
-       struct easycap *peasycap;
-
-       for (i = 0; i < DONGLE_MANY; i++) {
-               if (easycapdc60_dongle[i].peasycap->pusb_device == usbdev) {
-                       peasycap = easycapdc60_dongle[i].peasycap;
-                       JOT(8, "intf[%i]: dongle[%i].peasycap\n",
-                                       bInterfaceNumber, i);
-                       break;
-               }
-       }
-       if (i >= DONGLE_MANY) {
-               SAY("ERROR: peasycap is unknown when probing interface %i\n",
-                       bInterfaceNumber);
-               return NULL;
-       }
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL when probing interface %i\n",
-                       bInterfaceNumber);
-               return NULL;
-       }
-
-       return peasycap;
-}
-
-static void init_easycap(struct easycap *peasycap,
-                        struct usb_device *usbdev,
-                        struct usb_interface *intf,
-                        u8 bInterfaceNumber)
-{
-       /* Save usb_device and usb_interface */
-       peasycap->pusb_device = usbdev;
-       peasycap->pusb_interface = intf;
-
-       peasycap->minor = -1;
-       kref_init(&peasycap->kref);
-       JOM(8, "intf[%i]: after kref_init(..._video) "
-               "%i=peasycap->kref.refcount.counter\n",
-               bInterfaceNumber, peasycap->kref.refcount.counter);
-
-       /* module params */
-       peasycap->gain = (s8)clamp(easycap_gain, 0, 31);
-
-       init_waitqueue_head(&peasycap->wq_video);
-       init_waitqueue_head(&peasycap->wq_audio);
-       init_waitqueue_head(&peasycap->wq_trigger);
-
-       peasycap->allocation_video_struct = sizeof(struct easycap);
-
-       peasycap->microphone = false;
-
-       peasycap->video_interface = -1;
-       peasycap->video_altsetting_on = -1;
-       peasycap->video_altsetting_off = -1;
-       peasycap->video_endpointnumber = -1;
-       peasycap->video_isoc_maxframesize = -1;
-       peasycap->video_isoc_buffer_size = -1;
-
-       peasycap->audio_interface = -1;
-       peasycap->audio_altsetting_on = -1;
-       peasycap->audio_altsetting_off = -1;
-       peasycap->audio_endpointnumber = -1;
-       peasycap->audio_isoc_maxframesize = -1;
-       peasycap->audio_isoc_buffer_size = -1;
-
-       peasycap->frame_buffer_many = FRAME_BUFFER_MANY;
-
-       peasycap->ntsc = easycap_ntsc;
-       JOM(8, "defaulting initially to %s\n",
-               easycap_ntsc ? "NTSC" : "PAL");
-}
-
-static int populate_inputset(struct easycap *peasycap)
-{
-       struct inputset *inputset;
-       struct easycap_format *peasycap_format;
-       struct v4l2_pix_format *pix;
-       int m, i, k, mask, fmtidx;
-       s32 value;
-
-       inputset = peasycap->inputset;
-
-       fmtidx = peasycap->ntsc ? NTSC_M : PAL_BGHIN;
-
-       m = 0;
-       mask = 0;
-       for (i = 0; easycap_standard[i].mask != 0xffff; i++) {
-               if (fmtidx == easycap_standard[i].v4l2_standard.index) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].standard_offset = i;
-                       mask = easycap_standard[i].mask;
-               }
-       }
-
-       if (m != 1) {
-               SAM("ERROR: inputset->standard_offset unpopulated, %i=m\n", m);
-               return -ENOENT;
-       }
-
-       peasycap_format = &easycap_format[0];
-       m = 0;
-       for (i = 0; peasycap_format->v4l2_format.fmt.pix.width; i++) {
-               pix = &peasycap_format->v4l2_format.fmt.pix;
-               if (((peasycap_format->mask & 0x0F) == (mask & 0x0F))
-                       && pix->field == V4L2_FIELD_NONE
-                       && pix->pixelformat == V4L2_PIX_FMT_UYVY
-                       && pix->width  == 640 && pix->height == 480) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].format_offset = i;
-                       break;
-               }
-               peasycap_format++;
-       }
-       if (m != 1) {
-               SAM("ERROR: inputset[]->format_offset unpopulated\n");
-               return -ENOENT;
-       }
-
-       m = 0;
-       for (i = 0; easycap_control[i].id != 0xffffffff; i++) {
-               value = easycap_control[i].default_value;
-               if (V4L2_CID_BRIGHTNESS == easycap_control[i].id) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].brightness = value;
-               } else if (V4L2_CID_CONTRAST == easycap_control[i].id) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].contrast = value;
-               } else if (V4L2_CID_SATURATION == easycap_control[i].id) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].saturation = value;
-               } else if (V4L2_CID_HUE == easycap_control[i].id) {
-                       m++;
-                       for (k = 0; k < INPUT_MANY; k++)
-                               inputset[k].hue = value;
-               }
-       }
-
-       if (m != 4) {
-               SAM("ERROR: inputset[]->brightness underpopulated\n");
-               return -ENOENT;
-       }
-
-       for (k = 0; k < INPUT_MANY; k++)
-               inputset[k].input = k;
-       JOM(4, "populated inputset[]\n");
-
-       return 0;
-}
-
-static int alloc_framebuffers(struct easycap *peasycap)
-{
-       int i, j;
-       void *pbuf;
-
-       JOM(4, "allocating %i frame buffers of size %li\n",
-                       FRAME_BUFFER_MANY, (long int)FRAME_BUFFER_SIZE);
-       JOM(4, ".... each scattered over %li pages\n",
-                       FRAME_BUFFER_SIZE/PAGE_SIZE);
-
-       for (i = 0; i < FRAME_BUFFER_MANY; i++) {
-               for (j = 0; j < FRAME_BUFFER_SIZE/PAGE_SIZE; j++) {
-                       if (peasycap->frame_buffer[i][j].pgo)
-                               SAM("attempting to reallocate framebuffers\n");
-                       else {
-                               pbuf = (void *)__get_free_page(GFP_KERNEL);
-                               if (!pbuf) {
-                                       SAM("ERROR: Could not allocate "
-                                       "framebuffer %i page %i\n", i, j);
-                                       return -ENOMEM;
-                               }
-                               peasycap->allocation_video_page += 1;
-                               peasycap->frame_buffer[i][j].pgo = pbuf;
-                       }
-                       peasycap->frame_buffer[i][j].pto =
-                           peasycap->frame_buffer[i][j].pgo;
-               }
-       }
-
-       peasycap->frame_fill = 0;
-       peasycap->frame_read = 0;
-       JOM(4, "allocation of frame buffers done: %i pages\n", i*j);
-
-       return 0;
-}
-
-static void free_framebuffers(struct easycap *peasycap)
-{
-       int k, m, gone;
-
-       JOM(4, "freeing video frame buffers.\n");
-       gone = 0;
-       for (k = 0;  k < FRAME_BUFFER_MANY;  k++) {
-               for (m = 0;  m < FRAME_BUFFER_SIZE/PAGE_SIZE;  m++) {
-                       if (peasycap->frame_buffer[k][m].pgo) {
-                               free_page((unsigned long)
-                                       peasycap->frame_buffer[k][m].pgo);
-                               peasycap->frame_buffer[k][m].pgo = NULL;
-                               peasycap->allocation_video_page -= 1;
-                               gone++;
-                       }
-               }
-       }
-       JOM(4, "video frame buffers freed: %i pages\n", gone);
-}
-
-static int alloc_fieldbuffers(struct easycap *peasycap)
-{
-       int i, j;
-       void *pbuf;
-
-       JOM(4, "allocating %i field buffers of size %li\n",
-                       FIELD_BUFFER_MANY, (long int)FIELD_BUFFER_SIZE);
-       JOM(4, ".... each scattered over %li pages\n",
-                       FIELD_BUFFER_SIZE/PAGE_SIZE);
-
-       for (i = 0; i < FIELD_BUFFER_MANY; i++) {
-               for (j = 0; j < FIELD_BUFFER_SIZE/PAGE_SIZE; j++) {
-                       if (peasycap->field_buffer[i][j].pgo) {
-                               SAM("ERROR: attempting to reallocate "
-                                       "fieldbuffers\n");
-                       } else {
-                               pbuf = (void *) __get_free_page(GFP_KERNEL);
-                               if (!pbuf) {
-                                       SAM("ERROR: Could not allocate "
-                                       "fieldbuffer %i page %i\n", i, j);
-                                       return -ENOMEM;
-                               }
-                               peasycap->allocation_video_page += 1;
-                               peasycap->field_buffer[i][j].pgo = pbuf;
-                       }
-                       peasycap->field_buffer[i][j].pto =
-                               peasycap->field_buffer[i][j].pgo;
-               }
-               /* TODO: Hardcoded 0x0200 meaning? */
-               peasycap->field_buffer[i][0].kount = 0x0200;
-       }
-       peasycap->field_fill = 0;
-       peasycap->field_page = 0;
-       peasycap->field_read = 0;
-       JOM(4, "allocation of field buffers done:  %i pages\n", i*j);
-
-       return 0;
-}
-
-static void free_fieldbuffers(struct easycap *peasycap)
-{
-       int k, m, gone;
-
-       JOM(4, "freeing video field buffers.\n");
-       gone = 0;
-       for (k = 0;  k < FIELD_BUFFER_MANY;  k++) {
-               for (m = 0;  m < FIELD_BUFFER_SIZE/PAGE_SIZE;  m++) {
-                       if (peasycap->field_buffer[k][m].pgo) {
-                               free_page((unsigned long)
-                                         peasycap->field_buffer[k][m].pgo);
-                               peasycap->field_buffer[k][m].pgo = NULL;
-                               peasycap->allocation_video_page -= 1;
-                               gone++;
-                       }
-               }
-       }
-       JOM(4, "video field buffers freed: %i pages\n", gone);
-}
-
-static int alloc_isocbuffers(struct easycap *peasycap)
-{
-       int i;
-       void *pbuf;
-
-       JOM(4, "allocating %i isoc video buffers of size %i\n",
-                       VIDEO_ISOC_BUFFER_MANY,
-                       peasycap->video_isoc_buffer_size);
-       JOM(4, ".... each occupying contiguous memory pages\n");
-
-       for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
-               pbuf = (void *)__get_free_pages(GFP_KERNEL,
-                               VIDEO_ISOC_ORDER);
-               if (!pbuf) {
-                       SAM("ERROR: Could not allocate isoc "
-                               "video buffer %i\n", i);
-                       return -ENOMEM;
-               }
-               peasycap->allocation_video_page += BIT(VIDEO_ISOC_ORDER);
-
-               peasycap->video_isoc_buffer[i].pgo = pbuf;
-               peasycap->video_isoc_buffer[i].pto =
-                       pbuf + peasycap->video_isoc_buffer_size;
-               peasycap->video_isoc_buffer[i].kount = i;
-       }
-       JOM(4, "allocation of isoc video buffers done: %i pages\n",
-                       i * (0x01 << VIDEO_ISOC_ORDER));
-       return 0;
-}
-
-static void free_isocbuffers(struct easycap *peasycap)
-{
-       int k, m;
-
-       JOM(4, "freeing video isoc buffers.\n");
-       m = 0;
-       for (k = 0;  k < VIDEO_ISOC_BUFFER_MANY;  k++) {
-               if (peasycap->video_isoc_buffer[k].pgo) {
-                       free_pages((unsigned long)
-                                  peasycap->video_isoc_buffer[k].pgo,
-                                       VIDEO_ISOC_ORDER);
-                       peasycap->video_isoc_buffer[k].pgo = NULL;
-                       peasycap->allocation_video_page -=
-                                               BIT(VIDEO_ISOC_ORDER);
-                       m++;
-               }
-       }
-       JOM(4, "isoc video buffers freed: %i pages\n",
-                       m * (0x01 << VIDEO_ISOC_ORDER));
-}
-
-static int create_video_urbs(struct easycap *peasycap)
-{
-       struct urb *purb;
-       struct data_urb *pdata_urb;
-       int i, j;
-
-       JOM(4, "allocating %i struct urb.\n", VIDEO_ISOC_BUFFER_MANY);
-       JOM(4, "using %i=peasycap->video_isoc_framesperdesc\n",
-                       peasycap->video_isoc_framesperdesc);
-       JOM(4, "using %i=peasycap->video_isoc_maxframesize\n",
-                       peasycap->video_isoc_maxframesize);
-       JOM(4, "using %i=peasycap->video_isoc_buffer_sizen",
-                       peasycap->video_isoc_buffer_size);
-
-       for (i = 0; i < VIDEO_ISOC_BUFFER_MANY; i++) {
-               purb = usb_alloc_urb(peasycap->video_isoc_framesperdesc,
-                               GFP_KERNEL);
-               if (!purb) {
-                       SAM("ERROR: usb_alloc_urb returned NULL for buffer "
-                               "%i\n", i);
-                       return -ENOMEM;
-               }
-
-               peasycap->allocation_video_urb += 1;
-               pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
-               if (!pdata_urb) {
-                       usb_free_urb(purb);
-                       SAM("ERROR: Could not allocate struct data_urb.\n");
-                       return -ENOMEM;
-               }
-
-               peasycap->allocation_video_struct +=
-                       sizeof(struct data_urb);
-
-               pdata_urb->purb = purb;
-               pdata_urb->isbuf = i;
-               pdata_urb->length = 0;
-               list_add_tail(&(pdata_urb->list_head),
-                               peasycap->purb_video_head);
-
-               if (!i) {
-                       JOM(4, "initializing video urbs thus:\n");
-                       JOM(4, "  purb->interval = 1;\n");
-                       JOM(4, "  purb->dev = peasycap->pusb_device;\n");
-                       JOM(4, "  purb->pipe = usb_rcvisocpipe"
-                                       "(peasycap->pusb_device,%i);\n",
-                                       peasycap->video_endpointnumber);
-                       JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
-                       JOM(4, "  purb->transfer_buffer = peasycap->"
-                                       "video_isoc_buffer[.].pgo;\n");
-                       JOM(4, "  purb->transfer_buffer_length = %i;\n",
-                                       peasycap->video_isoc_buffer_size);
-                       JOM(4, "  purb->complete = easycap_complete;\n");
-                       JOM(4, "  purb->context = peasycap;\n");
-                       JOM(4, "  purb->start_frame = 0;\n");
-                       JOM(4, "  purb->number_of_packets = %i;\n",
-                                       peasycap->video_isoc_framesperdesc);
-                       JOM(4, "  for (j = 0; j < %i; j++)\n",
-                                       peasycap->video_isoc_framesperdesc);
-                       JOM(4, "    {\n");
-                       JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
-                                       peasycap->video_isoc_maxframesize);
-                       JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
-                                       peasycap->video_isoc_maxframesize);
-                       JOM(4, "    }\n");
-               }
-
-               purb->interval = 1;
-               purb->dev = peasycap->pusb_device;
-               purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
-                               peasycap->video_endpointnumber);
-
-               purb->transfer_flags = URB_ISO_ASAP;
-               purb->transfer_buffer = peasycap->video_isoc_buffer[i].pgo;
-               purb->transfer_buffer_length =
-                       peasycap->video_isoc_buffer_size;
-
-               purb->complete = easycap_complete;
-               purb->context = peasycap;
-               purb->start_frame = 0;
-               purb->number_of_packets = peasycap->video_isoc_framesperdesc;
-
-               for (j = 0; j < peasycap->video_isoc_framesperdesc; j++) {
-                       purb->iso_frame_desc[j].offset =
-                               j * peasycap->video_isoc_maxframesize;
-                       purb->iso_frame_desc[j].length =
-                               peasycap->video_isoc_maxframesize;
-               }
-       }
-       JOM(4, "allocation of %i struct urb done.\n", i);
-       return 0;
-}
-
-static void free_video_urbs(struct easycap *peasycap)
-{
-       struct list_head *plist_head, *plist_next;
-       struct data_urb *pdata_urb;
-       int m;
-
-       if (peasycap->purb_video_head) {
-               m = 0;
-               list_for_each(plist_head, peasycap->purb_video_head) {
-                       pdata_urb = list_entry(plist_head,
-                                       struct data_urb, list_head);
-                       if (pdata_urb && pdata_urb->purb) {
-                               usb_free_urb(pdata_urb->purb);
-                               pdata_urb->purb = NULL;
-                               peasycap->allocation_video_urb--;
-                               m++;
-                       }
-               }
-
-               JOM(4, "%i video urbs freed\n", m);
-               JOM(4, "freeing video data_urb structures.\n");
-               m = 0;
-               list_for_each_safe(plist_head, plist_next,
-                                       peasycap->purb_video_head) {
-                       pdata_urb = list_entry(plist_head,
-                                       struct data_urb, list_head);
-                       if (pdata_urb) {
-                               peasycap->allocation_video_struct -=
-                                       sizeof(struct data_urb);
-                               kfree(pdata_urb);
-                               m++;
-                       }
-               }
-               JOM(4, "%i video data_urb structures freed\n", m);
-               JOM(4, "setting peasycap->purb_video_head=NULL\n");
-               peasycap->purb_video_head = NULL;
-       }
-}
-
-static int alloc_audio_buffers(struct easycap *peasycap)
-{
-       void *pbuf;
-       int k;
-
-       JOM(4, "allocating %i isoc audio buffers of size %i\n",
-               AUDIO_ISOC_BUFFER_MANY,
-               peasycap->audio_isoc_buffer_size);
-       JOM(4, ".... each occupying contiguous memory pages\n");
-
-       for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
-               pbuf = (void *)__get_free_pages(GFP_KERNEL, AUDIO_ISOC_ORDER);
-               if (!pbuf) {
-                       SAM("ERROR: Could not allocate isoc audio buffer %i\n",
-                           k);
-                               return -ENOMEM;
-               }
-               peasycap->allocation_audio_page += BIT(AUDIO_ISOC_ORDER);
-
-               peasycap->audio_isoc_buffer[k].pgo = pbuf;
-               peasycap->audio_isoc_buffer[k].pto =
-                       pbuf + peasycap->audio_isoc_buffer_size;
-               peasycap->audio_isoc_buffer[k].kount = k;
-       }
-
-       JOM(4, "allocation of isoc audio buffers done.\n");
-       return 0;
-}
-
-static void free_audio_buffers(struct easycap *peasycap)
-{
-       int k, m;
-
-       JOM(4, "freeing audio isoc buffers.\n");
-       m = 0;
-       for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY;  k++) {
-               if (peasycap->audio_isoc_buffer[k].pgo) {
-                       free_pages((unsigned long)
-                                       (peasycap->audio_isoc_buffer[k].pgo),
-                                       AUDIO_ISOC_ORDER);
-                       peasycap->audio_isoc_buffer[k].pgo = NULL;
-                       peasycap->allocation_audio_page -=
-                                       BIT(AUDIO_ISOC_ORDER);
-                       m++;
-               }
-       }
-       JOM(4, "easyoss_delete(): isoc audio buffers freed: %i pages\n",
-                                       m * (0x01 << AUDIO_ISOC_ORDER));
-}
-
-static int create_audio_urbs(struct easycap *peasycap)
-{
-       struct urb *purb;
-       struct data_urb *pdata_urb;
-       int k, j;
-
-       JOM(4, "allocating %i struct urb.\n", AUDIO_ISOC_BUFFER_MANY);
-       JOM(4, "using %i=peasycap->audio_isoc_framesperdesc\n",
-               peasycap->audio_isoc_framesperdesc);
-       JOM(4, "using %i=peasycap->audio_isoc_maxframesize\n",
-               peasycap->audio_isoc_maxframesize);
-       JOM(4, "using %i=peasycap->audio_isoc_buffer_size\n",
-               peasycap->audio_isoc_buffer_size);
-
-       for (k = 0;  k < AUDIO_ISOC_BUFFER_MANY; k++) {
-               purb = usb_alloc_urb(peasycap->audio_isoc_framesperdesc,
-                                    GFP_KERNEL);
-               if (!purb) {
-                       SAM("ERROR: usb_alloc_urb returned NULL for buffer "
-                            "%i\n", k);
-                       return -ENOMEM;
-               }
-               peasycap->allocation_audio_urb += 1 ;
-               pdata_urb = kzalloc(sizeof(struct data_urb), GFP_KERNEL);
-               if (!pdata_urb) {
-                       usb_free_urb(purb);
-                       SAM("ERROR: Could not allocate struct data_urb.\n");
-                       return -ENOMEM;
-               }
-               peasycap->allocation_audio_struct +=
-                       sizeof(struct data_urb);
-
-               pdata_urb->purb = purb;
-               pdata_urb->isbuf = k;
-               pdata_urb->length = 0;
-               list_add_tail(&(pdata_urb->list_head),
-                               peasycap->purb_audio_head);
-
-               if (!k) {
-                       JOM(4, "initializing audio urbs thus:\n");
-                       JOM(4, "  purb->interval = 1;\n");
-                       JOM(4, "  purb->dev = peasycap->pusb_device;\n");
-                       JOM(4, "  purb->pipe = usb_rcvisocpipe(peasycap->"
-                               "pusb_device,%i);\n",
-                               peasycap->audio_endpointnumber);
-                       JOM(4, "  purb->transfer_flags = URB_ISO_ASAP;\n");
-                       JOM(4, "  purb->transfer_buffer = "
-                               "peasycap->audio_isoc_buffer[.].pgo;\n");
-                       JOM(4, "  purb->transfer_buffer_length = %i;\n",
-                               peasycap->audio_isoc_buffer_size);
-                       JOM(4, "  purb->complete = easycap_alsa_complete;\n");
-                       JOM(4, "  purb->context = peasycap;\n");
-                       JOM(4, "  purb->start_frame = 0;\n");
-                       JOM(4, "  purb->number_of_packets = %i;\n",
-                               peasycap->audio_isoc_framesperdesc);
-                       JOM(4, "  for (j = 0; j < %i; j++)\n",
-                               peasycap->audio_isoc_framesperdesc);
-                       JOM(4, "    {\n");
-                       JOM(4, "    purb->iso_frame_desc[j].offset = j*%i;\n",
-                               peasycap->audio_isoc_maxframesize);
-                       JOM(4, "    purb->iso_frame_desc[j].length = %i;\n",
-                               peasycap->audio_isoc_maxframesize);
-                       JOM(4, "    }\n");
-               }
-
-               purb->interval = 1;
-               purb->dev = peasycap->pusb_device;
-               purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
-                                            peasycap->audio_endpointnumber);
-               purb->transfer_flags = URB_ISO_ASAP;
-               purb->transfer_buffer = peasycap->audio_isoc_buffer[k].pgo;
-               purb->transfer_buffer_length =
-                       peasycap->audio_isoc_buffer_size;
-               purb->complete = easycap_alsa_complete;
-               purb->context = peasycap;
-               purb->start_frame = 0;
-               purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
-               for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
-                       purb->iso_frame_desc[j].offset =
-                               j * peasycap->audio_isoc_maxframesize;
-                       purb->iso_frame_desc[j].length =
-                               peasycap->audio_isoc_maxframesize;
-               }
-       }
-       JOM(4, "allocation of %i struct urb done.\n", k);
-       return 0;
-}
-
-static void free_audio_urbs(struct easycap *peasycap)
-{
-       struct list_head *plist_head, *plist_next;
-       struct data_urb *pdata_urb;
-       int m;
-
-       if (peasycap->purb_audio_head) {
-               JOM(4, "freeing audio urbs\n");
-               m = 0;
-               list_for_each(plist_head, (peasycap->purb_audio_head)) {
-                       pdata_urb = list_entry(plist_head,
-                                       struct data_urb, list_head);
-                       if (pdata_urb && pdata_urb->purb) {
-                               usb_free_urb(pdata_urb->purb);
-                               pdata_urb->purb = NULL;
-                               peasycap->allocation_audio_urb--;
-                               m++;
-                       }
-               }
-               JOM(4, "%i audio urbs freed\n", m);
-               JOM(4, "freeing audio data_urb structures.\n");
-               m = 0;
-               list_for_each_safe(plist_head, plist_next,
-                                       peasycap->purb_audio_head) {
-                       pdata_urb = list_entry(plist_head,
-                                       struct data_urb, list_head);
-                       if (pdata_urb) {
-                               peasycap->allocation_audio_struct -=
-                                                       sizeof(struct data_urb);
-                               kfree(pdata_urb);
-                               m++;
-                       }
-               }
-               JOM(4, "%i audio data_urb structures freed\n", m);
-               JOM(4, "setting peasycap->purb_audio_head=NULL\n");
-               peasycap->purb_audio_head = NULL;
-       }
-}
-
-static void config_easycap(struct easycap *peasycap,
-                          u8 bInterfaceNumber,
-                          u8 bInterfaceClass,
-                          u8 bInterfaceSubClass)
-{
-       if ((USB_CLASS_VIDEO == bInterfaceClass) ||
-           (USB_CLASS_VENDOR_SPEC == bInterfaceClass)) {
-               if (-1 == peasycap->video_interface) {
-                       peasycap->video_interface = bInterfaceNumber;
-                       JOM(4, "setting peasycap->video_interface=%i\n",
-                               peasycap->video_interface);
-               } else {
-                       if (peasycap->video_interface != bInterfaceNumber) {
-                               SAM("ERROR: attempting to reset "
-                                   "peasycap->video_interface\n");
-                               SAM("...... continuing with "
-                                   "%i=peasycap->video_interface\n",
-                                   peasycap->video_interface);
-                       }
-               }
-       } else if ((USB_CLASS_AUDIO == bInterfaceClass) &&
-                  (USB_SUBCLASS_AUDIOSTREAMING == bInterfaceSubClass)) {
-               if (-1 == peasycap->audio_interface) {
-                       peasycap->audio_interface = bInterfaceNumber;
-                       JOM(4, "setting peasycap->audio_interface=%i\n",
-                               peasycap->audio_interface);
-               } else {
-                       if (peasycap->audio_interface != bInterfaceNumber) {
-                               SAM("ERROR: attempting to reset "
-                                   "peasycap->audio_interface\n");
-                               SAM("...... continuing with "
-                                   "%i=peasycap->audio_interface\n",
-                                   peasycap->audio_interface);
-                       }
-               }
-       }
-}
-
-/*
- * This function is called from within easycap_usb_disconnect() and is
- * protected by semaphores set and cleared by easycap_usb_disconnect().
- * By this stage the device has already been physically unplugged,
- * so peasycap->pusb_device is no longer valid.
- */
-static void easycap_delete(struct kref *pkref)
-{
-       struct easycap *peasycap;
-
-       peasycap = container_of(pkref, struct easycap, kref);
-       if (!peasycap) {
-               SAM("ERROR: peasycap is NULL: cannot perform deletions\n");
-               return;
-       }
-
-       /* Free video urbs */
-       free_video_urbs(peasycap);
-
-       /* Free video isoc buffers */
-       free_isocbuffers(peasycap);
-
-       /* Free video field buffers */
-       free_fieldbuffers(peasycap);
-
-       /* Free video frame buffers */
-       free_framebuffers(peasycap);
-
-       /* Free audio urbs */
-       free_audio_urbs(peasycap);
-
-       /* Free audio isoc buffers */
-       free_audio_buffers(peasycap);
-
-       free_easycap(peasycap);
-
-       JOT(4, "ending.\n");
-}
-
-static const struct v4l2_file_operations v4l2_fops = {
-       .owner          = THIS_MODULE,
-       .open           = easycap_open_noinode,
-       .unlocked_ioctl = easycap_unlocked_ioctl,
-       .poll           = easycap_poll,
-       .mmap           = easycap_mmap,
-};
-
-static int easycap_register_video(struct easycap *peasycap)
-{
-       /*
-        * FIXME: This is believed to be harmless,
-        * but may well be unnecessary or wrong.
-        */
-       peasycap->video_device.v4l2_dev = NULL;
-
-       strcpy(&peasycap->video_device.name[0], "easycapdc60");
-       peasycap->video_device.fops = &v4l2_fops;
-       peasycap->video_device.minor = -1;
-       peasycap->video_device.release = (void *)(&videodev_release);
-
-       video_set_drvdata(&(peasycap->video_device), (void *)peasycap);
-
-       if (0 != (video_register_device(&(peasycap->video_device),
-                                       VFL_TYPE_GRABBER, -1))) {
-               videodev_release(&(peasycap->video_device));
-               return -ENODEV;
-       }
-
-       peasycap->registered_video++;
-
-       SAM("registered with videodev: %i=minor\n",
-           peasycap->video_device.minor);
-           peasycap->minor = peasycap->video_device.minor;
-
-       return 0;
-}
-
-/*
- * When the device is plugged, this function is called three times,
- * one for each interface.
- */
-static int easycap_usb_probe(struct usb_interface *intf,
-                           const struct usb_device_id *id)
-{
-       struct usb_device *usbdev;
-       struct usb_host_interface *alt;
-       struct usb_endpoint_descriptor *ep;
-       struct usb_interface_descriptor *interface;
-       struct easycap *peasycap;
-       int i, j, rc;
-       u8 bInterfaceNumber;
-       u8 bInterfaceClass;
-       u8 bInterfaceSubClass;
-       int okalt[8], isokalt;
-       int okepn[8];
-       int okmps[8];
-       int maxpacketsize;
-
-       usbdev = interface_to_usbdev(intf);
-
-       alt = usb_altnum_to_altsetting(intf, 0);
-       if (!alt) {
-               SAY("ERROR: usb_host_interface not found\n");
-               return -EFAULT;
-       }
-
-       interface = &alt->desc;
-       if (!interface) {
-               SAY("ERROR: intf_descriptor is NULL\n");
-               return -EFAULT;
-       }
-
-       /* Get properties of probed interface */
-       bInterfaceNumber = interface->bInterfaceNumber;
-       bInterfaceClass = interface->bInterfaceClass;
-       bInterfaceSubClass = interface->bInterfaceSubClass;
-
-       JOT(4, "intf[%i]: num_altsetting=%i\n",
-                       bInterfaceNumber, intf->num_altsetting);
-       JOT(4, "intf[%i]: cur_altsetting - altsetting=%li\n",
-               bInterfaceNumber,
-               (long int)(intf->cur_altsetting - intf->altsetting));
-       JOT(4, "intf[%i]: bInterfaceClass=0x%02X bInterfaceSubClass=0x%02X\n",
-                       bInterfaceNumber, bInterfaceClass, bInterfaceSubClass);
-
-       /*
-        * A new struct easycap is always allocated when interface 0 is probed.
-        * It is not possible here to free any existing struct easycap.
-        * This should have been done by easycap_delete() when the device was
-        * physically unplugged.
-        * The allocated struct easycap is saved for later usage when
-        * interfaces 1 and 2 are probed.
-        */
-       if (0 == bInterfaceNumber) {
-               /*
-                * Alloc structure and save it in a free slot in
-                * easycapdc60_dongle array
-                */
-               peasycap = alloc_easycap(bInterfaceNumber);
-               if (!peasycap)
-                       return -ENOMEM;
-
-               /* Perform basic struct initialization */
-               init_easycap(peasycap, usbdev, intf, bInterfaceNumber);
-
-               /* Dynamically fill in the available formats */
-               rc = easycap_video_fillin_formats();
-               if (0 > rc) {
-                       SAM("ERROR: fillin_formats() rc = %i\n", rc);
-                       return -EFAULT;
-               }
-               JOM(4, "%i formats available\n", rc);
-
-               /* Populate easycap.inputset[] */
-               rc = populate_inputset(peasycap);
-               if (rc < 0)
-                       return rc;
-               JOM(4, "finished initialization\n");
-       } else {
-               peasycap = get_easycap(usbdev, bInterfaceNumber);
-               if (!peasycap)
-                       return -ENODEV;
-       }
-
-       config_easycap(peasycap, bInterfaceNumber,
-                                bInterfaceClass,
-                                bInterfaceSubClass);
-
-       /*
-        * Investigate all altsettings. This is done in detail
-        * because USB device 05e1:0408 has disparate incarnations.
-        */
-       isokalt = 0;
-       for (i = 0; i < intf->num_altsetting; i++) {
-               alt = usb_altnum_to_altsetting(intf, i);
-               if (!alt) {
-                       SAM("ERROR: alt is NULL\n");
-                       return -EFAULT;
-               }
-               interface = &alt->desc;
-               if (!interface) {
-                       SAM("ERROR: intf_descriptor is NULL\n");
-                       return -EFAULT;
-               }
-
-               if (0 == interface->bNumEndpoints)
-                       JOM(4, "intf[%i]alt[%i] has no endpoints\n",
-                                               bInterfaceNumber, i);
-               for (j = 0; j < interface->bNumEndpoints; j++) {
-                       ep = &alt->endpoint[j].desc;
-                       if (!ep) {
-                               SAM("ERROR:  ep is NULL.\n");
-                               SAM("...... skipping\n");
-                               continue;
-                       }
-
-                       if (!usb_endpoint_is_isoc_in(ep)) {
-                               JOM(4, "intf[%i]alt[%i]end[%i] is a %d endpoint\n",
-                                               bInterfaceNumber,
-                                               i, j, ep->bmAttributes);
-                               if (usb_endpoint_dir_out(ep)) {
-                                       SAM("ERROR: OUT endpoint unexpected\n");
-                                       SAM("...... continuing\n");
-                               }
-                               continue;
-                       }
-                       switch (bInterfaceClass) {
-                       case USB_CLASS_VIDEO:
-                       case USB_CLASS_VENDOR_SPEC: {
-                               if (ep->wMaxPacketSize) {
-                                       if (8 > isokalt) {
-                                               okalt[isokalt] = i;
-                                               JOM(4,
-                                               "%i=okalt[%i]\n",
-                                               okalt[isokalt],
-                                               isokalt);
-                                               okepn[isokalt] =
-                                               ep->
-                                               bEndpointAddress &
-                                               0x0F;
-                                               JOM(4,
-                                               "%i=okepn[%i]\n",
-                                               okepn[isokalt],
-                                               isokalt);
-                                               okmps[isokalt] =
-                                               le16_to_cpu(ep->
-                                               wMaxPacketSize);
-                                               JOM(4,
-                                               "%i=okmps[%i]\n",
-                                               okmps[isokalt],
-                                               isokalt);
-                                               isokalt++;
-                                       }
-                               } else {
-                                       if (-1 == peasycap->
-                                               video_altsetting_off) {
-                                               peasycap->
-                                               video_altsetting_off =
-                                                                i;
-                                               JOM(4, "%i=video_"
-                                               "altsetting_off "
-                                                       "<====\n",
-                                               peasycap->
-                                               video_altsetting_off);
-                                       } else {
-                                               SAM("ERROR: peasycap"
-                                               "->video_altsetting_"
-                                               "off already set\n");
-                                               SAM("...... "
-                                               "continuing with "
-                                               "%i=peasycap->video_"
-                                               "altsetting_off\n",
-                                               peasycap->
-                                               video_altsetting_off);
-                                       }
-                               }
-                               break;
-                       }
-                       case USB_CLASS_AUDIO: {
-                               if (bInterfaceSubClass !=
-                                   USB_SUBCLASS_AUDIOSTREAMING)
-                                       break;
-                               if (!peasycap) {
-                                       SAM("MISTAKE: "
-                                       "peasycap is NULL\n");
-                                       return -EFAULT;
-                               }
-                               if (ep->wMaxPacketSize) {
-                                       if (8 > isokalt) {
-                                               okalt[isokalt] = i ;
-                                               JOM(4,
-                                               "%i=okalt[%i]\n",
-                                               okalt[isokalt],
-                                               isokalt);
-                                               okepn[isokalt] =
-                                               ep->
-                                               bEndpointAddress &
-                                               0x0F;
-                                               JOM(4,
-                                               "%i=okepn[%i]\n",
-                                               okepn[isokalt],
-                                               isokalt);
-                                               okmps[isokalt] =
-                                               le16_to_cpu(ep->
-                                               wMaxPacketSize);
-                                               JOM(4,
-                                               "%i=okmps[%i]\n",
-                                               okmps[isokalt],
-                                               isokalt);
-                                               isokalt++;
-                                       }
-                               } else {
-                                       if (-1 == peasycap->
-                                               audio_altsetting_off) {
-                                               peasycap->
-                                               audio_altsetting_off =
-                                                                i;
-                                               JOM(4, "%i=audio_"
-                                               "altsetting_off "
-                                               "<====\n",
-                                               peasycap->
-                                               audio_altsetting_off);
-                                       } else {
-                                               SAM("ERROR: peasycap"
-                                               "->audio_altsetting_"
-                                               "off already set\n");
-                                               SAM("...... "
-                                               "continuing with "
-                                               "%i=peasycap->"
-                                               "audio_altsetting_"
-                                               "off\n",
-                                               peasycap->
-                                               audio_altsetting_off);
-                                       }
-                               }
-                       break;
-                       }
-                       default:
-                               break;
-                       }
-                       if (0 == ep->wMaxPacketSize) {
-                               JOM(4, "intf[%i]alt[%i]end[%i] "
-                                                       "has zero packet size\n",
-                                                       bInterfaceNumber, i, j);
-                       }
-               }
-       }
-
-       /* Perform initialization of the probed interface */
-       JOM(4, "initialization begins for interface %i\n",
-               interface->bInterfaceNumber);
-       switch (bInterfaceNumber) {
-       /* 0: Video interface */
-       case 0: {
-               if (!peasycap) {
-                       SAM("MISTAKE: peasycap is NULL\n");
-                       return -EFAULT;
-               }
-               if (!isokalt) {
-                       SAM("ERROR:  no viable video_altsetting_on\n");
-                       return -ENOENT;
-               }
-               peasycap->video_altsetting_on = okalt[isokalt - 1];
-               JOM(4, "%i=video_altsetting_on <====\n",
-                                       peasycap->video_altsetting_on);
-
-               /* Decide video streaming parameters */
-               peasycap->video_endpointnumber = okepn[isokalt - 1];
-               JOM(4, "%i=video_endpointnumber\n", peasycap->video_endpointnumber);
-               maxpacketsize = okmps[isokalt - 1];
-
-               peasycap->video_isoc_maxframesize =
-                               min(maxpacketsize, USB_2_0_MAXPACKETSIZE);
-               if (0 >= peasycap->video_isoc_maxframesize) {
-                       SAM("ERROR:  bad video_isoc_maxframesize\n");
-                       SAM("        possibly because port is USB 1.1\n");
-                       return -ENOENT;
-               }
-               JOM(4, "%i=video_isoc_maxframesize\n",
-                                       peasycap->video_isoc_maxframesize);
-
-               peasycap->video_isoc_framesperdesc = VIDEO_ISOC_FRAMESPERDESC;
-               JOM(4, "%i=video_isoc_framesperdesc\n",
-                                       peasycap->video_isoc_framesperdesc);
-               if (0 >= peasycap->video_isoc_framesperdesc) {
-                       SAM("ERROR:  bad video_isoc_framesperdesc\n");
-                       return -ENOENT;
-               }
-               peasycap->video_isoc_buffer_size =
-                                       peasycap->video_isoc_maxframesize *
-                                       peasycap->video_isoc_framesperdesc;
-               JOM(4, "%i=video_isoc_buffer_size\n",
-                                       peasycap->video_isoc_buffer_size);
-               if ((PAGE_SIZE << VIDEO_ISOC_ORDER) <
-                                       peasycap->video_isoc_buffer_size) {
-                       SAM("MISTAKE: peasycap->video_isoc_buffer_size too big\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_interface) {
-                       SAM("MISTAKE:  video_interface is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_altsetting_on) {
-                       SAM("MISTAKE:  video_altsetting_on is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_altsetting_off) {
-                       SAM("MISTAKE:  video_interface_off is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_endpointnumber) {
-                       SAM("MISTAKE:  video_endpointnumber is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_isoc_maxframesize) {
-                       SAM("MISTAKE:  video_isoc_maxframesize is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->video_isoc_buffer_size) {
-                       SAM("MISTAKE:  video_isoc_buffer_size is unset\n");
-                       return -EFAULT;
-               }
-
-               /*
-                * Allocate memory for video buffers.
-                * Lists must be initialized first.
-                */
-               INIT_LIST_HEAD(&(peasycap->urb_video_head));
-               peasycap->purb_video_head = &(peasycap->urb_video_head);
-
-               rc = alloc_framebuffers(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               rc = alloc_fieldbuffers(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               rc = alloc_isocbuffers(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               /* Allocate and initialize video urbs */
-               rc = create_video_urbs(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               /* Save pointer peasycap in this interface */
-               usb_set_intfdata(intf, peasycap);
-
-               /*
-                * It is essential to initialize the hardware before,
-                * rather than after, the device is registered,
-                * because some udev rules triggers easycap_open()
-                * immediately after registration, causing a clash.
-                */
-               rc = reset(peasycap);
-               if (rc) {
-                       SAM("ERROR: reset() rc = %i\n", rc);
-                       return -EFAULT;
-               }
-
-               /* The video device can now be registered */
-               if (v4l2_device_register(&intf->dev, &peasycap->v4l2_device)) {
-                       SAM("v4l2_device_register() failed\n");
-                       return -ENODEV;
-               }
-               JOM(4, "registered device instance: %s\n",
-                       peasycap->v4l2_device.name);
-
-               rc = easycap_register_video(peasycap);
-               if (rc < 0) {
-                       dev_err(&intf->dev,
-                               "Not able to register with videodev\n");
-                       return -ENODEV;
-               }
-               break;
-       }
-       /* 1: Audio control */
-       case 1: {
-               if (!peasycap) {
-                       SAM("MISTAKE: peasycap is NULL\n");
-                       return -EFAULT;
-               }
-               /* Save pointer peasycap in this interface */
-               usb_set_intfdata(intf, peasycap);
-               JOM(4, "no initialization required for interface %i\n",
-                                       interface->bInterfaceNumber);
-               break;
-       }
-       /* 2: Audio streaming */
-       case 2: {
-               if (!peasycap) {
-                       SAM("MISTAKE: peasycap is NULL\n");
-                       return -EFAULT;
-               }
-               if (!isokalt) {
-                       SAM("ERROR:  no viable audio_altsetting_on\n");
-                       return -ENOENT;
-               }
-               peasycap->audio_altsetting_on = okalt[isokalt - 1];
-               JOM(4, "%i=audio_altsetting_on <====\n",
-                                               peasycap->audio_altsetting_on);
-
-               peasycap->audio_endpointnumber = okepn[isokalt - 1];
-               JOM(4, "%i=audio_endpointnumber\n", peasycap->audio_endpointnumber);
-
-               peasycap->audio_isoc_maxframesize = okmps[isokalt - 1];
-               JOM(4, "%i=audio_isoc_maxframesize\n",
-                                               peasycap->audio_isoc_maxframesize);
-               if (0 >= peasycap->audio_isoc_maxframesize) {
-                       SAM("ERROR:  bad audio_isoc_maxframesize\n");
-                       return -ENOENT;
-               }
-               if (9 == peasycap->audio_isoc_maxframesize) {
-                       peasycap->ilk |= 0x02;
-                       SAM("audio hardware is microphone\n");
-                       peasycap->microphone = true;
-                       peasycap->audio_pages_per_fragment =
-                                       PAGES_PER_AUDIO_FRAGMENT;
-               } else if (256 == peasycap->audio_isoc_maxframesize) {
-                       peasycap->ilk &= ~0x02;
-                       SAM("audio hardware is AC'97\n");
-                       peasycap->microphone = false;
-                       peasycap->audio_pages_per_fragment =
-                                       PAGES_PER_AUDIO_FRAGMENT;
-               } else {
-                       SAM("hardware is unidentified:\n");
-                       SAM("%i=audio_isoc_maxframesize\n",
-                               peasycap->audio_isoc_maxframesize);
-                       return -ENOENT;
-               }
-
-               peasycap->audio_bytes_per_fragment =
-                               peasycap->audio_pages_per_fragment * PAGE_SIZE;
-               peasycap->audio_buffer_page_many = (AUDIO_FRAGMENT_MANY *
-                               peasycap->audio_pages_per_fragment);
-
-               JOM(4, "%6i=AUDIO_FRAGMENT_MANY\n", AUDIO_FRAGMENT_MANY);
-               JOM(4, "%6i=audio_pages_per_fragment\n",
-                                               peasycap->audio_pages_per_fragment);
-               JOM(4, "%6i=audio_bytes_per_fragment\n",
-                                               peasycap->audio_bytes_per_fragment);
-               JOM(4, "%6i=audio_buffer_page_many\n",
-                                               peasycap->audio_buffer_page_many);
-
-               peasycap->audio_isoc_framesperdesc = AUDIO_ISOC_FRAMESPERDESC;
-
-               JOM(4, "%i=audio_isoc_framesperdesc\n",
-                                               peasycap->audio_isoc_framesperdesc);
-               if (0 >= peasycap->audio_isoc_framesperdesc) {
-                       SAM("ERROR:  bad audio_isoc_framesperdesc\n");
-                       return -ENOENT;
-               }
-
-               peasycap->audio_isoc_buffer_size =
-                                       peasycap->audio_isoc_maxframesize *
-                                       peasycap->audio_isoc_framesperdesc;
-               JOM(4, "%i=audio_isoc_buffer_size\n",
-                                               peasycap->audio_isoc_buffer_size);
-               if (AUDIO_ISOC_BUFFER_SIZE < peasycap->audio_isoc_buffer_size) {
-                               SAM("MISTAKE:  audio_isoc_buffer_size bigger "
-                               "than %li=AUDIO_ISOC_BUFFER_SIZE\n",
-                                                       AUDIO_ISOC_BUFFER_SIZE);
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_interface) {
-                       SAM("MISTAKE:  audio_interface is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_altsetting_on) {
-                       SAM("MISTAKE:  audio_altsetting_on is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_altsetting_off) {
-                       SAM("MISTAKE:  audio_interface_off is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_endpointnumber) {
-                       SAM("MISTAKE:  audio_endpointnumber is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_isoc_maxframesize) {
-                       SAM("MISTAKE:  audio_isoc_maxframesize is unset\n");
-                       return -EFAULT;
-               }
-               if (-1 == peasycap->audio_isoc_buffer_size) {
-                       SAM("MISTAKE:  audio_isoc_buffer_size is unset\n");
-                       return -EFAULT;
-               }
-
-               /*
-                * Allocate memory for audio buffers.
-                * Lists must be initialized first.
-                */
-               INIT_LIST_HEAD(&(peasycap->urb_audio_head));
-               peasycap->purb_audio_head = &(peasycap->urb_audio_head);
-
-               alloc_audio_buffers(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               /* Allocate and initialize urbs */
-               rc = create_audio_urbs(peasycap);
-               if (rc < 0)
-                       return rc;
-
-               /* Save pointer peasycap in this interface */
-               usb_set_intfdata(intf, peasycap);
-
-               /* The audio device can now be registered */
-               JOM(4, "initializing ALSA card\n");
-
-               rc = easycap_alsa_probe(peasycap);
-               if (rc) {
-                       dev_err(&intf->dev, "easycap_alsa_probe() rc = %i\n",
-                               rc);
-                       return -ENODEV;
-               }
-
-
-               JOM(8, "kref_get() with %i=kref.refcount.counter\n",
-                               peasycap->kref.refcount.counter);
-               kref_get(&peasycap->kref);
-               peasycap->registered_audio++;
-               break;
-       }
-       /* Interfaces other than 0,1,2 are unexpected */
-       default:
-               JOM(4, "ERROR: unexpected interface %i\n", bInterfaceNumber);
-               return -EINVAL;
-       }
-       SAM("ends successfully for interface %i\n", bInterfaceNumber);
-       return 0;
-}
-
-/*
- * When this function is called the device has already been
- * physically unplugged.
- * Hence, peasycap->pusb_device is no longer valid.
- * This function affects alsa.
- */
-static void easycap_usb_disconnect(struct usb_interface *pusb_interface)
-{
-       struct usb_host_interface *pusb_host_interface;
-       struct usb_interface_descriptor *pusb_interface_descriptor;
-       struct easycap *peasycap;
-       int minor, kd;
-       u8 bInterfaceNumber;
-
-       JOT(4, "\n");
-
-       pusb_host_interface = pusb_interface->cur_altsetting;
-       if (!pusb_host_interface) {
-               JOT(4, "ERROR: pusb_host_interface is NULL\n");
-               return;
-       }
-       pusb_interface_descriptor = &(pusb_host_interface->desc);
-       if (!pusb_interface_descriptor) {
-               JOT(4, "ERROR: pusb_interface_descriptor is NULL\n");
-               return;
-       }
-       bInterfaceNumber = pusb_interface_descriptor->bInterfaceNumber;
-       minor = pusb_interface->minor;
-       JOT(4, "intf[%i]: minor=%i\n", bInterfaceNumber, minor);
-
-       /* There is nothing to do for Interface Number 1 */
-       if (1 == bInterfaceNumber)
-               return;
-
-       peasycap = usb_get_intfdata(pusb_interface);
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return;
-       }
-
-       /* If the waitqueues are not cleared a deadlock is possible */
-       peasycap->video_eof = 1;
-       peasycap->audio_eof = 1;
-       wake_up_interruptible(&(peasycap->wq_video));
-       wake_up_interruptible(&(peasycap->wq_audio));
-
-       switch (bInterfaceNumber) {
-       case 0:
-               easycap_video_kill_urbs(peasycap);
-               break;
-       case 2:
-               easycap_audio_kill_urbs(peasycap);
-               break;
-       default:
-               break;
-       }
-
-       /*
-        * Deregister
-        * This procedure will block until easycap_poll(),
-        * video and audio ioctl are all unlocked.
-        * If this is not done an oops can occur when an easycap
-        * is unplugged while the urbs are running.
-        */
-       kd = easycap_isdongle(peasycap);
-       switch (bInterfaceNumber) {
-       case 0: {
-               if (0 <= kd && DONGLE_MANY > kd) {
-                       wake_up_interruptible(&peasycap->wq_video);
-                       JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
-                       if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
-                                                               mutex_video)) {
-                               SAY("ERROR: "
-                                   "cannot lock dongle[%i].mutex_video\n", kd);
-                               return;
-                       }
-                       JOM(4, "locked dongle[%i].mutex_video\n", kd);
-               } else {
-                       SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
-               }
-               if (!peasycap->v4l2_device.name[0]) {
-                       SAM("ERROR: peasycap->v4l2_device.name is empty\n");
-                       if (0 <= kd && DONGLE_MANY > kd)
-                               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       return;
-               }
-               v4l2_device_disconnect(&peasycap->v4l2_device);
-               JOM(4, "v4l2_device_disconnect() OK\n");
-               v4l2_device_unregister(&peasycap->v4l2_device);
-               JOM(4, "v4l2_device_unregister() OK\n");
-
-               video_unregister_device(&peasycap->video_device);
-               JOM(4, "intf[%i]: video_unregister_device() minor=%i\n",
-                               bInterfaceNumber, minor);
-               peasycap->registered_video--;
-
-               if (0 <= kd && DONGLE_MANY > kd) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-                       JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
-               }
-               break;
-       }
-       case 2: {
-               if (0 <= kd && DONGLE_MANY > kd) {
-                       wake_up_interruptible(&peasycap->wq_audio);
-                       JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
-                       if (mutex_lock_interruptible(&easycapdc60_dongle[kd].
-                                                               mutex_audio)) {
-                               SAY("ERROR: "
-                                   "cannot lock dongle[%i].mutex_audio\n", kd);
-                               return;
-                       }
-                       JOM(4, "locked dongle[%i].mutex_audio\n", kd);
-               } else
-                       SAY("ERROR: %i=kd is bad: cannot lock dongle\n", kd);
-               if (0 != snd_card_free(peasycap->psnd_card)) {
-                       SAY("ERROR: snd_card_free() failed\n");
-               } else {
-                       peasycap->psnd_card = NULL;
-                       (peasycap->registered_audio)--;
-               }
-               if (0 <= kd && DONGLE_MANY > kd) {
-                       mutex_unlock(&easycapdc60_dongle[kd].mutex_audio);
-                       JOM(4, "unlocked dongle[%i].mutex_audio\n", kd);
-               }
-               break;
-       }
-       default:
-               break;
-       }
-
-       /*
-        * If no remaining references to peasycap,
-        * call easycap_delete.
-        * (Also when alsa has been in use)
-        */
-       if (!peasycap->kref.refcount.counter) {
-               SAM("ERROR: peasycap->kref.refcount.counter is zero "
-                                                       "so cannot call kref_put()\n");
-               SAM("ending unsuccessfully: may cause memory leak\n");
-               return;
-       }
-       if (0 <= kd && DONGLE_MANY > kd) {
-               JOM(4, "about to lock dongle[%i].mutex_video\n", kd);
-               if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_video)) {
-                       SAY("ERROR: cannot lock dongle[%i].mutex_video\n", kd);
-                       SAM("ending unsuccessfully: may cause memory leak\n");
-                       return;
-               }
-               JOM(4, "locked dongle[%i].mutex_video\n", kd);
-               JOM(4, "about to lock dongle[%i].mutex_audio\n", kd);
-               if (mutex_lock_interruptible(&easycapdc60_dongle[kd].mutex_audio)) {
-                       SAY("ERROR: cannot lock dongle[%i].mutex_audio\n", kd);
-                       mutex_unlock(&(easycapdc60_dongle[kd].mutex_video));
-                       JOM(4, "unlocked dongle[%i].mutex_video\n", kd);
-                       SAM("ending unsuccessfully: may cause memory leak\n");
-                       return;
-               }
-               JOM(4, "locked dongle[%i].mutex_audio\n", kd);
-       }
-       JOM(4, "intf[%i]: %i=peasycap->kref.refcount.counter\n",
-                       bInterfaceNumber, (int)peasycap->kref.refcount.counter);
-       kref_put(&peasycap->kref, easycap_delete);
-       JOT(4, "intf[%i]: kref_put() done.\n", bInterfaceNumber);
-       if (0 <= kd && DONGLE_MANY > kd) {
-               mutex_unlock(&(easycapdc60_dongle[kd].mutex_audio));
-               JOT(4, "unlocked dongle[%i].mutex_audio\n", kd);
-               mutex_unlock(&easycapdc60_dongle[kd].mutex_video);
-               JOT(4, "unlocked dongle[%i].mutex_video\n", kd);
-       }
-       JOM(4, "ends\n");
-       return;
-}
-
-/* Devices supported by this driver */
-static struct usb_device_id easycap_usb_device_id_table[] = {
-       {USB_DEVICE(USB_EASYCAP_VENDOR_ID, USB_EASYCAP_PRODUCT_ID)},
-       { }
-};
-
-MODULE_DEVICE_TABLE(usb, easycap_usb_device_id_table);
-static struct usb_driver easycap_usb_driver = {
-       .name = "easycap",
-       .id_table = easycap_usb_device_id_table,
-       .probe = easycap_usb_probe,
-       .disconnect = easycap_usb_disconnect,
-};
-
-static int __init easycap_module_init(void)
-{
-       int k, rc;
-
-       printk(KERN_INFO "Easycap version: "EASYCAP_DRIVER_VERSION "\n");
-
-       JOT(4, "begins.  %i=debug %i=bars %i=gain\n",
-               easycap_debug, easycap_bars, easycap_gain);
-
-       mutex_init(&mutex_dongle);
-       for (k = 0; k < DONGLE_MANY; k++) {
-               easycapdc60_dongle[k].peasycap = NULL;
-               mutex_init(&easycapdc60_dongle[k].mutex_video);
-               mutex_init(&easycapdc60_dongle[k].mutex_audio);
-       }
-       rc = usb_register(&easycap_usb_driver);
-       if (rc)
-               printk(KERN_ERR "Easycap: usb_register failed rc=%d\n", rc);
-
-       return rc;
-}
-
-static void __exit easycap_module_exit(void)
-{
-       usb_deregister(&easycap_usb_driver);
-}
-
-module_init(easycap_module_init);
-module_exit(easycap_module_exit);
diff --git a/drivers/staging/media/easycap/easycap_settings.c b/drivers/staging/media/easycap/easycap_settings.c
deleted file mode 100644 (file)
index 3f5f5b3..0000000
+++ /dev/null
@@ -1,696 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_settings.c                                                         *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-
-/*---------------------------------------------------------------------------*/
-/*
- *  THE LEAST SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
- *                         0 => 25 fps
- *                         1 => 30 fps
- *
- *  THE MOST  SIGNIFICANT BIT OF easycap_standard.mask HAS MEANING:
- *                         0 => full framerate
- *                         1 => 20%  framerate
- */
-/*---------------------------------------------------------------------------*/
-const struct easycap_standard easycap_standard[] = {
-       {
-               .mask = 0x00FF & PAL_BGHIN ,
-               .v4l2_standard = {
-                       .index = PAL_BGHIN,
-                       .id = (V4L2_STD_PAL_B |
-                               V4L2_STD_PAL_G | V4L2_STD_PAL_H |
-                               V4L2_STD_PAL_I | V4L2_STD_PAL_N),
-                       .name = "PAL_BGHIN",
-                       .frameperiod = {1, 25},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & NTSC_N_443 ,
-               .v4l2_standard = {
-                       .index = NTSC_N_443,
-                       .id = V4L2_STD_UNKNOWN,
-                       .name = "NTSC_N_443",
-                       .frameperiod = {1, 25},
-                       .framelines = 480,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & PAL_Nc ,
-               .v4l2_standard = {
-                       .index = PAL_Nc,
-                       .id = V4L2_STD_PAL_Nc,
-                       .name = "PAL_Nc",
-                       .frameperiod = {1, 25},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & NTSC_N ,
-               .v4l2_standard = {
-                       .index = NTSC_N,
-                       .id = V4L2_STD_UNKNOWN,
-                       .name = "NTSC_N",
-                       .frameperiod = {1, 25},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & SECAM ,
-               .v4l2_standard = {
-                       .index = SECAM,
-                       .id = V4L2_STD_SECAM,
-                       .name = "SECAM",
-                       .frameperiod = {1, 25},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & NTSC_M ,
-               .v4l2_standard = {
-                       .index = NTSC_M,
-                       .id = V4L2_STD_NTSC_M,
-                       .name = "NTSC_M",
-                       .frameperiod = {1, 30},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & NTSC_M_JP ,
-               .v4l2_standard = {
-                       .index = NTSC_M_JP,
-                       .id = V4L2_STD_NTSC_M_JP,
-                       .name = "NTSC_M_JP",
-                       .frameperiod = {1, 30},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & PAL_60 ,
-               .v4l2_standard = {
-                       .index = PAL_60,
-                       .id = V4L2_STD_PAL_60,
-                       .name = "PAL_60",
-                       .frameperiod = {1, 30},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & NTSC_443 ,
-               .v4l2_standard = {
-                       .index = NTSC_443,
-                       .id = V4L2_STD_NTSC_443,
-                       .name = "NTSC_443",
-                       .frameperiod = {1, 30},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x00FF & PAL_M ,
-               .v4l2_standard = {
-                       .index = PAL_M,
-                       .id = V4L2_STD_PAL_M,
-                       .name = "PAL_M",
-                       .frameperiod = {1, 30},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & PAL_BGHIN_SLOW),
-               .v4l2_standard = {
-                       .index = PAL_BGHIN_SLOW,
-                       .id = (V4L2_STD_PAL_B | V4L2_STD_PAL_G |
-                               V4L2_STD_PAL_H |
-                               V4L2_STD_PAL_I | V4L2_STD_PAL_N |
-                               (((v4l2_std_id)0x01) << 32)),
-                       .name = "PAL_BGHIN_SLOW",
-                       .frameperiod = {1, 5},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & NTSC_N_443_SLOW),
-               .v4l2_standard = {
-                       .index = NTSC_N_443_SLOW,
-                       .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x11) << 32)),
-                       .name = "NTSC_N_443_SLOW",
-                       .frameperiod = {1, 5},
-                       .framelines = 480,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & PAL_Nc_SLOW),
-               .v4l2_standard = {
-                       .index = PAL_Nc_SLOW,
-                       .id = (V4L2_STD_PAL_Nc | (((v4l2_std_id)0x01) << 32)),
-                       .name = "PAL_Nc_SLOW",
-                       .frameperiod = {1, 5},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & NTSC_N_SLOW),
-               .v4l2_standard = {
-                       .index = NTSC_N_SLOW,
-                       .id = (V4L2_STD_UNKNOWN | (((v4l2_std_id)0x21) << 32)),
-                       .name = "NTSC_N_SLOW",
-                       .frameperiod = {1, 5},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & SECAM_SLOW),
-               .v4l2_standard = {
-                       .index = SECAM_SLOW,
-                       .id = (V4L2_STD_SECAM | (((v4l2_std_id)0x01) << 32)),
-                       .name = "SECAM_SLOW",
-                       .frameperiod = {1, 5},
-                       .framelines = 625,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & NTSC_M_SLOW),
-               .v4l2_standard = {
-                       .index = NTSC_M_SLOW,
-                       .id = (V4L2_STD_NTSC_M | (((v4l2_std_id)0x01) << 32)),
-                       .name = "NTSC_M_SLOW",
-                       .frameperiod = {1, 6},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & NTSC_M_JP_SLOW),
-               .v4l2_standard = {
-                       .index = NTSC_M_JP_SLOW,
-                       .id = (V4L2_STD_NTSC_M_JP |
-                               (((v4l2_std_id)0x01) << 32)),
-                       .name = "NTSC_M_JP_SLOW",
-                       .frameperiod = {1, 6},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & PAL_60_SLOW),
-               .v4l2_standard = {
-                       .index = PAL_60_SLOW,
-                       .id = (V4L2_STD_PAL_60 | (((v4l2_std_id)0x01) << 32)),
-                       .name = "PAL_60_SLOW",
-                       .frameperiod = {1, 6},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & NTSC_443_SLOW),
-               .v4l2_standard = {
-                       .index = NTSC_443_SLOW,
-                       .id = (V4L2_STD_NTSC_443 | (((v4l2_std_id)0x01) << 32)),
-                       .name = "NTSC_443_SLOW",
-                       .frameperiod = {1, 6},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0x8000 | (0x00FF & PAL_M_SLOW),
-               .v4l2_standard = {
-                       .index = PAL_M_SLOW,
-                       .id = (V4L2_STD_PAL_M | (((v4l2_std_id)0x01) << 32)),
-                       .name = "PAL_M_SLOW",
-                       .frameperiod = {1, 6},
-                       .framelines = 525,
-                       .reserved = {0, 0, 0, 0}
-               }
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .mask = 0xFFFF
-       }
-};
-/*---------------------------------------------------------------------------*/
-/*
- *  THE 16-BIT easycap_format.mask HAS MEANING:
- *    (least significant) BIT  0:     0 => PAL, 25 FPS;   1 => NTSC, 30 FPS
- *                        BITS 2-4:   RESERVED FOR DIFFERENTIATING STANDARDS
- *                        BITS 5-7:   NUMBER OF BYTES PER PIXEL
- *                        BIT  8:     0 => NATIVE BYTE ORDER;  1 => SWAPPED
- *                        BITS 9-10:  RESERVED FOR OTHER BYTE PERMUTATIONS
- *                        BIT 11:     0 => UNDECIMATED;    1 => DECIMATED
- *                        BIT 12:     0 => OFFER FRAMES;   1 => OFFER FIELDS
- *                        BIT 13:     0 => FULL FRAMERATE; 1 => REDUCED
- *     (most significant) BITS 14-15: RESERVED FOR OTHER FIELD/FRAME OPTIONS
- *  IT FOLLOWS THAT:
- *     bytesperpixel IS         ((0x00E0 & easycap_format.mask) >> 5)
- *     byteswaporder IS true IF (0 != (0x0100 & easycap_format.mask))
- *
- *     decimatepixel IS true IF (0 != (0x0800 & easycap_format.mask))
- *
- *       offerfields IS true IF (0 != (0x1000 & easycap_format.mask))
- */
-/*---------------------------------------------------------------------------*/
-
-struct easycap_format easycap_format[1 + SETTINGS_MANY];
-
-int easycap_video_fillin_formats(void)
-{
-       const char *name1, *name2, *name3, *name4;
-       struct v4l2_format *fmt;
-       int i, j, k, m, n;
-       u32 width, height, pixelformat, bytesperline, sizeimage;
-       u16 mask1, mask2, mask3, mask4;
-       enum v4l2_field field;
-       enum v4l2_colorspace colorspace;
-
-       for (i = 0, n = 0; i < STANDARD_MANY; i++) {
-               mask1 = 0x0000;
-               switch (i) {
-               case PAL_BGHIN: {
-                       mask1 = 0x1F & PAL_BGHIN;
-                       name1 = "PAL_BGHIN";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case SECAM: {
-                       mask1 = 0x1F & SECAM;
-                       name1 = "SECAM";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_Nc: {
-                       mask1 = 0x1F & PAL_Nc;
-                       name1 = "PAL_Nc";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_60: {
-                       mask1 = 0x1F & PAL_60;
-                       name1 = "PAL_60";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_M: {
-                       mask1 = 0x1F & PAL_M;
-                       name1 = "PAL_M";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case NTSC_M: {
-                       mask1 = 0x1F & NTSC_M;
-                       name1 = "NTSC_M";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_443: {
-                       mask1 = 0x1F & NTSC_443;
-                       name1 = "NTSC_443";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_M_JP: {
-                       mask1 = 0x1F & NTSC_M_JP;
-                       name1 = "NTSC_M_JP";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_N: {
-                       mask1 = 0x1F & NTSC_M;
-                       name1 = "NTSC_N";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_N_443: {
-                       mask1 = 0x1F & NTSC_N_443;
-                       name1 = "NTSC_N_443";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case PAL_BGHIN_SLOW: {
-                       mask1 = 0x001F & PAL_BGHIN_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "PAL_BGHIN_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case SECAM_SLOW: {
-                       mask1 = 0x001F & SECAM_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "SECAM_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_Nc_SLOW: {
-                       mask1 = 0x001F & PAL_Nc_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "PAL_Nc_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_60_SLOW: {
-                       mask1 = 0x001F & PAL_60_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "PAL_60_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case PAL_M_SLOW: {
-                       mask1 = 0x001F & PAL_M_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "PAL_M_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_BG;
-                       break;
-               }
-               case NTSC_M_SLOW: {
-                       mask1 = 0x001F & NTSC_M_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "NTSC_M_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_443_SLOW: {
-                       mask1 = 0x001F & NTSC_443_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "NTSC_443_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_M_JP_SLOW: {
-                       mask1 = 0x001F & NTSC_M_JP_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "NTSC_M_JP_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_N_SLOW: {
-                       mask1 = 0x001F & NTSC_N_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "NTSC_N_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               case NTSC_N_443_SLOW: {
-                       mask1 = 0x001F & NTSC_N_443_SLOW;
-                       mask1 |= 0x0200;
-                       name1 = "NTSC_N_443_SLOW";
-                       colorspace = V4L2_COLORSPACE_470_SYSTEM_M;
-                       break;
-               }
-               default:
-                       return -1;
-               }
-
-               for (j = 0; j < RESOLUTION_MANY; j++) {
-                       mask2 = 0x0000;
-                       switch (j) {
-                       case AT_720x576: {
-                               if (0x1 & mask1)
-                                       continue;
-                               name2 = "_AT_720x576";
-                               width = 720;
-                               height = 576;
-                               break;
-                       }
-                       case AT_704x576: {
-                               if (0x1 & mask1)
-                                       continue;
-                               name2 = "_AT_704x576";
-                               width = 704;
-                               height = 576;
-                               break;
-                       }
-                       case AT_640x480: {
-                               name2 = "_AT_640x480";
-                               width = 640;
-                               height = 480;
-                               break;
-                       }
-                       case AT_720x480: {
-                               if (!(0x1 & mask1))
-                                       continue;
-                               name2 = "_AT_720x480";
-                               width = 720;
-                               height = 480;
-                               break;
-                       }
-                       case AT_360x288: {
-                               if (0x1 & mask1)
-                                       continue;
-                               name2 = "_AT_360x288";
-                               width = 360;
-                               height = 288;
-                               mask2 = 0x0800;
-                               break;
-                       }
-                       case AT_320x240: {
-                               name2 = "_AT_320x240";
-                               width = 320;
-                               height = 240;
-                               mask2 = 0x0800;
-                               break;
-                       }
-                       case AT_360x240: {
-                               if (!(0x1 & mask1))
-                                       continue;
-                               name2 = "_AT_360x240";
-                               width = 360;
-                               height = 240;
-                               mask2 = 0x0800;
-                               break;
-                       }
-                       default:
-                               return -2;
-                       }
-
-                       for (k = 0; k < PIXELFORMAT_MANY; k++) {
-                               mask3 = 0x0000;
-                               switch (k) {
-                               case FMT_UYVY: {
-                                       name3 = __stringify(FMT_UYVY);
-                                       pixelformat = V4L2_PIX_FMT_UYVY;
-                                       mask3 |= (0x02 << 5);
-                                       break;
-                               }
-                               case FMT_YUY2: {
-                                       name3 = __stringify(FMT_YUY2);
-                                       pixelformat = V4L2_PIX_FMT_YUYV;
-                                       mask3 |= (0x02 << 5);
-                                       mask3 |= 0x0100;
-                                       break;
-                               }
-                               case FMT_RGB24: {
-                                       name3 = __stringify(FMT_RGB24);
-                                       pixelformat = V4L2_PIX_FMT_RGB24;
-                                       mask3 |= (0x03 << 5);
-                                       break;
-                               }
-                               case FMT_RGB32: {
-                                       name3 = __stringify(FMT_RGB32);
-                                       pixelformat = V4L2_PIX_FMT_RGB32;
-                                       mask3 |= (0x04 << 5);
-                                       break;
-                               }
-                               case FMT_BGR24: {
-                                       name3 = __stringify(FMT_BGR24);
-                                       pixelformat = V4L2_PIX_FMT_BGR24;
-                                       mask3 |= (0x03 << 5);
-                                       mask3 |= 0x0100;
-                                       break;
-                               }
-                               case FMT_BGR32: {
-                                       name3 = __stringify(FMT_BGR32);
-                                       pixelformat = V4L2_PIX_FMT_BGR32;
-                                       mask3 |= (0x04 << 5);
-                                       mask3 |= 0x0100;
-                                       break;
-                               }
-                               default:
-                                       return -3;
-                               }
-                               bytesperline = width * ((mask3 & 0x00E0) >> 5);
-                               sizeimage =  bytesperline * height;
-
-                               for (m = 0; m < INTERLACE_MANY; m++) {
-                                       mask4 = 0x0000;
-                                       switch (m) {
-                                       case FIELD_NONE: {
-                                               name4 = "-n";
-                                               field = V4L2_FIELD_NONE;
-                                               break;
-                                       }
-                                       case FIELD_INTERLACED: {
-                                               name4 = "-i";
-                                               mask4 |= 0x1000;
-                                               field = V4L2_FIELD_INTERLACED;
-                                               break;
-                                       }
-                                       default:
-                                               return -4;
-                                       }
-                                       if (SETTINGS_MANY <= n)
-                                               return -5;
-
-                                       strcpy(easycap_format[n].name, name1);
-                                       strcat(easycap_format[n].name, name2);
-                                       strcat(easycap_format[n].name, "_");
-                                       strcat(easycap_format[n].name, name3);
-                                       strcat(easycap_format[n].name, name4);
-                                       easycap_format[n].mask =
-                                               mask1 | mask2 | mask3 | mask4;
-                                       fmt = &easycap_format[n].v4l2_format;
-
-                                       fmt->type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
-                                       fmt->fmt.pix.width = width;
-                                       fmt->fmt.pix.height = height;
-                                       fmt->fmt.pix.pixelformat = pixelformat;
-                                       fmt->fmt.pix.field = field;
-                                       fmt->fmt.pix.bytesperline = bytesperline;
-                                       fmt->fmt.pix.sizeimage = sizeimage;
-                                       fmt->fmt.pix.colorspace = colorspace;
-                                       fmt->fmt.pix.priv = 0;
-                                       n++;
-                               }
-                       }
-               }
-       }
-       if ((1 + SETTINGS_MANY) <= n)
-               return -6;
-       easycap_format[n].mask = 0xFFFF;
-       return n;
-}
-/*---------------------------------------------------------------------------*/
-struct v4l2_queryctrl easycap_control[] = {
-       {
-               .id       = V4L2_CID_BRIGHTNESS,
-               .type     = V4L2_CTRL_TYPE_INTEGER,
-               .name     = "Brightness",
-               .minimum  = 0,
-               .maximum  = 255,
-               .step     =  1,
-               .default_value = SAA_0A_DEFAULT,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id       = V4L2_CID_CONTRAST,
-               .type     = V4L2_CTRL_TYPE_INTEGER,
-               .name     = "Contrast",
-               .minimum  = 0,
-               .maximum  = 255,
-               .step     =   1,
-               .default_value = SAA_0B_DEFAULT + 128,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id       = V4L2_CID_SATURATION,
-               .type     = V4L2_CTRL_TYPE_INTEGER,
-               .name     = "Saturation",
-               .minimum  = 0,
-               .maximum  = 255,
-               .step     =   1,
-               .default_value = SAA_0C_DEFAULT + 128,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id       = V4L2_CID_HUE,
-               .type     = V4L2_CTRL_TYPE_INTEGER,
-               .name     = "Hue",
-               .minimum  = 0,
-               .maximum  = 255,
-               .step     =   1,
-               .default_value = SAA_0D_DEFAULT + 128,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id       = V4L2_CID_AUDIO_VOLUME,
-               .type     = V4L2_CTRL_TYPE_INTEGER,
-               .name     = "Volume",
-               .minimum  = 0,
-               .maximum  = 31,
-               .step     =   1,
-               .default_value = 16,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id       = V4L2_CID_AUDIO_MUTE,
-               .type     = V4L2_CTRL_TYPE_BOOLEAN,
-               .name     = "Mute",
-               .default_value = true,
-               .flags    = 0,
-               .reserved = {0, 0}
-       },
-/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
-       {
-               .id = 0xFFFFFFFF
-       }
-};
-/*****************************************************************************/
diff --git a/drivers/staging/media/easycap/easycap_sound.c b/drivers/staging/media/easycap/easycap_sound.c
deleted file mode 100644 (file)
index 8c8bcae..0000000
+++ /dev/null
@@ -1,750 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_sound.c                                                            *
-*                                                                             *
-*  Audio driver for EasyCAP USB2.0 Video Capture Device DC60                  *
-*                                                                             *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-
-/*--------------------------------------------------------------------------*/
-/*
- *  PARAMETERS USED WHEN REGISTERING THE AUDIO INTERFACE
- */
-/*--------------------------------------------------------------------------*/
-static const struct snd_pcm_hardware alsa_hardware = {
-       .info = SNDRV_PCM_INFO_BLOCK_TRANSFER |
-               SNDRV_PCM_INFO_MMAP           |
-               SNDRV_PCM_INFO_INTERLEAVED    |
-               SNDRV_PCM_INFO_MMAP_VALID,
-       .formats = SNDRV_PCM_FMTBIT_S16_LE,
-       .rates = SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_48000,
-       .rate_min = 32000,
-       .rate_max = 48000,
-       .channels_min = 2,
-       .channels_max = 2,
-       .buffer_bytes_max = PAGE_SIZE *
-                           PAGES_PER_AUDIO_FRAGMENT *
-                           AUDIO_FRAGMENT_MANY,
-       .period_bytes_min = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT,
-       .period_bytes_max = PAGE_SIZE * PAGES_PER_AUDIO_FRAGMENT * 2,
-       .periods_min = AUDIO_FRAGMENT_MANY,
-       .periods_max = AUDIO_FRAGMENT_MANY * 2,
-};
-
-
-/*---------------------------------------------------------------------------*/
-/*
- *  SUBMIT ALL AUDIO URBS.
- */
-/*---------------------------------------------------------------------------*/
-static int easycap_audio_submit_urbs(struct easycap *peasycap)
-{
-       struct data_urb *pdata_urb;
-       struct urb *purb;
-       struct list_head *plist_head;
-       int j, isbad, nospc, m, rc;
-       int isbuf;
-
-       if (!peasycap->purb_audio_head) {
-               SAM("ERROR: peasycap->urb_audio_head uninitialized\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -EFAULT;
-       }
-
-       if (peasycap->audio_isoc_streaming) {
-               JOM(4, "already streaming audio urbs\n");
-               return 0;
-       }
-
-       JOM(4, "initial submission of all audio urbs\n");
-       rc = usb_set_interface(peasycap->pusb_device,
-                              peasycap->audio_interface,
-                              peasycap->audio_altsetting_on);
-       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n",
-           peasycap->audio_interface,
-           peasycap->audio_altsetting_on, rc);
-
-       isbad = 0;
-       nospc = 0;
-       m = 0;
-       list_for_each(plist_head, peasycap->purb_audio_head) {
-               pdata_urb = list_entry(plist_head, struct data_urb, list_head);
-               if (pdata_urb && pdata_urb->purb) {
-                       purb = pdata_urb->purb;
-                       isbuf = pdata_urb->isbuf;
-
-                       purb->interval = 1;
-                       purb->dev = peasycap->pusb_device;
-                       purb->pipe = usb_rcvisocpipe(peasycap->pusb_device,
-                                       peasycap->audio_endpointnumber);
-                       purb->transfer_flags = URB_ISO_ASAP;
-                       purb->transfer_buffer = peasycap->audio_isoc_buffer[isbuf].pgo;
-                       purb->transfer_buffer_length = peasycap->audio_isoc_buffer_size;
-                       purb->complete = easycap_alsa_complete;
-                       purb->context = peasycap;
-                       purb->start_frame = 0;
-                       purb->number_of_packets = peasycap->audio_isoc_framesperdesc;
-                       for (j = 0;  j < peasycap->audio_isoc_framesperdesc; j++) {
-                               purb->iso_frame_desc[j].offset = j * peasycap->audio_isoc_maxframesize;
-                               purb->iso_frame_desc[j].length = peasycap->audio_isoc_maxframesize;
-                       }
-
-                       rc = usb_submit_urb(purb, GFP_KERNEL);
-                       if (rc) {
-                               isbad++;
-                               SAM("ERROR: usb_submit_urb() failed"
-                                   " for urb with rc: -%s: %d\n",
-                                   strerror(rc), rc);
-                       } else {
-                               m++;
-                       }
-               } else {
-                       isbad++;
-               }
-       }
-       if (nospc) {
-               SAM("-ENOSPC=usb_submit_urb() for %i urbs\n", nospc);
-               SAM(".....  possibly inadequate USB bandwidth\n");
-               peasycap->audio_eof = 1;
-       }
-
-       if (isbad)
-               easycap_audio_kill_urbs(peasycap);
-       else
-               peasycap->audio_isoc_streaming = m;
-
-       return 0;
-}
-/*---------------------------------------------------------------------------*/
-/*
- *  COMMON AUDIO INITIALIZATION
- */
-/*---------------------------------------------------------------------------*/
-static int easycap_sound_setup(struct easycap *peasycap)
-{
-       int rc;
-
-       JOM(4, "starting initialization\n");
-
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL.\n");
-               return -EFAULT;
-       }
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device is NULL\n");
-               return -ENODEV;
-       }
-       JOM(16, "0x%08lX=peasycap->pusb_device\n", (long int)peasycap->pusb_device);
-
-       rc = easycap_audio_setup(peasycap);
-       JOM(8, "audio_setup() returned %i\n", rc);
-
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device has become NULL\n");
-               return -ENODEV;
-       }
-/*---------------------------------------------------------------------------*/
-       if (!peasycap->pusb_device) {
-               SAM("ERROR: peasycap->pusb_device has become NULL\n");
-               return -ENODEV;
-       }
-       rc = usb_set_interface(peasycap->pusb_device, peasycap->audio_interface,
-                              peasycap->audio_altsetting_on);
-       JOM(8, "usb_set_interface(.,%i,%i) returned %i\n", peasycap->audio_interface,
-           peasycap->audio_altsetting_on, rc);
-
-       rc = easycap_wakeup_device(peasycap->pusb_device);
-       JOM(8, "wakeup_device() returned %i\n", rc);
-
-       peasycap->audio_eof = 0;
-       peasycap->audio_idle = 0;
-
-       easycap_audio_submit_urbs(peasycap);
-
-       JOM(4, "finished initialization\n");
-       return 0;
-}
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  ON COMPLETION OF AN AUDIO URB ITS DATA IS COPIED TO THE DAM BUFFER
- *  PROVIDED peasycap->audio_idle IS ZERO.  REGARDLESS OF THIS BEING TRUE,
- *  IT IS RESUBMITTED PROVIDED peasycap->audio_isoc_streaming IS NOT ZERO.
- */
-/*---------------------------------------------------------------------------*/
-void easycap_alsa_complete(struct urb *purb)
-{
-       struct easycap *peasycap;
-       struct snd_pcm_substream *pss;
-       struct snd_pcm_runtime *prt;
-       int dma_bytes, fragment_bytes;
-       int isfragment;
-       u8 *p1, *p2;
-       s16 tmp;
-       int i, j, more, much, rc;
-#ifdef UPSAMPLE
-       int k;
-       s16 oldaudio, newaudio, delta;
-#endif /*UPSAMPLE*/
-
-       JOT(16, "\n");
-
-       if (!purb) {
-               SAY("ERROR: purb is NULL\n");
-               return;
-       }
-       peasycap = purb->context;
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return;
-       }
-       much = 0;
-       if (peasycap->audio_idle) {
-               JOM(16, "%i=audio_idle  %i=audio_isoc_streaming\n",
-                   peasycap->audio_idle, peasycap->audio_isoc_streaming);
-               if (peasycap->audio_isoc_streaming)
-                       goto resubmit;
-       }
-/*---------------------------------------------------------------------------*/
-       pss = peasycap->psubstream;
-       if (!pss)
-               goto resubmit;
-       prt = pss->runtime;
-       if (!prt)
-               goto resubmit;
-       dma_bytes = (int)prt->dma_bytes;
-       if (0 == dma_bytes)
-               goto resubmit;
-       fragment_bytes = 4 * ((int)prt->period_size);
-       if (0 == fragment_bytes)
-               goto resubmit;
-/* -------------------------------------------------------------------------*/
-       if (purb->status) {
-               if ((-ESHUTDOWN == purb->status) || (-ENOENT == purb->status)) {
-                       JOM(16, "urb status -ESHUTDOWN or -ENOENT\n");
-                       return;
-               }
-               SAM("ERROR: non-zero urb status: -%s: %d\n",
-                   strerror(purb->status), purb->status);
-               goto resubmit;
-       }
-/*---------------------------------------------------------------------------*/
-/*
- *  PROCEED HERE WHEN NO ERROR
- */
-/*---------------------------------------------------------------------------*/
-
-#ifdef UPSAMPLE
-       oldaudio = peasycap->oldaudio;
-#endif /*UPSAMPLE*/
-
-       for (i = 0;  i < purb->number_of_packets; i++) {
-               if (purb->iso_frame_desc[i].status < 0) {
-                       SAM("-%s: %d\n",
-                           strerror(purb->iso_frame_desc[i].status),
-                           purb->iso_frame_desc[i].status);
-               }
-               if (purb->iso_frame_desc[i].status) {
-                       JOM(12, "discarding audio samples because "
-                           "%i=purb->iso_frame_desc[i].status\n",
-                           purb->iso_frame_desc[i].status);
-                       continue;
-               }
-               more = purb->iso_frame_desc[i].actual_length;
-               if (more == 0) {
-                       peasycap->audio_mt++;
-                       continue;
-               }
-               if (0 > more) {
-                       SAM("MISTAKE: more is negative\n");
-                       return;
-               }
-
-               if (peasycap->audio_mt) {
-                       JOM(12, "%4i empty audio urb frames\n",
-                           peasycap->audio_mt);
-                       peasycap->audio_mt = 0;
-               }
-
-               p1 = (u8 *)(purb->transfer_buffer +
-                               purb->iso_frame_desc[i].offset);
-
-               /*
-                *  COPY more BYTES FROM ISOC BUFFER
-                *  TO THE DMA BUFFER, CONVERTING
-                *  8-BIT MONO TO 16-BIT SIGNED
-                *  LITTLE-ENDIAN SAMPLES IF NECESSARY
-                */
-               while (more) {
-                       much = dma_bytes - peasycap->dma_fill;
-                       if (0 > much) {
-                               SAM("MISTAKE: much is negative\n");
-                               return;
-                       }
-                       if (0 == much) {
-                               peasycap->dma_fill = 0;
-                               peasycap->dma_next = fragment_bytes;
-                               JOM(8, "wrapped dma buffer\n");
-                       }
-                       if (!peasycap->microphone) {
-                               if (much > more)
-                                       much = more;
-                               memcpy(prt->dma_area + peasycap->dma_fill,
-                                       p1, much);
-                               p1 += much;
-                               more -= much;
-                       } else {
-#ifdef UPSAMPLE
-                               if (much % 16)
-                                       JOM(8, "MISTAKE? much"
-                                           " is not divisible by 16\n");
-                               if (much > (16 * more))
-                                       much = 16 * more;
-                               p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
-
-                               for (j = 0;  j < (much / 16);  j++) {
-                                       newaudio =  ((int) *p1) - 128;
-                                       newaudio = 128 * newaudio;
-
-                                       delta = (newaudio - oldaudio) / 4;
-                                       tmp = oldaudio + delta;
-
-                                       for (k = 0;  k < 4;  k++) {
-                                               *p2 = (0x00FF & tmp);
-                                               *(p2 + 1) = (0xFF00 & tmp) >> 8;
-                                               p2 += 2;
-                                               *p2 = (0x00FF & tmp);
-                                               *(p2 + 1) = (0xFF00 & tmp) >> 8;
-                                               p2 += 2;
-                                               tmp += delta;
-                                       }
-                                       p1++;
-                                       more--;
-                                       oldaudio = tmp;
-                               }
-#else /*!UPSAMPLE*/
-                               if (much > (2 * more))
-                                       much = 2 * more;
-                               p2 = (u8 *)(prt->dma_area + peasycap->dma_fill);
-
-                               for (j = 0;  j < (much / 2);  j++) {
-                                       tmp = ((int) *p1) - 128;
-                                       tmp = 128 * tmp;
-                                       *p2 = (0x00FF & tmp);
-                                       *(p2 + 1) = (0xFF00 & tmp) >> 8;
-                                       p1++;
-                                       p2 += 2;
-                                       more--;
-                               }
-#endif /*UPSAMPLE*/
-                       }
-                       peasycap->dma_fill += much;
-                       if (peasycap->dma_fill >= peasycap->dma_next) {
-                               isfragment = peasycap->dma_fill / fragment_bytes;
-                               if (0 > isfragment) {
-                                       SAM("MISTAKE: isfragment is negative\n");
-                                       return;
-                               }
-                               peasycap->dma_read = (isfragment - 1) * fragment_bytes;
-                               peasycap->dma_next = (isfragment + 1) * fragment_bytes;
-                               if (dma_bytes < peasycap->dma_next)
-                                       peasycap->dma_next = fragment_bytes;
-
-                               if (0 <= peasycap->dma_read) {
-                                       JOM(8, "snd_pcm_period_elapsed(), %i="
-                                           "isfragment\n", isfragment);
-                                       snd_pcm_period_elapsed(pss);
-                               }
-                       }
-               }
-
-#ifdef UPSAMPLE
-               peasycap->oldaudio = oldaudio;
-#endif /*UPSAMPLE*/
-
-       }
-/*---------------------------------------------------------------------------*/
-/*
- *  RESUBMIT THIS URB
- */
-/*---------------------------------------------------------------------------*/
-resubmit:
-       if (peasycap->audio_isoc_streaming == 0)
-               return;
-
-       rc = usb_submit_urb(purb, GFP_ATOMIC);
-       if (rc) {
-               if ((-ENODEV != rc) && (-ENOENT != rc)) {
-                       SAM("ERROR: while %i=audio_idle, usb_submit_urb failed "
-                           "with rc: -%s :%d\n",
-                               peasycap->audio_idle, strerror(rc), rc);
-               }
-               if (0 < peasycap->audio_isoc_streaming)
-                       peasycap->audio_isoc_streaming--;
-       }
-       return;
-}
-/*****************************************************************************/
-static int easycap_alsa_open(struct snd_pcm_substream *pss)
-{
-       struct snd_pcm *psnd_pcm;
-       struct snd_card *psnd_card;
-       struct easycap *peasycap;
-
-       JOT(4, "\n");
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       psnd_pcm = pss->pcm;
-       if (!psnd_pcm) {
-               SAY("ERROR:  psnd_pcm is NULL\n");
-               return -EFAULT;
-       }
-       psnd_card = psnd_pcm->card;
-       if (!psnd_card) {
-               SAY("ERROR:  psnd_card is NULL\n");
-               return -EFAULT;
-       }
-
-       peasycap = psnd_card->private_data;
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if (peasycap->psnd_card != psnd_card) {
-               SAM("ERROR: bad peasycap->psnd_card\n");
-               return -EFAULT;
-       }
-       if (peasycap->psubstream) {
-               SAM("ERROR: bad peasycap->psubstream\n");
-               return -EFAULT;
-       }
-       pss->private_data = peasycap;
-       peasycap->psubstream = pss;
-       pss->runtime->hw = peasycap->alsa_hardware;
-       pss->runtime->private_data = peasycap;
-       pss->private_data = peasycap;
-
-       if (0 != easycap_sound_setup(peasycap)) {
-               JOM(4, "ending unsuccessfully\n");
-               return -EFAULT;
-       }
-       JOM(4, "ending successfully\n");
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_close(struct snd_pcm_substream *pss)
-{
-       struct easycap *peasycap;
-
-       JOT(4, "\n");
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       peasycap = snd_pcm_substream_chip(pss);
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       pss->private_data = NULL;
-       peasycap->psubstream = NULL;
-       JOT(4, "ending successfully\n");
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_vmalloc(struct snd_pcm_substream *pss, size_t sz)
-{
-       struct snd_pcm_runtime *prt;
-       JOT(4, "\n");
-
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       prt = pss->runtime;
-       if (!prt) {
-               SAY("ERROR: substream.runtime is NULL\n");
-               return -EFAULT;
-       }
-       if (prt->dma_area) {
-               if (prt->dma_bytes > sz)
-                       return 0;
-               vfree(prt->dma_area);
-       }
-       prt->dma_area = vmalloc(sz);
-       if (!prt->dma_area)
-               return -ENOMEM;
-       prt->dma_bytes = sz;
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_hw_params(struct snd_pcm_substream *pss,
-                                struct snd_pcm_hw_params *phw)
-{
-       int rc;
-
-       JOT(4, "%i\n", (params_buffer_bytes(phw)));
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       rc = easycap_alsa_vmalloc(pss, params_buffer_bytes(phw));
-       if (rc)
-               return rc;
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_hw_free(struct snd_pcm_substream *pss)
-{
-       struct snd_pcm_runtime *prt;
-       JOT(4, "\n");
-
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       prt = pss->runtime;
-       if (!prt) {
-               SAY("ERROR: substream.runtime is NULL\n");
-               return -EFAULT;
-       }
-       if (prt->dma_area) {
-               JOT(8, "prt->dma_area = %p\n", prt->dma_area);
-               vfree(prt->dma_area);
-               prt->dma_area = NULL;
-       } else
-               JOT(8, "dma_area already freed\n");
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_prepare(struct snd_pcm_substream *pss)
-{
-       struct easycap *peasycap;
-       struct snd_pcm_runtime *prt;
-
-       JOT(4, "\n");
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       prt = pss->runtime;
-       peasycap = snd_pcm_substream_chip(pss);
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-
-       JOM(16, "ALSA decides %8i Hz=rate\n", pss->runtime->rate);
-       JOM(16, "ALSA decides %8ld =period_size\n", pss->runtime->period_size);
-       JOM(16, "ALSA decides %8i =periods\n", pss->runtime->periods);
-       JOM(16, "ALSA decides %8ld =buffer_size\n", pss->runtime->buffer_size);
-       JOM(16, "ALSA decides %8zd =dma_bytes\n", pss->runtime->dma_bytes);
-       JOM(16, "ALSA decides %8ld =boundary\n", pss->runtime->boundary);
-       JOM(16, "ALSA decides %8i =period_step\n", pss->runtime->period_step);
-       JOM(16, "ALSA decides %8i =sample_bits\n", pss->runtime->sample_bits);
-       JOM(16, "ALSA decides %8i =frame_bits\n", pss->runtime->frame_bits);
-       JOM(16, "ALSA decides %8ld =min_align\n", pss->runtime->min_align);
-       JOM(12, "ALSA decides %8ld =hw_ptr_base\n", pss->runtime->hw_ptr_base);
-       JOM(12, "ALSA decides %8ld =hw_ptr_interrupt\n",
-               pss->runtime->hw_ptr_interrupt);
-
-       if (prt->dma_bytes != 4 * ((int)prt->period_size) * ((int)prt->periods)) {
-               SAY("MISTAKE:  unexpected ALSA parameters\n");
-               return -ENOENT;
-       }
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_ack(struct snd_pcm_substream *pss)
-{
-       return 0;
-}
-/*****************************************************************************/
-static int easycap_alsa_trigger(struct snd_pcm_substream *pss, int cmd)
-{
-       struct easycap *peasycap;
-
-       JOT(4, "%i=cmd cf %i=START %i=STOP\n", cmd, SNDRV_PCM_TRIGGER_START,
-           SNDRV_PCM_TRIGGER_STOP);
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       peasycap = snd_pcm_substream_chip(pss);
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       switch (cmd) {
-       case SNDRV_PCM_TRIGGER_START: {
-               peasycap->audio_idle = 0;
-               break;
-       }
-       case SNDRV_PCM_TRIGGER_STOP: {
-               peasycap->audio_idle = 1;
-               break;
-       }
-       default:
-               return -EINVAL;
-       }
-       return 0;
-}
-/*****************************************************************************/
-static snd_pcm_uframes_t easycap_alsa_pointer(struct snd_pcm_substream *pss)
-{
-       struct easycap *peasycap;
-       snd_pcm_uframes_t offset;
-
-       JOT(16, "\n");
-       if (!pss) {
-               SAY("ERROR:  pss is NULL\n");
-               return -EFAULT;
-       }
-       peasycap = snd_pcm_substream_chip(pss);
-       if (!peasycap) {
-               SAY("ERROR:  peasycap is NULL\n");
-               return -EFAULT;
-       }
-       if ((0 != peasycap->audio_eof) || (0 != peasycap->audio_idle)) {
-               JOM(8, "returning -EIO because  "
-                   "%i=audio_idle  %i=audio_eof\n",
-                   peasycap->audio_idle, peasycap->audio_eof);
-               return -EIO;
-       }
-/*---------------------------------------------------------------------------*/
-       if (0 > peasycap->dma_read) {
-               JOM(8, "returning -EBUSY\n");
-               return -EBUSY;
-       }
-       offset = ((snd_pcm_uframes_t)peasycap->dma_read)/4;
-       JOM(8, "ALSA decides %8i   =hw_ptr_base\n", (int)pss->runtime->hw_ptr_base);
-       JOM(8, "ALSA decides %8i   =hw_ptr_interrupt\n",
-           (int)pss->runtime->hw_ptr_interrupt);
-       JOM(8, "%7i=offset %7i=dma_read %7i=dma_next\n",
-           (int)offset, peasycap->dma_read, peasycap->dma_next);
-       return offset;
-}
-/*****************************************************************************/
-static struct page *
-easycap_alsa_page(struct snd_pcm_substream *pss, unsigned long offset)
-{
-       return vmalloc_to_page(pss->runtime->dma_area + offset);
-}
-/*****************************************************************************/
-
-static struct snd_pcm_ops easycap_alsa_pcm_ops = {
-       .open      = easycap_alsa_open,
-       .close     = easycap_alsa_close,
-       .ioctl     = snd_pcm_lib_ioctl,
-       .hw_params = easycap_alsa_hw_params,
-       .hw_free   = easycap_alsa_hw_free,
-       .prepare   = easycap_alsa_prepare,
-       .ack       = easycap_alsa_ack,
-       .trigger   = easycap_alsa_trigger,
-       .pointer   = easycap_alsa_pointer,
-       .page      = easycap_alsa_page,
-};
-
-/*****************************************************************************/
-/*---------------------------------------------------------------------------*/
-/*
- *  THE FUNCTION snd_card_create() HAS  THIS_MODULE  AS AN ARGUMENT.  THIS
- *  MEANS MODULE easycap.  BEWARE.
-*/
-/*---------------------------------------------------------------------------*/
-int easycap_alsa_probe(struct easycap *peasycap)
-{
-       int rc;
-       struct snd_card *psnd_card;
-       struct snd_pcm *psnd_pcm;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return -ENODEV;
-       }
-       if (0 > peasycap->minor) {
-               SAY("ERROR: no minor\n");
-               return -ENODEV;
-       }
-
-       peasycap->alsa_hardware = alsa_hardware;
-       if (peasycap->microphone) {
-               peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_32000;
-               peasycap->alsa_hardware.rate_min = 32000;
-               peasycap->alsa_hardware.rate_max = 32000;
-       } else {
-               peasycap->alsa_hardware.rates = SNDRV_PCM_RATE_48000;
-               peasycap->alsa_hardware.rate_min = 48000;
-               peasycap->alsa_hardware.rate_max = 48000;
-       }
-
-       if (0 != snd_card_create(SNDRV_DEFAULT_IDX1, "easycap_alsa",
-                               THIS_MODULE, 0, &psnd_card)) {
-               SAY("ERROR: Cannot do ALSA snd_card_create()\n");
-               return -EFAULT;
-       }
-
-       sprintf(&psnd_card->id[0], "EasyALSA%i", peasycap->minor);
-       strcpy(&psnd_card->driver[0], EASYCAP_DRIVER_DESCRIPTION);
-       strcpy(&psnd_card->shortname[0], "easycap_alsa");
-       sprintf(&psnd_card->longname[0], "%s", &psnd_card->shortname[0]);
-
-       psnd_card->dev = &peasycap->pusb_device->dev;
-       psnd_card->private_data = peasycap;
-       peasycap->psnd_card = psnd_card;
-
-       rc = snd_pcm_new(psnd_card, "easycap_pcm", 0, 0, 1, &psnd_pcm);
-       if (rc) {
-               SAM("ERROR: Cannot do ALSA snd_pcm_new()\n");
-               snd_card_free(psnd_card);
-               return -EFAULT;
-       }
-
-       snd_pcm_set_ops(psnd_pcm, SNDRV_PCM_STREAM_CAPTURE,
-                       &easycap_alsa_pcm_ops);
-       psnd_pcm->info_flags = 0;
-       strcpy(&psnd_pcm->name[0], &psnd_card->id[0]);
-       psnd_pcm->private_data = peasycap;
-       peasycap->psnd_pcm = psnd_pcm;
-       peasycap->psubstream = NULL;
-
-       rc = snd_card_register(psnd_card);
-       if (rc) {
-               SAM("ERROR: Cannot do ALSA snd_card_register()\n");
-               snd_card_free(psnd_card);
-               return -EFAULT;
-       }
-
-       SAM("registered %s\n", &psnd_card->id[0]);
-       return 0;
-}
-
diff --git a/drivers/staging/media/easycap/easycap_testcard.c b/drivers/staging/media/easycap/easycap_testcard.c
deleted file mode 100644 (file)
index 0f71470..0000000
+++ /dev/null
@@ -1,155 +0,0 @@
-/******************************************************************************
-*                                                                             *
-*  easycap_testcard.c                                                         *
-*                                                                             *
-******************************************************************************/
-/*
- *
- *  Copyright (C) 2010 R.M. Thomas  <rmthomas@sciolus.org>
- *
- *
- *  This 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.
- *
- *  The software 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 software; if not, write to the Free Software
- *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- *
-*/
-/*****************************************************************************/
-
-#include "easycap.h"
-
-/*****************************************************************************/
-#define TESTCARD_BYTESPERLINE (2 * 720)
-void
-easycap_testcard(struct easycap *peasycap, int field)
-{
-       int total;
-       int y, u, v, r, g, b;
-       unsigned char uyvy[4];
-       int i1, line, k, m, n, more, much, barwidth, barheight;
-       unsigned char bfbar[TESTCARD_BYTESPERLINE / 8], *p1, *p2;
-       struct data_buffer *pfield_buffer;
-
-       if (!peasycap) {
-               SAY("ERROR: peasycap is NULL\n");
-               return;
-       }
-       JOM(8, "%i=field\n", field);
-       switch (peasycap->width) {
-       case 720:
-       case 360: {
-               barwidth = (2 * 720) / 8;
-               break;
-       }
-       case 704:
-       case 352: {
-               barwidth = (2 * 704) / 8;
-               break;
-       }
-       case 640:
-       case 320: {
-               barwidth = (2 * 640) / 8;
-               break;
-       }
-       default: {
-               SAM("ERROR:  cannot set barwidth\n");
-               return;
-       }
-       }
-       if (TESTCARD_BYTESPERLINE < barwidth) {
-               SAM("ERROR: barwidth is too large\n");
-               return;
-       }
-       switch (peasycap->height) {
-       case 576:
-       case 288: {
-               barheight = 576;
-               break;
-       }
-       case 480:
-       case 240: {
-               barheight = 480;
-               break;
-       }
-       default: {
-               SAM("ERROR: cannot set barheight\n");
-               return;
-       }
-       }
-       total = 0;
-       k = field;
-       m = 0;
-       n = 0;
-
-       for (line = 0;  line < (barheight / 2);  line++) {
-               for (i1 = 0;  i1 < 8;  i1++) {
-                       r = (i1 * 256)/8;
-                       g = (i1 * 256)/8;
-                       b = (i1 * 256)/8;
-
-                       y =  299*r/1000 + 587*g/1000 + 114*b/1000 ;
-                       u = -147*r/1000 - 289*g/1000 + 436*b/1000 ;
-                       u = u + 128;
-                       v =  615*r/1000 - 515*g/1000 - 100*b/1000 ;
-                       v = v + 128;
-
-                       uyvy[0] =  0xFF & u ;
-                       uyvy[1] =  0xFF & y ;
-                       uyvy[2] =  0xFF & v ;
-                       uyvy[3] =  0xFF & y ;
-
-                       p1 = &bfbar[0];
-                       while (p1 < &bfbar[barwidth]) {
-                               *p1++ = uyvy[0] ;
-                               *p1++ = uyvy[1] ;
-                               *p1++ = uyvy[2] ;
-                               *p1++ = uyvy[3] ;
-                               total += 4;
-                       }
-
-                       p1 = &bfbar[0];
-                       more = barwidth;
-
-                       while (more) {
-                               if ((FIELD_BUFFER_SIZE/PAGE_SIZE) <= m) {
-                                       SAM("ERROR:  bad m reached\n");
-                                       return;
-                               }
-                               if (PAGE_SIZE < n) {
-                                       SAM("ERROR:  bad n reached\n");
-                                       return;
-                               }
-
-                               if (0 > more) {
-                                       SAM("ERROR:  internal fault\n");
-                                       return;
-                               }
-
-                               much = PAGE_SIZE - n;
-                               if (much > more)
-                                       much = more;
-                               pfield_buffer = &peasycap->field_buffer[k][m];
-                               p2 = pfield_buffer->pgo + n;
-                               memcpy(p2, p1, much);
-
-                               p1 += much;
-                               n += much;
-                               more -= much;
-                               if (PAGE_SIZE == n) {
-                                       m++;
-                                       n = 0;
-                               }
-                       }
-               }
-       }
-       return;
-}
index 6ee837c56706308b5a7fb951d088b878573e6072..3fdbef5306a0a9bea05d30822fb6287b2c378117 100644 (file)
@@ -24,7 +24,7 @@ s2250-y := s2250-board.o
 #ccflags-$(CONFIG_VIDEO_SAA7134:m=y) += -Idrivers/media/video/saa7134 -DSAA7134_MPEG_GO7007=3
 
 # S2250 needs cypress ezusb loader from dvb-usb
-ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/dvb/dvb-usb
+ccflags-$(CONFIG_VIDEO_GO7007_USB_S2250_BOARD:m=y) += -Idrivers/media/usb/dvb-usb
 
-ccflags-y += -Idrivers/media/dvb/frontends
-ccflags-y += -Idrivers/media/dvb/dvb-core
+ccflags-y += -Idrivers/media/dvb-frontends
+ccflags-y += -Idrivers/media/dvb-core
index c184ad30fbd8c6ea9e8cc9f806f582c917c0637c..980371b0274966b45b71a38621f4452e8bf0cf72 100644 (file)
@@ -1372,7 +1372,7 @@ static int vidioc_g_crop(struct file *file, void *priv, struct v4l2_crop *crop)
 
 /* FIXME: vidioc_s_crop is not really implemented!!!
  */
-static int vidioc_s_crop(struct file *file, void *priv, struct v4l2_crop *crop)
+static int vidioc_s_crop(struct file *file, void *priv, const struct v4l2_crop *crop)
 {
        if (crop->type != V4L2_BUF_TYPE_VIDEO_CAPTURE)
                return -EINVAL;
@@ -1392,7 +1392,7 @@ static int vidioc_g_jpegcomp(struct file *file, void *priv,
 }
 
 static int vidioc_s_jpegcomp(struct file *file, void *priv,
-                        struct v4l2_jpegcompression *params)
+                        const struct v4l2_jpegcompression *params)
 {
        if (params->quality != 50 ||
                        params->jpeg_markers != (V4L2_JPEG_MARKER_DHT |
index 526ec0fc2f042703b0237d9e29887dfd47fb23f8..e60a59fc252bd22255739b5053fe25fb8363e5d7 100644 (file)
@@ -63,12 +63,6 @@ config LIRC_SIR
        help
          Driver for the SIR IrDA port
 
-config LIRC_TTUSBIR
-       tristate "Technotrend USB IR Receiver"
-       depends on LIRC && USB
-       help
-         Driver for the Technotrend USB IR Receiver
-
 config LIRC_ZILOG
        tristate "Zilog/Hauppauge IR Transmitter"
        depends on LIRC && I2C
index d76b0fa2af53413bbfe4b318fda00e0beb060a73..b90fcabddab6fe48dbe93066cdf01d5b4674a5a4 100644 (file)
@@ -10,5 +10,4 @@ obj-$(CONFIG_LIRC_PARALLEL)   += lirc_parallel.o
 obj-$(CONFIG_LIRC_SASEM)       += lirc_sasem.o
 obj-$(CONFIG_LIRC_SERIAL)      += lirc_serial.o
 obj-$(CONFIG_LIRC_SIR)         += lirc_sir.o
-obj-$(CONFIG_LIRC_TTUSBIR)     += lirc_ttusbir.o
 obj-$(CONFIG_LIRC_ZILOG)       += lirc_zilog.o
diff --git a/drivers/staging/media/lirc/lirc_ene0100.h b/drivers/staging/media/lirc/lirc_ene0100.h
deleted file mode 100644 (file)
index 06bebd6..0000000
+++ /dev/null
@@ -1,169 +0,0 @@
-/*
- * driver for ENE KB3926 B/C/D CIR (also known as ENE0100)
- *
- * Copyright (C) 2009 Maxim Levitsky <maximlevitsky@gmail.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.
- *
- * 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 <media/lirc.h>
-#include <media/lirc_dev.h>
-
-/* hardware address */
-#define ENE_STATUS             0        /* hardware status - unused */
-#define ENE_ADDR_HI            1        /* hi byte of register address */
-#define ENE_ADDR_LO            2        /* low byte of register address */
-#define ENE_IO                 3        /* read/write window */
-#define ENE_MAX_IO             4
-
-/* 8 bytes of samples, divided in 2 halfs*/
-#define ENE_SAMPLE_BUFFER      0xF8F0   /* regular sample buffer */
-#define ENE_SAMPLE_SPC_MASK    (1 << 7) /* sample is space */
-#define ENE_SAMPLE_VALUE_MASK  0x7F
-#define ENE_SAMPLE_OVERFLOW    0x7F
-#define ENE_SAMPLES_SIZE       4
-
-/* fan input sample buffer */
-#define ENE_SAMPLE_BUFFER_FAN  0xF8FB   /* this buffer holds high byte of */
-                                        /* each sample of normal buffer */
-
-#define ENE_FAN_SMPL_PULS_MSK  0x8000   /* this bit of combined sample */
-                                        /* if set, says that sample is pulse */
-#define ENE_FAN_VALUE_MASK     0x0FFF   /* mask for valid bits of the value */
-
-/* first firmware register */
-#define ENE_FW1                        0xF8F8
-#define        ENE_FW1_ENABLE          (1 << 0) /* enable fw processing */
-#define ENE_FW1_TXIRQ          (1 << 1) /* TX interrupt pending */
-#define ENE_FW1_WAKE           (1 << 6) /* enable wake from S3 */
-#define ENE_FW1_IRQ            (1 << 7) /* enable interrupt */
-
-/* second firmware register */
-#define ENE_FW2                        0xF8F9
-#define ENE_FW2_BUF_HIGH       (1 << 0) /* which half of the buffer to read */
-#define ENE_FW2_IRQ_CLR                (1 << 2) /* clear this on IRQ */
-#define ENE_FW2_GP40_AS_LEARN  (1 << 4) /* normal input is used as */
-                                        /* learning input */
-#define ENE_FW2_FAN_AS_NRML_IN (1 << 6) /* fan is used as normal input */
-#define ENE_FW2_LEARNING       (1 << 7) /* hardware supports learning and TX */
-
-/* fan as input settings - only if learning capable */
-#define ENE_FAN_AS_IN1         0xFE30   /* fan init reg 1 */
-#define ENE_FAN_AS_IN1_EN      0xCD
-#define ENE_FAN_AS_IN2         0xFE31   /* fan init reg 2 */
-#define ENE_FAN_AS_IN2_EN      0x03
-#define ENE_SAMPLE_PERIOD_FAN   61      /* fan input has fixed sample period */
-
-/* IRQ registers block (for revision B) */
-#define ENEB_IRQ               0xFD09   /* IRQ number */
-#define ENEB_IRQ_UNK1          0xFD17   /* unknown setting = 1 */
-#define ENEB_IRQ_STATUS                0xFD80   /* irq status */
-#define ENEB_IRQ_STATUS_IR     (1 << 5) /* IR irq */
-
-/* IRQ registers block (for revision C,D) */
-#define ENEC_IRQ               0xFE9B   /* new irq settings register */
-#define ENEC_IRQ_MASK          0x0F     /* irq number mask */
-#define ENEC_IRQ_UNK_EN                (1 << 4) /* always enabled */
-#define ENEC_IRQ_STATUS                (1 << 5) /* irq status and ACK */
-
-/* CIR block settings */
-#define ENE_CIR_CONF1          0xFEC0
-#define ENE_CIR_CONF1_ADC_ON   0x7      /* receiver on gpio40 enabled */
-#define ENE_CIR_CONF1_LEARN1   (1 << 3) /* enabled on learning mode */
-#define ENE_CIR_CONF1_TX_ON    0x30     /* enabled on transmit */
-#define ENE_CIR_CONF1_TX_CARR  (1 << 7) /* send TX carrier or not */
-
-#define ENE_CIR_CONF2          0xFEC1   /* unknown setting = 0 */
-#define ENE_CIR_CONF2_LEARN2   (1 << 4) /* set on enable learning */
-#define ENE_CIR_CONF2_GPIO40DIS        (1 << 5) /* disable normal input via gpio40 */
-
-#define ENE_CIR_SAMPLE_PERIOD  0xFEC8   /* sample period in us */
-#define ENE_CIR_SAMPLE_OVERFLOW        (1 << 7) /* interrupt on overflows if set */
-
-
-/* transmitter - not implemented yet */
-/* KB3926C and higher */
-/* transmission is very similar to receiving, a byte is written to */
-/* ENE_TX_INPUT, in same manner as it is read from sample buffer */
-/* sample period is fixed*/
-
-
-/* transmitter ports */
-#define ENE_TX_PORT1           0xFC01   /* this enables one or both */
-#define ENE_TX_PORT1_EN                (1 << 5) /* TX ports */
-#define ENE_TX_PORT2           0xFC08
-#define ENE_TX_PORT2_EN                (1 << 1)
-
-#define ENE_TX_INPUT           0xFEC9   /* next byte to transmit */
-#define ENE_TX_SPC_MASK                (1 << 7) /* Transmitted sample is space */
-#define ENE_TX_UNK1            0xFECB   /* set to 0x63 */
-#define ENE_TX_SMPL_PERIOD     50       /* transmit sample period */
-
-
-#define ENE_TX_CARRIER         0xFECE   /* TX carrier * 2 (khz) */
-#define ENE_TX_CARRIER_UNKBIT  0x80     /* This bit set on transmit */
-#define ENE_TX_CARRIER_LOW     0xFECF   /* TX carrier / 2 */
-
-/* Hardware versions */
-#define ENE_HW_VERSION         0xFF00   /* hardware revision */
-#define ENE_HW_UNK             0xFF1D
-#define ENE_HW_UNK_CLR         (1 << 2)
-#define ENE_HW_VER_MAJOR       0xFF1E   /* chip version */
-#define ENE_HW_VER_MINOR       0xFF1F
-#define ENE_HW_VER_OLD         0xFD00
-
-#define same_sign(a, b) ((((a) > 0) && (b) > 0) || ((a) < 0 && (b) < 0))
-
-#define ENE_DRIVER_NAME                "enecir"
-#define ENE_MAXGAP             250000   /* this is amount of time we wait
-                                        before turning the sampler, chosen
-                                        arbitry */
-
-#define space(len)            (-(len))  /* add a space */
-
-/* software defines */
-#define ENE_IRQ_RX             1
-#define ENE_IRQ_TX             2
-
-#define  ENE_HW_B              1       /* 3926B */
-#define  ENE_HW_C              2       /* 3926C */
-#define  ENE_HW_D              3       /* 3926D */
-
-#define ene_printk(level, text, ...) \
-       printk(level ENE_DRIVER_NAME ": " text, ## __VA_ARGS__)
-
-struct ene_device {
-       struct pnp_dev *pnp_dev;
-       struct lirc_driver *lirc_driver;
-
-       /* hw settings */
-       unsigned long hw_io;
-       int irq;
-
-       int hw_revision;                        /* hardware revision */
-       int hw_learning_and_tx_capable;         /* learning capable */
-       int hw_gpio40_learning;                 /* gpio40 is learning */
-       int hw_fan_as_normal_input;     /* fan input is used as regular input */
-
-       /* device data */
-       int idle;
-       int fan_input_inuse;
-
-       int sample;
-       int in_use;
-
-       struct timeval gap_start;
-};
index 7a25017766790598f88622aa57e776581a505ea7..939a801c23e447a10c0e1ef7739e67320875549d 100644 (file)
@@ -325,8 +325,8 @@ static int igorplugusb_remote_poll(void *data, struct lirc_buffer *buf)
                if (ret < DEVICE_HEADERLEN)
                        return -ENODATA;
 
-               dprintk(DRIVER_NAME ": Got %d bytes. Header: %02x %02x %02x\n",
-                       ret, ir->buf_in[0], ir->buf_in[1], ir->buf_in[2]);
+               dprintk(DRIVER_NAME ": Got %d bytes. Header: %*ph\n",
+                       ret, 3, ir->buf_in);
 
                do_gettimeofday(&now);
                timediff = now.tv_sec - ir->last_time.tv_sec;
diff --git a/drivers/staging/media/lirc/lirc_ttusbir.c b/drivers/staging/media/lirc/lirc_ttusbir.c
deleted file mode 100644 (file)
index 3bb865c..0000000
+++ /dev/null
@@ -1,376 +0,0 @@
-/*
- * lirc_ttusbir.c
- *
- * lirc_ttusbir - LIRC device driver for the TechnoTrend USB IR Receiver
- *
- * Copyright (C) 2007 Stefan Macher <st_maker-lirc@yahoo.de>
- *
- * This LIRC driver provides access to the TechnoTrend USB IR Receiver.
- * The receiver delivers the IR signal as raw sampled true/false data in
- * isochronous USB packets each of size 128 byte.
- * Currently the driver reduces the sampling rate by factor of 8 as this
- * is still more than enough to decode RC-5 - others should be analyzed.
- * But the driver does not rely on RC-5 it should be able to decode every
- * IR signal that is not too fast.
- */
-
-/*
- *  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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
- */
-
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/module.h>
-#include <linux/errno.h>
-#include <linux/slab.h>
-#include <linux/usb.h>
-
-#include <media/lirc.h>
-#include <media/lirc_dev.h>
-
-MODULE_DESCRIPTION("TechnoTrend USB IR device driver for LIRC");
-MODULE_AUTHOR("Stefan Macher (st_maker-lirc@yahoo.de)");
-MODULE_LICENSE("GPL");
-
-/* #define DEBUG */
-#ifdef DEBUG
-#define DPRINTK printk
-#else
-#define DPRINTK(_x_, a...)
-#endif
-
-/* function declarations */
-static int probe(struct usb_interface *intf, const struct usb_device_id *id);
-static void disconnect(struct usb_interface *intf);
-static void urb_complete(struct urb *urb);
-static int set_use_inc(void *data);
-static void set_use_dec(void *data);
-
-static int num_urbs = 2;
-module_param(num_urbs, int, S_IRUGO);
-MODULE_PARM_DESC(num_urbs,
-                "Number of URBs in queue. Try to increase to 4 in case "
-                "of problems (default: 2; minimum: 2)");
-
-/* table of devices that work with this driver */
-static struct usb_device_id device_id_table[] = {
-       /* TechnoTrend USB IR Receiver */
-       { USB_DEVICE(0x0B48, 0x2003) },
-       /* Terminating entry */
-       { }
-};
-MODULE_DEVICE_TABLE(usb, device_id_table);
-
-/* USB driver definition */
-static struct usb_driver usb_driver = {
-       .name = "TTUSBIR",
-       .id_table = &(device_id_table[0]),
-       .probe = probe,
-       .disconnect = disconnect,
-};
-
-/* USB device definition */
-struct ttusbir_device {
-       struct usb_driver *usb_driver;
-       struct usb_device *udev;
-       struct usb_interface *interf;
-       struct usb_class_driver class_driver;
-       unsigned int ifnum; /* Interface number to use */
-       unsigned int alt_setting; /* alternate setting to use */
-       unsigned int endpoint; /* Endpoint to use */
-       struct urb **urb; /* num_urb URB pointers*/
-       char **buffer; /* 128 byte buffer for each URB */
-       struct lirc_buffer rbuf; /* Buffer towards LIRC */
-       struct lirc_driver driver;
-       int minor;
-       int last_pulse; /* remembers if last received byte was pulse or space */
-       int last_num; /* remembers how many last bytes appeared */
-       int opened;
-};
-
-/*** LIRC specific functions ***/
-static int set_use_inc(void *data)
-{
-       int i, retval;
-       struct ttusbir_device *ttusbir = data;
-
-       DPRINTK("Sending first URBs\n");
-       /* @TODO Do I need to check if I am already opened */
-       ttusbir->opened = 1;
-
-       for (i = 0; i < num_urbs; i++) {
-               retval = usb_submit_urb(ttusbir->urb[i], GFP_KERNEL);
-               if (retval) {
-                       dev_err(&ttusbir->interf->dev,
-                               "%s: usb_submit_urb failed on urb %d\n",
-                               __func__, i);
-                       return retval;
-               }
-       }
-       return 0;
-}
-
-static void set_use_dec(void *data)
-{
-       struct ttusbir_device *ttusbir = data;
-
-       DPRINTK("Device closed\n");
-
-       ttusbir->opened = 0;
-}
-
-/*** USB specific functions ***/
-
-/*
- * This mapping table is used to do a very simple filtering of the
- * input signal.
- * For a value with at least 4 bits set it returns 0xFF otherwise
- * 0x00.  For faster IR signals this can not be used. But for RC-5 we
- * still have about 14 samples per pulse/space, i.e. we sample with 14
- * times higher frequency than the signal frequency
- */
-const unsigned char map_table[] = {
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0x00, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF,
-       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-       0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF
-};
-
-static void urb_complete(struct urb *urb)
-{
-       struct ttusbir_device *ttusbir;
-       unsigned char *buf;
-       int i;
-       int l;
-
-       ttusbir = urb->context;
-
-       if (!ttusbir->opened)
-               return;
-
-       buf = (unsigned char *)urb->transfer_buffer;
-
-       for (i = 0; i < 128; i++) {
-               /* Here we do the filtering and some kind of down sampling */
-               buf[i] = ~map_table[buf[i]];
-               if (ttusbir->last_pulse == buf[i]) {
-                       if (ttusbir->last_num < PULSE_MASK/63)
-                               ttusbir->last_num++;
-               /*
-                * else we are in a idle period and do not need to
-                * increment any longer
-                */
-               } else {
-                       l = ttusbir->last_num * 62; /* about 62 = us/byte */
-                       if (ttusbir->last_pulse) /* pulse or space? */
-                               l |= PULSE_BIT;
-                       if (!lirc_buffer_full(&ttusbir->rbuf)) {
-                               lirc_buffer_write(&ttusbir->rbuf, (void *)&l);
-                               wake_up_interruptible(&ttusbir->rbuf.wait_poll);
-                       }
-                       ttusbir->last_num = 0;
-                       ttusbir->last_pulse = buf[i];
-               }
-       }
-       usb_submit_urb(urb, GFP_ATOMIC); /* keep data rolling :-) */
-}
-
-/*
- * Called whenever the USB subsystem thinks we could be the right driver
- * to handle this device
- */
-static int probe(struct usb_interface *intf, const struct usb_device_id *id)
-{
-       int alt_set, endp;
-       int found = 0;
-       int i, j;
-       int struct_size;
-       struct usb_host_interface *host_interf;
-       struct usb_interface_descriptor *interf_desc;
-       struct usb_host_endpoint *host_endpoint;
-       struct ttusbir_device *ttusbir;
-
-       DPRINTK("Module ttusbir probe\n");
-
-       /* To reduce memory fragmentation we use only one allocation */
-       struct_size =  sizeof(struct ttusbir_device) +
-               (sizeof(struct urb *) * num_urbs) +
-               (sizeof(char *) * num_urbs) +
-               (num_urbs * 128);
-       ttusbir = kzalloc(struct_size, GFP_KERNEL);
-       if (!ttusbir)
-               return -ENOMEM;
-
-       ttusbir->urb = (struct urb **)((char *)ttusbir +
-                                     sizeof(struct ttusbir_device));
-       ttusbir->buffer = (char **)((char *)ttusbir->urb +
-                                  (sizeof(struct urb *) * num_urbs));
-       for (i = 0; i < num_urbs; i++)
-               ttusbir->buffer[i] = (char *)ttusbir->buffer +
-                       (sizeof(char *)*num_urbs) + (i * 128);
-
-       ttusbir->usb_driver = &usb_driver;
-       ttusbir->alt_setting = -1;
-       /* @TODO check if error can be returned */
-       ttusbir->udev = usb_get_dev(interface_to_usbdev(intf));
-       ttusbir->interf = intf;
-       ttusbir->last_pulse = 0x00;
-       ttusbir->last_num = 0;
-
-       /*
-        * Now look for interface setting we can handle
-        * We are searching for the alt setting where end point
-        * 0x82 has max packet size 16
-        */
-       for (alt_set = 0; alt_set < intf->num_altsetting && !found; alt_set++) {
-               host_interf = &intf->altsetting[alt_set];
-               interf_desc = &host_interf->desc;
-               for (endp = 0; endp < interf_desc->bNumEndpoints; endp++) {
-                       host_endpoint = &host_interf->endpoint[endp];
-                       if ((host_endpoint->desc.bEndpointAddress == 0x82) &&
-                           (host_endpoint->desc.wMaxPacketSize == 0x10)) {
-                               ttusbir->alt_setting = alt_set;
-                               ttusbir->endpoint = endp;
-                               found = 1;
-                               break;
-                       }
-               }
-       }
-       if (ttusbir->alt_setting != -1)
-               DPRINTK("alt setting: %d\n", ttusbir->alt_setting);
-       else {
-               dev_err(&intf->dev, "Could not find alternate setting\n");
-               kfree(ttusbir);
-               return -EINVAL;
-       }
-
-       /* OK lets setup this interface setting */
-       usb_set_interface(ttusbir->udev, 0, ttusbir->alt_setting);
-
-       /* Store device info in interface structure */
-       usb_set_intfdata(intf, ttusbir);
-
-       /* Register as a LIRC driver */
-       if (lirc_buffer_init(&ttusbir->rbuf, sizeof(int), 256) < 0) {
-               dev_err(&intf->dev, "Could not get memory for LIRC data buffer\n");
-               usb_set_intfdata(intf, NULL);
-               kfree(ttusbir);
-               return -ENOMEM;
-       }
-       strcpy(ttusbir->driver.name, "TTUSBIR");
-       ttusbir->driver.minor = -1;
-       ttusbir->driver.code_length = 1;
-       ttusbir->driver.sample_rate = 0;
-       ttusbir->driver.data = ttusbir;
-       ttusbir->driver.add_to_buf = NULL;
-       ttusbir->driver.rbuf = &ttusbir->rbuf;
-       ttusbir->driver.set_use_inc = set_use_inc;
-       ttusbir->driver.set_use_dec = set_use_dec;
-       ttusbir->driver.dev = &intf->dev;
-       ttusbir->driver.owner = THIS_MODULE;
-       ttusbir->driver.features = LIRC_CAN_REC_MODE2;
-       ttusbir->minor = lirc_register_driver(&ttusbir->driver);
-       if (ttusbir->minor < 0) {
-               dev_err(&intf->dev, "Error registering as LIRC driver\n");
-               usb_set_intfdata(intf, NULL);
-               lirc_buffer_free(&ttusbir->rbuf);
-               kfree(ttusbir);
-               return -EIO;
-       }
-
-       /* Allocate and setup the URB that we will use to talk to the device */
-       for (i = 0; i < num_urbs; i++) {
-               ttusbir->urb[i] = usb_alloc_urb(8, GFP_KERNEL);
-               if (!ttusbir->urb[i]) {
-                       dev_err(&intf->dev, "Could not allocate memory for the URB\n");
-                       for (j = i - 1; j >= 0; j--)
-                               kfree(ttusbir->urb[j]);
-                       lirc_buffer_free(&ttusbir->rbuf);
-                       lirc_unregister_driver(ttusbir->minor);
-                       kfree(ttusbir);
-                       usb_set_intfdata(intf, NULL);
-                       return -ENOMEM;
-               }
-               ttusbir->urb[i]->dev = ttusbir->udev;
-               ttusbir->urb[i]->context = ttusbir;
-               ttusbir->urb[i]->pipe = usb_rcvisocpipe(ttusbir->udev,
-                                                       ttusbir->endpoint);
-               ttusbir->urb[i]->interval = 1;
-               ttusbir->urb[i]->transfer_flags = URB_ISO_ASAP;
-               ttusbir->urb[i]->transfer_buffer = &ttusbir->buffer[i][0];
-               ttusbir->urb[i]->complete = urb_complete;
-               ttusbir->urb[i]->number_of_packets = 8;
-               ttusbir->urb[i]->transfer_buffer_length = 128;
-               for (j = 0; j < 8; j++) {
-                       ttusbir->urb[i]->iso_frame_desc[j].offset = j*16;
-                       ttusbir->urb[i]->iso_frame_desc[j].length = 16;
-               }
-       }
-       return 0;
-}
-
-/**
- * Called when the driver is unloaded or the device is unplugged
- */
-static void disconnect(struct usb_interface *intf)
-{
-       int i;
-       struct ttusbir_device *ttusbir;
-
-       DPRINTK("Module ttusbir disconnect\n");
-
-       ttusbir = (struct ttusbir_device *) usb_get_intfdata(intf);
-       usb_set_intfdata(intf, NULL);
-       lirc_unregister_driver(ttusbir->minor);
-       DPRINTK("unregistered\n");
-
-       for (i = 0; i < num_urbs; i++) {
-               usb_kill_urb(ttusbir->urb[i]);
-               usb_free_urb(ttusbir->urb[i]);
-       }
-       DPRINTK("URBs killed\n");
-       lirc_buffer_free(&ttusbir->rbuf);
-       kfree(ttusbir);
-}
-
-module_usb_driver(usb_driver);
index 76ea4a8f2c751a865bce422d50da43dbf940880c..11d5338b4f2ffaa458ddc6729a5ea48298e17227 100644 (file)
@@ -658,8 +658,7 @@ static int send_data_block(struct IR_tx *tx, unsigned char *data_block)
                buf[0] = (unsigned char)(i + 1);
                for (j = 0; j < tosend; ++j)
                        buf[1 + j] = data_block[i + j];
-               dprintk("%02x %02x %02x %02x %02x",
-                       buf[0], buf[1], buf[2], buf[3], buf[4]);
+               dprintk("%*ph", 5, buf);
                ret = i2c_master_send(tx->c, buf, tosend + 1);
                if (ret != tosend + 1) {
                        zilog_error("i2c_master_send failed with %d\n", ret);
index 695ea35f75b0831cc8e2d28369d9ef124f8c2da9..d0a7e408efe93847606d1db21397fab44aba1ae6 100644 (file)
@@ -837,7 +837,7 @@ static int __devinit tegra_nvec_probe(struct platform_device *pdev)
        }
 
        ret = mfd_add_devices(nvec->dev, -1, nvec_devices,
-                             ARRAY_SIZE(nvec_devices), base, 0);
+                             ARRAY_SIZE(nvec_devices), base, 0, NULL);
        if (ret)
                dev_err(nvec->dev, "error adding subdevices\n");
 
index 5e2856c0e0bbf3ead714ca105d06e54e1dff1545..55e9c865585058e9195e3eeef9aa8c554b57c886 100644 (file)
@@ -48,13 +48,20 @@ static inline void copy_timings_omap_to_drm(struct drm_display_mode *mode,
        mode->vsync_end = mode->vsync_start + timings->vsw;
        mode->vtotal = mode->vsync_end + timings->vbp;
 
-       /* note: whether or not it is interlaced, +/- h/vsync, etc,
-        * which should be set in the mode flags, is not exposed in
-        * the omap_video_timings struct.. but hdmi driver tracks
-        * those separately so all we have to have to set the mode
-        * is the way to recover these timings values, and the
-        * omap_dss_driver would do the rest.
-        */
+       mode->flags = 0;
+
+       if (timings->interlace)
+               mode->flags |= DRM_MODE_FLAG_INTERLACE;
+
+       if (timings->hsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+               mode->flags |= DRM_MODE_FLAG_PHSYNC;
+       else
+               mode->flags |= DRM_MODE_FLAG_NHSYNC;
+
+       if (timings->vsync_level == OMAPDSS_SIG_ACTIVE_HIGH)
+               mode->flags |= DRM_MODE_FLAG_PVSYNC;
+       else
+               mode->flags |= DRM_MODE_FLAG_NVSYNC;
 }
 
 static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
@@ -71,6 +78,22 @@ static inline void copy_timings_drm_to_omap(struct omap_video_timings *timings,
        timings->vfp = mode->vsync_start - mode->vdisplay;
        timings->vsw = mode->vsync_end - mode->vsync_start;
        timings->vbp = mode->vtotal - mode->vsync_end;
+
+       timings->interlace = !!(mode->flags & DRM_MODE_FLAG_INTERLACE);
+
+       if (mode->flags & DRM_MODE_FLAG_PHSYNC)
+               timings->hsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       else
+               timings->hsync_level = OMAPDSS_SIG_ACTIVE_LOW;
+
+       if (mode->flags & DRM_MODE_FLAG_PVSYNC)
+               timings->vsync_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       else
+               timings->vsync_level = OMAPDSS_SIG_ACTIVE_LOW;
+
+       timings->data_pclk_edge = OMAPDSS_DRIVE_SIG_RISING_EDGE;
+       timings->de_level = OMAPDSS_SIG_ACTIVE_HIGH;
+       timings->sync_pclk_edge = OMAPDSS_DRIVE_SIG_OPPOSITE_EDGES;
 }
 
 static void omap_connector_dpms(struct drm_connector *connector, int mode)
@@ -187,7 +210,7 @@ static int omap_connector_get_modes(struct drm_connector *connector)
                }
        } else {
                struct drm_display_mode *mode = drm_mode_create(dev);
-               struct omap_video_timings timings;
+               struct omap_video_timings timings = {0};
 
                dssdrv->get_timings(dssdev, &timings);
 
@@ -291,7 +314,7 @@ void omap_connector_mode_set(struct drm_connector *connector,
        struct omap_connector *omap_connector = to_omap_connector(connector);
        struct omap_dss_device *dssdev = omap_connector->dssdev;
        struct omap_dss_driver *dssdrv = dssdev->driver;
-       struct omap_video_timings timings;
+       struct omap_video_timings timings = {0};
 
        copy_timings_drm_to_omap(&timings, mode);
 
index d98321945802c8daf8ec71cc3908ec0c44133c7a..758ce0a8d82e03c59d326b5ce0f6b8bdda425b25 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/cdev.h>
 #include <linux/uaccess.h>
 #include <linux/netdevice.h>
+#include <linux/etherdevice.h>
 #include <linux/poll.h>
 #include <linux/sched.h>
 #include "ozconfig.h"
@@ -213,7 +214,7 @@ static int oz_set_active_pd(u8 *addr)
                if (old_pd)
                        oz_pd_put(old_pd);
        } else {
-               if (!memcmp(addr, "\0\0\0\0\0\0", sizeof(addr))) {
+               if (is_zero_ether_addr(addr)) {
                        spin_lock_bh(&g_cdev.lock);
                        pd = g_cdev.active_pd;
                        g_cdev.active_pd = 0;
index 0e26d5f6cf2d57d64eca7d5440af7da0f77443cd..495ee1205e02a9c77aa59a1e7ec5da1cf255d534 100644 (file)
@@ -117,13 +117,8 @@ void r8712_recv_indicatepkt(struct _adapter *padapter,
        if (skb == NULL)
                goto _recv_indicatepkt_drop;
        skb->data = precv_frame->u.hdr.rx_data;
-#ifdef NET_SKBUFF_DATA_USES_OFFSET
-       skb->tail = (sk_buff_data_t)(precv_frame->u.hdr.rx_tail -
-                    precv_frame->u.hdr.rx_head);
-#else
-       skb->tail = (sk_buff_data_t)precv_frame->u.hdr.rx_tail;
-#endif
        skb->len = precv_frame->u.hdr.len;
+       skb_set_tail_pointer(skb, skb->len);
        if ((pattrib->tcpchk_valid == 1) && (pattrib->tcp_chkrpt == 1))
                skb->ip_summed = CHECKSUM_UNNECESSARY;
        else
index e4bdf2a2b5829292e23d8f4675fab023249e16d3..3aa895ec6507f7dde81f1440b4af349e792dc1cd 100644 (file)
@@ -200,7 +200,7 @@ s_vProcessRxMACHeader (
     } else if (!compare_ether_addr(pbyRxBuffer, &pDevice->abySNAP_RFC1042[0])) {
         cbHeaderSize += 6;
         pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
-       if ((*pwType == cpu_to_le16(ETH_P_IPX)) ||
+       if ((*pwType == cpu_to_be16(ETH_P_IPX)) ||
            (*pwType == cpu_to_le16(0xF380))) {
                cbHeaderSize -= 8;
             pwType = (PWORD) (pbyRxBufferAddr + cbHeaderSize);
index bb464527fc1b06e8814b05c23c97e89208cda92e..b6e04e7b629bdc0a63a04ac4f47698abed3cece8 100644 (file)
@@ -1699,7 +1699,7 @@ s_bPacketToWirelessUsb(
     // 802.1H
     if (ntohs(psEthHeader->wType) > ETH_DATA_LEN) {
        if (pDevice->dwDiagRefCount == 0) {
-               if ((psEthHeader->wType == cpu_to_le16(ETH_P_IPX)) ||
+               if ((psEthHeader->wType == cpu_to_be16(ETH_P_IPX)) ||
                    (psEthHeader->wType == cpu_to_le16(0xF380))) {
                        memcpy((PBYTE) (pbyPayloadHead),
                               abySNAP_Bridgetunnel, 6);
@@ -2838,10 +2838,10 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
     Packet_Type = skb->data[ETH_HLEN+1];
     Descriptor_type = skb->data[ETH_HLEN+1+1+2];
     Key_info = (skb->data[ETH_HLEN+1+1+2+1] << 8)|(skb->data[ETH_HLEN+1+1+2+2]);
-    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
-       /* 802.1x OR eapol-key challenge frame transfer */
-       if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
-               (Packet_Type == 3)) {
+       if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+               /* 802.1x OR eapol-key challenge frame transfer */
+               if (((Protocol_Version == 1) || (Protocol_Version == 2)) &&
+                       (Packet_Type == 3)) {
                         bTxeapol_key = TRUE;
                        if(!(Key_info & BIT3) &&  //WPA or RSN group-key challenge
                           (Key_info & BIT8) && (Key_info & BIT9)) {    //send 2/2 key
@@ -2987,19 +2987,19 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
         }
     }
 
-    if (pDevice->sTxEthHeader.wType == cpu_to_le16(ETH_P_PAE)) {
-        if (pDevice->byBBType != BB_TYPE_11A) {
-            pDevice->wCurrentRate = RATE_1M;
-            pDevice->byACKRate = RATE_1M;
-            pDevice->byTopCCKBasicRate = RATE_1M;
-            pDevice->byTopOFDMBasicRate = RATE_6M;
-        } else {
-            pDevice->wCurrentRate = RATE_6M;
-            pDevice->byACKRate = RATE_6M;
-            pDevice->byTopCCKBasicRate = RATE_1M;
-            pDevice->byTopOFDMBasicRate = RATE_6M;
-        }
-    }
+       if (pDevice->sTxEthHeader.wType == cpu_to_be16(ETH_P_PAE)) {
+               if (pDevice->byBBType != BB_TYPE_11A) {
+                       pDevice->wCurrentRate = RATE_1M;
+                       pDevice->byACKRate = RATE_1M;
+                       pDevice->byTopCCKBasicRate = RATE_1M;
+                       pDevice->byTopOFDMBasicRate = RATE_6M;
+               } else {
+                       pDevice->wCurrentRate = RATE_6M;
+                       pDevice->byACKRate = RATE_6M;
+                       pDevice->byTopCCKBasicRate = RATE_1M;
+                       pDevice->byTopOFDMBasicRate = RATE_6M;
+               }
+       }
 
     DBG_PRT(MSG_LEVEL_DEBUG,
            KERN_INFO "dma_tx: pDevice->wCurrentRate = %d\n",
@@ -3015,7 +3015,7 @@ int nsDMA_tx_packet(PSDevice pDevice, unsigned int uDMAIdx, struct sk_buff *skb)
 
     if (bNeedEncryption == TRUE) {
         DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"ntohs Pkt Type=%04x\n", ntohs(pDevice->sTxEthHeader.wType));
-       if ((pDevice->sTxEthHeader.wType) == cpu_to_le16(ETH_P_PAE)) {
+       if ((pDevice->sTxEthHeader.wType) == cpu_to_be16(ETH_P_PAE)) {
                bNeedEncryption = FALSE;
             DBG_PRT(MSG_LEVEL_DEBUG, KERN_INFO"Pkt Type=%04x\n", (pDevice->sTxEthHeader.wType));
             if ((pMgmt->eCurrMode == WMAC_MODE_ESS_STA) && (pMgmt->eCurrState == WMAC_STATE_ASSOC)) {
index fabff4d650ef8c5645ed26dfeb5a46e452d26c05..0970127344e60828e569e1ca87ee6c82cb3f11eb 100644 (file)
@@ -327,9 +327,9 @@ int prism2_get_station(struct wiphy *wiphy, struct net_device *dev,
        return result;
 }
 
-int prism2_scan(struct wiphy *wiphy, struct net_device *dev,
-               struct cfg80211_scan_request *request)
+int prism2_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
 {
+       struct net_device *dev = request->wdev->netdev;
        struct prism2_wiphy_private *priv = wiphy_priv(wiphy);
        wlandevice_t *wlandev = dev->ml_priv;
        struct p80211msg_dot11req_scan msg1;
index c214977b4ab48adec84fc260df0116b12b498aa7..52b43b7b83d7b3c9d7e3acfc853912afc64c2b61 100644 (file)
@@ -1251,13 +1251,12 @@ static int zcache_pampd_get_data_and_free(char *data, size_t *bufsize, bool raw,
                                        void *pampd, struct tmem_pool *pool,
                                        struct tmem_oid *oid, uint32_t index)
 {
-       int ret = 0;
-
        BUG_ON(!is_ephemeral(pool));
-       zbud_decompress((struct page *)(data), pampd);
+       if (zbud_decompress((struct page *)(data), pampd) < 0)
+               return -EINVAL;
        zbud_free_and_delist((struct zbud_hdr *)pampd);
        atomic_dec(&zcache_curr_eph_pampd_count);
-       return ret;
+       return 0;
 }
 
 /*
index 0694d9b1bce6a4e066a7bba1b1ef5f870b4b51d7..6aba4395e8d8ffd5aa950c4dfc745791c3f65fc2 100644 (file)
@@ -221,6 +221,7 @@ static int iscsi_login_zero_tsih_s1(
 {
        struct iscsi_session *sess = NULL;
        struct iscsi_login_req *pdu = (struct iscsi_login_req *)buf;
+       int ret;
 
        sess = kzalloc(sizeof(struct iscsi_session), GFP_KERNEL);
        if (!sess) {
@@ -257,9 +258,17 @@ static int iscsi_login_zero_tsih_s1(
                return -ENOMEM;
        }
        spin_lock(&sess_idr_lock);
-       idr_get_new(&sess_idr, NULL, &sess->session_index);
+       ret = idr_get_new(&sess_idr, NULL, &sess->session_index);
        spin_unlock(&sess_idr_lock);
 
+       if (ret < 0) {
+               pr_err("idr_get_new() for sess_idr failed\n");
+               iscsit_tx_login_rsp(conn, ISCSI_STATUS_CLS_TARGET_ERR,
+                               ISCSI_LOGIN_STATUS_NO_RESOURCES);
+               kfree(sess);
+               return -ENOMEM;
+       }
+
        sess->creation_time = get_jiffies_64();
        spin_lock_init(&sess->session_stats_lock);
        /*
index 91799973081a3d907cd260792df3f573d1dbec82..41641ba548286e9dbf33f45a02ece5b20eec0d14 100644 (file)
@@ -218,6 +218,13 @@ int target_emulate_set_target_port_groups(struct se_cmd *cmd)
                cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                return -EINVAL;
        }
+       if (cmd->data_length < 4) {
+               pr_warn("SET TARGET PORT GROUPS parameter list length %u too"
+                       " small\n", cmd->data_length);
+               cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+               return -EINVAL;
+       }
+
        buf = transport_kmap_data_sg(cmd);
 
        /*
index cf2c66f3c11690c81ca23e9fd2ce286e76b56e62..9fc9a6006ca082076a6d235dfad676e1e1a11ea9 100644 (file)
@@ -669,6 +669,13 @@ int target_report_luns(struct se_cmd *se_cmd)
        unsigned char *buf;
        u32 lun_count = 0, offset = 8, i;
 
+       if (se_cmd->data_length < 16) {
+               pr_warn("REPORT LUNS allocation length %u too small\n",
+                       se_cmd->data_length);
+               se_cmd->scsi_sense_reason = TCM_INVALID_CDB_FIELD;
+               return -EINVAL;
+       }
+
        buf = transport_kmap_data_sg(se_cmd);
        if (!buf)
                return -ENOMEM;
index 76db75e836ede701c2aed6090a212fdf1a08ad10..9ba495477fd24f80bf6643cfae3707525b7c165e 100644 (file)
@@ -325,17 +325,30 @@ static int iblock_execute_unmap(struct se_cmd *cmd)
        struct iblock_dev *ibd = dev->dev_ptr;
        unsigned char *buf, *ptr = NULL;
        sector_t lba;
-       int size = cmd->data_length;
+       int size;
        u32 range;
        int ret = 0;
        int dl, bd_dl;
 
+       if (cmd->data_length < 8) {
+               pr_warn("UNMAP parameter list length %u too small\n",
+                       cmd->data_length);
+               cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+               return -EINVAL;
+       }
+
        buf = transport_kmap_data_sg(cmd);
 
        dl = get_unaligned_be16(&buf[0]);
        bd_dl = get_unaligned_be16(&buf[2]);
 
-       size = min(size - 8, bd_dl);
+       size = cmd->data_length - 8;
+       if (bd_dl > size)
+               pr_warn("UNMAP parameter list length %u too small, ignoring bd_dl %u\n",
+                       cmd->data_length, bd_dl);
+       else
+               size = bd_dl;
+
        if (size / 16 > dev->se_sub_dev->se_dev_attrib.max_unmap_block_desc_count) {
                cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
                ret = -EINVAL;
index 1e946502c378886aa90bafc16239d2c34730b9fb..956c84c6b666498caabf7b60b7404413698c0b14 100644 (file)
@@ -1540,6 +1540,14 @@ static int core_scsi3_decode_spec_i_port(
        tidh_new->dest_local_nexus = 1;
        list_add_tail(&tidh_new->dest_list, &tid_dest_list);
 
+       if (cmd->data_length < 28) {
+               pr_warn("SPC-PR: Received PR OUT parameter list"
+                       " length too small: %u\n", cmd->data_length);
+               cmd->scsi_sense_reason = TCM_INVALID_PARAMETER_LIST;
+               ret = -EINVAL;
+               goto out;
+       }
+
        buf = transport_kmap_data_sg(cmd);
        /*
         * For a PERSISTENT RESERVE OUT specify initiator ports payload,
index 5552fa7426bc9b317da906dec2e395bbf854ae78..9d7ce3daa26275a7c08b831ae9b955382e0e9103 100644 (file)
@@ -667,7 +667,8 @@ static void pscsi_free_device(void *p)
        kfree(pdv);
 }
 
-static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
+static void pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg,
+                                    unsigned char *sense_buffer)
 {
        struct pscsi_dev_virt *pdv = cmd->se_dev->dev_ptr;
        struct scsi_device *sd = pdv->pdv_sd;
@@ -679,7 +680,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
         * not been allocated because TCM is handling the emulation directly.
         */
        if (!pt)
-               return 0;
+               return;
 
        cdb = &pt->pscsi_cdb[0];
        result = pt->pscsi_result;
@@ -687,11 +688,11 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
         * Hack to make sure that Write-Protect modepage is set if R/O mode is
         * forced.
         */
+       if (!cmd->se_deve || !cmd->data_length)
+               goto after_mode_sense;
+
        if (((cdb[0] == MODE_SENSE) || (cdb[0] == MODE_SENSE_10)) &&
             (status_byte(result) << 1) == SAM_STAT_GOOD) {
-               if (!cmd->se_deve)
-                       goto after_mode_sense;
-
                if (cmd->se_deve->lun_flags & TRANSPORT_LUNFLAGS_READ_ONLY) {
                        unsigned char *buf = transport_kmap_data_sg(cmd);
 
@@ -708,7 +709,7 @@ static int pscsi_transport_complete(struct se_cmd *cmd, struct scatterlist *sg)
        }
 after_mode_sense:
 
-       if (sd->type != TYPE_TAPE)
+       if (sd->type != TYPE_TAPE || !cmd->data_length)
                goto after_mode_select;
 
        /*
@@ -750,10 +751,10 @@ after_mode_sense:
        }
 after_mode_select:
 
-       if (status_byte(result) & CHECK_CONDITION)
-               return 1;
-
-       return 0;
+       if (sense_buffer && (status_byte(result) & CHECK_CONDITION)) {
+               memcpy(sense_buffer, pt->pscsi_sense, TRANSPORT_SENSE_BUFFER);
+               cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
+       }
 }
 
 enum {
@@ -1184,13 +1185,6 @@ fail:
        return -ENOMEM;
 }
 
-static unsigned char *pscsi_get_sense_buffer(struct se_cmd *cmd)
-{
-       struct pscsi_plugin_task *pt = cmd->priv;
-
-       return pt->pscsi_sense;
-}
-
 /*     pscsi_get_device_rev():
  *
  *
@@ -1273,7 +1267,6 @@ static struct se_subsystem_api pscsi_template = {
        .check_configfs_dev_params = pscsi_check_configfs_dev_params,
        .set_configfs_dev_params = pscsi_set_configfs_dev_params,
        .show_configfs_dev_params = pscsi_show_configfs_dev_params,
-       .get_sense_buffer       = pscsi_get_sense_buffer,
        .get_device_rev         = pscsi_get_device_rev,
        .get_device_type        = pscsi_get_device_type,
        .get_blocks             = pscsi_get_blocks,
index 4c861de538c9ddb627356e8aa3ea992b164033cf..388a922c8f6de8f4f2a18f7bea85f5b3590b41a9 100644 (file)
@@ -877,9 +877,11 @@ static int spc_emulate_modesense(struct se_cmd *cmd)
 static int spc_emulate_request_sense(struct se_cmd *cmd)
 {
        unsigned char *cdb = cmd->t_task_cdb;
-       unsigned char *buf;
+       unsigned char *rbuf;
        u8 ua_asc = 0, ua_ascq = 0;
-       int err = 0;
+       unsigned char buf[SE_SENSE_BUF];
+
+       memset(buf, 0, SE_SENSE_BUF);
 
        if (cdb[1] & 0x01) {
                pr_err("REQUEST_SENSE description emulation not"
@@ -888,20 +890,21 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
                return -ENOSYS;
        }
 
-       buf = transport_kmap_data_sg(cmd);
-
-       if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
+       rbuf = transport_kmap_data_sg(cmd);
+       if (cmd->scsi_sense_reason != 0) {
+               /*
+                * Out of memory.  We will fail with CHECK CONDITION, so
+                * we must not clear the unit attention condition.
+                */
+               target_complete_cmd(cmd, CHECK_CONDITION);
+               return 0;
+       } else if (!core_scsi3_ua_clear_for_request_sense(cmd, &ua_asc, &ua_ascq)) {
                /*
                 * CURRENT ERROR, UNIT ATTENTION
                 */
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = UNIT_ATTENTION;
 
-               if (cmd->data_length < 18) {
-                       buf[7] = 0x00;
-                       err = -EINVAL;
-                       goto end;
-               }
                /*
                 * The Additional Sense Code (ASC) from the UNIT ATTENTION
                 */
@@ -915,11 +918,6 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
                buf[0] = 0x70;
                buf[SPC_SENSE_KEY_OFFSET] = NO_SENSE;
 
-               if (cmd->data_length < 18) {
-                       buf[7] = 0x00;
-                       err = -EINVAL;
-                       goto end;
-               }
                /*
                 * NO ADDITIONAL SENSE INFORMATION
                 */
@@ -927,8 +925,11 @@ static int spc_emulate_request_sense(struct se_cmd *cmd)
                buf[7] = 0x0A;
        }
 
-end:
-       transport_kunmap_data_sg(cmd);
+       if (rbuf) {
+               memcpy(rbuf, buf, min_t(u32, sizeof(buf), cmd->data_length));
+               transport_kunmap_data_sg(cmd);
+       }
+
        target_complete_cmd(cmd, GOOD);
        return 0;
 }
index 4de3186dc44e99672d3666a24ec145e058183691..269f54488397bd2193bb80869bf9de8ac4c73bf2 100644 (file)
@@ -567,6 +567,34 @@ static void target_complete_failure_work(struct work_struct *work)
        transport_generic_request_failure(cmd);
 }
 
+/*
+ * Used when asking transport to copy Sense Data from the underlying
+ * Linux/SCSI struct scsi_cmnd
+ */
+static unsigned char *transport_get_sense_buffer(struct se_cmd *cmd)
+{
+       unsigned char *buffer = cmd->sense_buffer;
+       struct se_device *dev = cmd->se_dev;
+       u32 offset = 0;
+
+       WARN_ON(!cmd->se_lun);
+
+       if (!dev)
+               return NULL;
+
+       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION)
+               return NULL;
+
+       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
+
+       /* Automatically padded */
+       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
+
+       pr_debug("HBA_[%u]_PLUG[%s]: Requesting sense for SAM STATUS: 0x%02x\n",
+               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
+       return &buffer[offset];
+}
+
 void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
 {
        struct se_device *dev = cmd->se_dev;
@@ -580,11 +608,11 @@ void target_complete_cmd(struct se_cmd *cmd, u8 scsi_status)
        cmd->transport_state &= ~CMD_T_BUSY;
 
        if (dev && dev->transport->transport_complete) {
-               if (dev->transport->transport_complete(cmd,
-                               cmd->t_data_sg) != 0) {
-                       cmd->se_cmd_flags |= SCF_TRANSPORT_TASK_SENSE;
+               dev->transport->transport_complete(cmd,
+                               cmd->t_data_sg,
+                               transport_get_sense_buffer(cmd));
+               if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE)
                        success = 1;
-               }
        }
 
        /*
@@ -1181,15 +1209,20 @@ int target_cmd_size_check(struct se_cmd *cmd, unsigned int size)
                        /* Returns CHECK_CONDITION + INVALID_CDB_FIELD */
                        goto out_invalid_cdb_field;
                }
-
+               /*
+                * For the overflow case keep the existing fabric provided
+                * ->data_length.  Otherwise for the underflow case, reset
+                * ->data_length to the smaller SCSI expected data transfer
+                * length.
+                */
                if (size > cmd->data_length) {
                        cmd->se_cmd_flags |= SCF_OVERFLOW_BIT;
                        cmd->residual_count = (size - cmd->data_length);
                } else {
                        cmd->se_cmd_flags |= SCF_UNDERFLOW_BIT;
                        cmd->residual_count = (cmd->data_length - size);
+                       cmd->data_length = size;
                }
-               cmd->data_length = size;
        }
 
        return 0;
@@ -1815,61 +1848,6 @@ execute:
 }
 EXPORT_SYMBOL(target_execute_cmd);
 
-/*
- * Used to obtain Sense Data from underlying Linux/SCSI struct scsi_cmnd
- */
-static int transport_get_sense_data(struct se_cmd *cmd)
-{
-       unsigned char *buffer = cmd->sense_buffer, *sense_buffer = NULL;
-       struct se_device *dev = cmd->se_dev;
-       unsigned long flags;
-       u32 offset = 0;
-
-       WARN_ON(!cmd->se_lun);
-
-       if (!dev)
-               return 0;
-
-       spin_lock_irqsave(&cmd->t_state_lock, flags);
-       if (cmd->se_cmd_flags & SCF_SENT_CHECK_CONDITION) {
-               spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-               return 0;
-       }
-
-       if (!(cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE))
-               goto out;
-
-       if (!dev->transport->get_sense_buffer) {
-               pr_err("dev->transport->get_sense_buffer is NULL\n");
-               goto out;
-       }
-
-       sense_buffer = dev->transport->get_sense_buffer(cmd);
-       if (!sense_buffer) {
-               pr_err("ITT 0x%08x cmd %p: Unable to locate"
-                       " sense buffer for task with sense\n",
-                       cmd->se_tfo->get_task_tag(cmd), cmd);
-               goto out;
-       }
-
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-
-       offset = cmd->se_tfo->set_fabric_sense_len(cmd, TRANSPORT_SENSE_BUFFER);
-
-       memcpy(&buffer[offset], sense_buffer, TRANSPORT_SENSE_BUFFER);
-
-       /* Automatically padded */
-       cmd->scsi_sense_length = TRANSPORT_SENSE_BUFFER + offset;
-
-       pr_debug("HBA_[%u]_PLUG[%s]: Set SAM STATUS: 0x%02x and sense\n",
-               dev->se_hba->hba_id, dev->transport->name, cmd->scsi_status);
-       return 0;
-
-out:
-       spin_unlock_irqrestore(&cmd->t_state_lock, flags);
-       return -1;
-}
-
 /*
  * Process all commands up to the last received ORDERED task attribute which
  * requires another blocking boundary
@@ -1985,7 +1963,7 @@ static void transport_handle_queue_full(
 static void target_complete_ok_work(struct work_struct *work)
 {
        struct se_cmd *cmd = container_of(work, struct se_cmd, work);
-       int reason = 0, ret;
+       int ret;
 
        /*
         * Check if we need to move delayed/dormant tasks from cmds on the
@@ -2002,23 +1980,19 @@ static void target_complete_ok_work(struct work_struct *work)
                schedule_work(&cmd->se_dev->qf_work_queue);
 
        /*
-        * Check if we need to retrieve a sense buffer from
+        * Check if we need to send a sense buffer from
         * the struct se_cmd in question.
         */
        if (cmd->se_cmd_flags & SCF_TRANSPORT_TASK_SENSE) {
-               if (transport_get_sense_data(cmd) < 0)
-                       reason = TCM_NON_EXISTENT_LUN;
-
-               if (cmd->scsi_status) {
-                       ret = transport_send_check_condition_and_sense(
-                                       cmd, reason, 1);
-                       if (ret == -EAGAIN || ret == -ENOMEM)
-                               goto queue_full;
+               WARN_ON(!cmd->scsi_status);
+               ret = transport_send_check_condition_and_sense(
+                                       cmd, 0, 1);
+               if (ret == -EAGAIN || ret == -ENOMEM)
+                       goto queue_full;
 
-                       transport_lun_remove_cmd(cmd);
-                       transport_cmd_check_stop_to_fabric(cmd);
-                       return;
-               }
+               transport_lun_remove_cmd(cmd);
+               transport_cmd_check_stop_to_fabric(cmd);
+               return;
        }
        /*
         * Check for a callback, used by amongst other things
@@ -2216,7 +2190,6 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
        struct page **pages;
        int i;
 
-       BUG_ON(!sg);
        /*
         * We need to take into account a possible offset here for fabrics like
         * tcm_loop who may be using a contig buffer from the SCSI midlayer for
@@ -2224,13 +2197,17 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
         */
        if (!cmd->t_data_nents)
                return NULL;
-       else if (cmd->t_data_nents == 1)
+
+       BUG_ON(!sg);
+       if (cmd->t_data_nents == 1)
                return kmap(sg_page(sg)) + sg->offset;
 
        /* >1 page. use vmap */
        pages = kmalloc(sizeof(*pages) * cmd->t_data_nents, GFP_KERNEL);
-       if (!pages)
+       if (!pages) {
+               cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                return NULL;
+       }
 
        /* convert sg[] to pages[] */
        for_each_sg(cmd->t_data_sg, sg, cmd->t_data_nents, i) {
@@ -2239,8 +2216,10 @@ void *transport_kmap_data_sg(struct se_cmd *cmd)
 
        cmd->t_data_vmap = vmap(pages, cmd->t_data_nents,  VM_MAP, PAGE_KERNEL);
        kfree(pages);
-       if (!cmd->t_data_vmap)
+       if (!cmd->t_data_vmap) {
+               cmd->scsi_sense_reason = TCM_LOGICAL_UNIT_COMMUNICATION_FAILURE;
                return NULL;
+       }
 
        return cmd->t_data_vmap + cmd->t_data_sg[0].offset;
 }
@@ -2326,19 +2305,14 @@ int transport_generic_new_cmd(struct se_cmd *cmd)
         * into the fabric for data transfers, go ahead and complete it right
         * away.
         */
-       if (!cmd->data_length) {
+       if (!cmd->data_length &&
+           cmd->t_task_cdb[0] != REQUEST_SENSE &&
+           cmd->se_dev->transport->transport_type != TRANSPORT_PLUGIN_PHBA_PDEV) {
                spin_lock_irq(&cmd->t_state_lock);
                cmd->t_state = TRANSPORT_COMPLETE;
                cmd->transport_state |= CMD_T_ACTIVE;
                spin_unlock_irq(&cmd->t_state_lock);
 
-               if (cmd->t_task_cdb[0] == REQUEST_SENSE) {
-                       u8 ua_asc = 0, ua_ascq = 0;
-
-                       core_scsi3_ua_clear_for_request_sense(cmd,
-                                       &ua_asc, &ua_ascq);
-               }
-
                INIT_WORK(&cmd->work, target_complete_ok_work);
                queue_work(target_completion_wq, &cmd->work);
                return 0;
index fc65ba2c2d5096d3a9b6d9a7905d4b9dab4a8c21..92d11789d6bdfb9393f5f1af7639c811abd79a5a 100644 (file)
 #define  UCR4_OREN      (1<<1)  /* Receiver overrun interrupt enable */
 #define  UCR4_DREN      (1<<0)  /* Recv data ready interrupt enable */
 #define  UFCR_RXTL_SHF   0       /* Receiver trigger level shift */
+#define  UFCR_DCEDTE    (1<<6)  /* DCE/DTE mode select */
 #define  UFCR_RFDIV      (7<<7)  /* Reference freq divider mask */
 #define  UFCR_RFDIV_REG(x)     (((x) < 7 ? 6 - (x) : 6) << 7)
 #define  UFCR_TXTL_SHF   10      /* Transmitter trigger level shift */
@@ -667,22 +668,11 @@ static void imx_break_ctl(struct uart_port *port, int break_state)
 static int imx_setup_ufcr(struct imx_port *sport, unsigned int mode)
 {
        unsigned int val;
-       unsigned int ufcr_rfdiv;
-
-       /* set receiver / transmitter trigger level.
-        * RFDIV is set such way to satisfy requested uartclk value
-        */
-       val = TXTL << 10 | RXTL;
-       ufcr_rfdiv = (clk_get_rate(sport->clk_per) + sport->port.uartclk / 2)
-                       / sport->port.uartclk;
-
-       if(!ufcr_rfdiv)
-               ufcr_rfdiv = 1;
-
-       val |= UFCR_RFDIV_REG(ufcr_rfdiv);
 
+       /* set receiver / transmitter trigger level */
+       val = readl(sport->port.membase + UFCR) & (UFCR_RFDIV | UFCR_DCEDTE);
+       val |= TXTL << UFCR_TXTL_SHF | RXTL;
        writel(val, sport->port.membase + UFCR);
-
        return 0;
 }
 
@@ -754,6 +744,7 @@ static int imx_startup(struct uart_port *port)
                }
        }
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        /*
         * Finally, clear and enable interrupts
         */
@@ -807,7 +798,6 @@ static int imx_startup(struct uart_port *port)
        /*
         * Enable modem status interrupts
         */
-       spin_lock_irqsave(&sport->port.lock,flags);
        imx_enable_ms(&sport->port);
        spin_unlock_irqrestore(&sport->port.lock,flags);
 
@@ -837,10 +827,13 @@ static void imx_shutdown(struct uart_port *port)
 {
        struct imx_port *sport = (struct imx_port *)port;
        unsigned long temp;
+       unsigned long flags;
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR2);
        temp &= ~(UCR2_TXEN);
        writel(temp, sport->port.membase + UCR2);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 
        if (USE_IRDA(sport)) {
                struct imxuart_platform_data *pdata;
@@ -869,12 +862,14 @@ static void imx_shutdown(struct uart_port *port)
         * Disable all interrupts, port and break condition.
         */
 
+       spin_lock_irqsave(&sport->port.lock, flags);
        temp = readl(sport->port.membase + UCR1);
        temp &= ~(UCR1_TXMPTYEN | UCR1_RRDYEN | UCR1_RTSDEN | UCR1_UARTEN);
        if (USE_IRDA(sport))
                temp &= ~(UCR1_IREN);
 
        writel(temp, sport->port.membase + UCR1);
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 static void
@@ -1217,6 +1212,9 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        struct imx_port *sport = imx_ports[co->index];
        struct imx_port_ucrs old_ucr;
        unsigned int ucr1;
+       unsigned long flags;
+
+       spin_lock_irqsave(&sport->port.lock, flags);
 
        /*
         *      First, save UCR1/2/3 and then disable interrupts
@@ -1242,6 +1240,8 @@ imx_console_write(struct console *co, const char *s, unsigned int count)
        while (!(readl(sport->port.membase + USR2) & USR2_TXDC));
 
        imx_port_ucrs_restore(&sport->port, &old_ucr);
+
+       spin_unlock_irqrestore(&sport->port.lock, flags);
 }
 
 /*
index c7a032a4f0c54b4aa975e4dbc3dba9ba43cabfc9..d214448b677e68d1eeff7847fea48bb46942f31f 100644 (file)
@@ -78,8 +78,7 @@ static inline int ep_to_bit(struct ci13xxx *ci, int n)
 }
 
 /**
- * hw_device_state: enables/disables interrupts & starts/stops device (execute
- *                  without interruption)
+ * hw_device_state: enables/disables interrupts (execute without interruption)
  * @dma: 0 => disable, !0 => enable and set dma engine
  *
  * This function returns an error code
@@ -91,9 +90,7 @@ static int hw_device_state(struct ci13xxx *ci, u32 dma)
                /* interrupt, error, port change, reset, sleep/suspend */
                hw_write(ci, OP_USBINTR, ~0,
                             USBi_UI|USBi_UEI|USBi_PCI|USBi_URI|USBi_SLI);
-               hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
        } else {
-               hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
                hw_write(ci, OP_USBINTR, ~0, 0);
        }
        return 0;
@@ -774,10 +771,7 @@ __acquires(mEp->lock)
 {
        struct ci13xxx_req *mReq, *mReqTemp;
        struct ci13xxx_ep *mEpTemp = mEp;
-       int uninitialized_var(retval);
-
-       if (list_empty(&mEp->qh.queue))
-               return -EINVAL;
+       int retval = 0;
 
        list_for_each_entry_safe(mReq, mReqTemp, &mEp->qh.queue,
                        queue) {
@@ -1420,6 +1414,21 @@ static int ci13xxx_vbus_draw(struct usb_gadget *_gadget, unsigned mA)
        return -ENOTSUPP;
 }
 
+/* Change Data+ pullup status
+ * this func is used by usb_gadget_connect/disconnet
+ */
+static int ci13xxx_pullup(struct usb_gadget *_gadget, int is_on)
+{
+       struct ci13xxx *ci = container_of(_gadget, struct ci13xxx, gadget);
+
+       if (is_on)
+               hw_write(ci, OP_USBCMD, USBCMD_RS, USBCMD_RS);
+       else
+               hw_write(ci, OP_USBCMD, USBCMD_RS, 0);
+
+       return 0;
+}
+
 static int ci13xxx_start(struct usb_gadget *gadget,
                         struct usb_gadget_driver *driver);
 static int ci13xxx_stop(struct usb_gadget *gadget,
@@ -1432,6 +1441,7 @@ static int ci13xxx_stop(struct usb_gadget *gadget,
 static const struct usb_gadget_ops usb_gadget_ops = {
        .vbus_session   = ci13xxx_vbus_session,
        .wakeup         = ci13xxx_wakeup,
+       .pullup         = ci13xxx_pullup,
        .vbus_draw      = ci13xxx_vbus_draw,
        .udc_start      = ci13xxx_start,
        .udc_stop       = ci13xxx_stop,
@@ -1455,7 +1465,12 @@ static int init_eps(struct ci13xxx *ci)
 
                        mEp->ep.name      = mEp->name;
                        mEp->ep.ops       = &usb_ep_ops;
-                       mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
+                       /*
+                        * for ep0: maxP defined in desc, for other
+                        * eps, maxP is set by epautoconfig() called
+                        * by gadget layer
+                        */
+                       mEp->ep.maxpacket = (unsigned short)~0;
 
                        INIT_LIST_HEAD(&mEp->qh.queue);
                        mEp->qh.ptr = dma_pool_alloc(ci->qh_pool, GFP_KERNEL,
@@ -1475,6 +1490,7 @@ static int init_eps(struct ci13xxx *ci)
                                else
                                        ci->ep0in = mEp;
 
+                               mEp->ep.maxpacket = CTRL_PAYLOAD_MAX;
                                continue;
                        }
 
@@ -1484,6 +1500,17 @@ static int init_eps(struct ci13xxx *ci)
        return retval;
 }
 
+static void destroy_eps(struct ci13xxx *ci)
+{
+       int i;
+
+       for (i = 0; i < ci->hw_ep_max; i++) {
+               struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
+
+               dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
+       }
+}
+
 /**
  * ci13xxx_start: register a gadget driver
  * @gadget: our gadget
@@ -1691,7 +1718,7 @@ static int udc_start(struct ci13xxx *ci)
        if (ci->platdata->flags & CI13XXX_REQUIRE_TRANSCEIVER) {
                if (ci->transceiver == NULL) {
                        retval = -ENODEV;
-                       goto free_pools;
+                       goto destroy_eps;
                }
        }
 
@@ -1729,7 +1756,7 @@ static int udc_start(struct ci13xxx *ci)
 
 remove_trans:
        if (!IS_ERR_OR_NULL(ci->transceiver)) {
-               otg_set_peripheral(ci->transceiver->otg, &ci->gadget);
+               otg_set_peripheral(ci->transceiver->otg, NULL);
                if (ci->global_phy)
                        usb_put_phy(ci->transceiver);
        }
@@ -1742,6 +1769,8 @@ unreg_device:
 put_transceiver:
        if (!IS_ERR_OR_NULL(ci->transceiver) && ci->global_phy)
                usb_put_phy(ci->transceiver);
+destroy_eps:
+       destroy_eps(ci);
 free_pools:
        dma_pool_destroy(ci->td_pool);
 free_qh_pool:
@@ -1756,18 +1785,12 @@ free_qh_pool:
  */
 static void udc_stop(struct ci13xxx *ci)
 {
-       int i;
-
        if (ci == NULL)
                return;
 
        usb_del_gadget_udc(&ci->gadget);
 
-       for (i = 0; i < ci->hw_ep_max; i++) {
-               struct ci13xxx_ep *mEp = &ci->ci13xxx_ep[i];
-
-               dma_pool_free(ci->qh_pool, mEp->qh.ptr, mEp->qh.dma);
-       }
+       destroy_eps(ci);
 
        dma_pool_destroy(ci->td_pool);
        dma_pool_destroy(ci->qh_pool);
index 65a55abb791f53dd458f0b23c77af5497142ec6d..5f0cb417b736bb4b61c73afc52672029af59cbda 100644 (file)
@@ -109,12 +109,14 @@ static struct usb_driver wdm_driver;
 /* return intfdata if we own the interface, else look up intf in the list */
 static struct wdm_device *wdm_find_device(struct usb_interface *intf)
 {
-       struct wdm_device *desc = NULL;
+       struct wdm_device *desc;
 
        spin_lock(&wdm_device_list_lock);
        list_for_each_entry(desc, &wdm_device_list, device_list)
                if (desc->intf == intf)
-                       break;
+                       goto found;
+       desc = NULL;
+found:
        spin_unlock(&wdm_device_list_lock);
 
        return desc;
@@ -122,12 +124,14 @@ static struct wdm_device *wdm_find_device(struct usb_interface *intf)
 
 static struct wdm_device *wdm_find_device_by_minor(int minor)
 {
-       struct wdm_device *desc = NULL;
+       struct wdm_device *desc;
 
        spin_lock(&wdm_device_list_lock);
        list_for_each_entry(desc, &wdm_device_list, device_list)
                if (desc->intf->minor == minor)
-                       break;
+                       goto found;
+       desc = NULL;
+found:
        spin_unlock(&wdm_device_list_lock);
 
        return desc;
index d9569658476274f34d8a51726da828d87bf44831..3440812b4a849c3d2f372e022f730ade5f5e3e6b 100644 (file)
@@ -624,7 +624,7 @@ static ssize_t usb_device_read(struct file *file, char __user *buf,
        /* print devices for all busses */
        list_for_each_entry(bus, &usb_bus_list, bus_list) {
                /* recurse through all children of the root hub */
-               if (!bus->root_hub)
+               if (!bus_to_hcd(bus)->rh_registered)
                        continue;
                usb_lock_device(bus->root_hub);
                ret = usb_device_dump(&buf, &nbytes, &skip_bytes, ppos,
index bc84106ac057d7affb0e4d7c5c6ce22dcc2b7943..75ba2091f9b4f253a699563e22a9c6fd80c12676 100644 (file)
@@ -1011,10 +1011,7 @@ static int register_root_hub(struct usb_hcd *hcd)
        if (retval) {
                dev_err (parent_dev, "can't register root hub for %s, %d\n",
                                dev_name(&usb_dev->dev), retval);
-       }
-       mutex_unlock(&usb_bus_list_lock);
-
-       if (retval == 0) {
+       } else {
                spin_lock_irq (&hcd_root_hub_lock);
                hcd->rh_registered = 1;
                spin_unlock_irq (&hcd_root_hub_lock);
@@ -1023,6 +1020,7 @@ static int register_root_hub(struct usb_hcd *hcd)
                if (HCD_DEAD(hcd))
                        usb_hc_died (hcd);      /* This time clean up */
        }
+       mutex_unlock(&usb_bus_list_lock);
 
        return retval;
 }
index f15501f4c585694c0c513eac78f692558ae8720f..e77a8e8eaa233b9b4febd38ef8c01ace8ac832a5 100644 (file)
@@ -71,6 +71,10 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x04b4, 0x0526), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
 
+       /* Microchip Joss Optical infrared touchboard device */
+       { USB_DEVICE(0x04d8, 0x000c), .driver_info =
+                       USB_QUIRK_CONFIG_INTF_STRINGS },
+
        /* Samsung Android phone modem - ID conflict with SPH-I500 */
        { USB_DEVICE(0x04e8, 0x6601), .driver_info =
                        USB_QUIRK_CONFIG_INTF_STRINGS },
index c34452a7304f9dec269ba64706ab999559e67eff..a68ff53124dc15e88ab3ceaa35e3fbf7e97cc978 100644 (file)
@@ -436,16 +436,21 @@ static int __devinit dwc3_probe(struct platform_device *pdev)
                dev_err(dev, "missing IRQ\n");
                return -ENODEV;
        }
-       dwc->xhci_resources[1] = *res;
+       dwc->xhci_resources[1].start = res->start;
+       dwc->xhci_resources[1].end = res->end;
+       dwc->xhci_resources[1].flags = res->flags;
+       dwc->xhci_resources[1].name = res->name;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(dev, "missing memory resource\n");
                return -ENODEV;
        }
-       dwc->xhci_resources[0] = *res;
+       dwc->xhci_resources[0].start = res->start;
        dwc->xhci_resources[0].end = dwc->xhci_resources[0].start +
                                        DWC3_XHCI_REGS_END;
+       dwc->xhci_resources[0].flags = res->flags;
+       dwc->xhci_resources[0].name = res->name;
 
         /*
          * Request memory region but exclude xHCI regs,
index 9b94886b66e589ee3040556bf284985a01a64bc6..e4d5ca86b9da5413d1c3c52079b4a2abcd9481ad 100644 (file)
@@ -720,7 +720,6 @@ static void dwc3_ep0_complete_data(struct dwc3 *dwc,
                transferred = min_t(u32, ur->length,
                                transfer_size - length);
                memcpy(ur->buf, dwc->ep0_bounce, transferred);
-               dwc->ep0_bounced = false;
        } else {
                transferred = ur->length - length;
        }
index 58fdfad96b4d61b2cc86de9763a135dc81fcd908..c2813c2b005a8e223f93ff50a3215e24172904c2 100644 (file)
@@ -263,8 +263,11 @@ void dwc3_gadget_giveback(struct dwc3_ep *dep, struct dwc3_request *req,
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
 
-       usb_gadget_unmap_request(&dwc->gadget, &req->request,
-                       req->direction);
+       if (dwc->ep0_bounced && dep->number == 0)
+               dwc->ep0_bounced = false;
+       else
+               usb_gadget_unmap_request(&dwc->gadget, &req->request,
+                               req->direction);
 
        dev_dbg(dwc->dev, "request %p from %s completed %d/%d ===> %d\n",
                        req, dep->name, req->request.actual,
@@ -1026,6 +1029,7 @@ static void __dwc3_gadget_start_isoc(struct dwc3 *dwc,
        if (list_empty(&dep->request_list)) {
                dev_vdbg(dwc->dev, "ISOC ep %s run out for requests.\n",
                        dep->name);
+               dep->flags |= DWC3_EP_PENDING_REQUEST;
                return;
        }
 
@@ -1089,6 +1093,17 @@ static int __dwc3_gadget_ep_queue(struct dwc3_ep *dep, struct dwc3_request *req)
        if (dep->flags & DWC3_EP_PENDING_REQUEST) {
                int     ret;
 
+               /*
+                * If xfernotready is already elapsed and it is a case
+                * of isoc transfer, then issue END TRANSFER, so that
+                * you can receive xfernotready again and can have
+                * notion of current microframe.
+                */
+               if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) {
+                       dwc3_stop_active_transfer(dwc, dep->number);
+                       return 0;
+               }
+
                ret = __dwc3_gadget_kick_transfer(dep, 0, true);
                if (ret && ret != -EBUSY) {
                        struct dwc3     *dwc = dep->dwc;
index c9e66dfb02e6642c1e88149884857948b44869e8..1e35963bd4edc29f735319a76e0a4eb7052b27f5 100644 (file)
@@ -475,8 +475,7 @@ static int at91_ep_enable(struct usb_ep *_ep,
        unsigned long   flags;
 
        if (!_ep || !ep
-                       || !desc || ep->ep.desc
-                       || _ep->name == ep0name
+                       || !desc || _ep->name == ep0name
                        || desc->bDescriptorType != USB_DT_ENDPOINT
                        || (maxpacket = usb_endpoint_maxp(desc)) == 0
                        || maxpacket > ep->maxpacket) {
@@ -530,7 +529,6 @@ ok:
        tmp |= AT91_UDP_EPEDS;
        __raw_writel(tmp, ep->creg);
 
-       ep->ep.desc = desc;
        ep->ep.maxpacket = maxpacket;
 
        /*
@@ -1635,7 +1633,6 @@ static int at91_start(struct usb_gadget *gadget,
        udc->driver = driver;
        udc->gadget.dev.driver = &driver->driver;
        udc->gadget.dev.of_node = udc->pdev->dev.of_node;
-       dev_set_drvdata(&udc->gadget.dev, &driver->driver);
        udc->enabled = 1;
        udc->selfpowered = 1;
 
@@ -1656,7 +1653,6 @@ static int at91_stop(struct usb_gadget *gadget,
        spin_unlock_irqrestore(&udc->lock, flags);
 
        udc->gadget.dev.driver = NULL;
-       dev_set_drvdata(&udc->gadget.dev, NULL);
        udc->driver = NULL;
 
        DBG("unbound from %s\n", driver->driver.name);
index b799106027adfc5d75a45244a47fbd015bedfd20..afdbb1cbf5d94d972c52f57f4099a1bb0202bef5 100644 (file)
@@ -1916,6 +1916,27 @@ done:
        return retval;
 }
 
+/* usb 3.0 root hub device descriptor */
+struct {
+       struct usb_bos_descriptor bos;
+       struct usb_ss_cap_descriptor ss_cap;
+} __packed usb3_bos_desc = {
+
+       .bos = {
+               .bLength                = USB_DT_BOS_SIZE,
+               .bDescriptorType        = USB_DT_BOS,
+               .wTotalLength           = cpu_to_le16(sizeof(usb3_bos_desc)),
+               .bNumDeviceCaps         = 1,
+       },
+       .ss_cap = {
+               .bLength                = USB_DT_USB_SS_CAP_SIZE,
+               .bDescriptorType        = USB_DT_DEVICE_CAPABILITY,
+               .bDevCapabilityType     = USB_SS_CAP_TYPE,
+               .wSpeedSupported        = cpu_to_le16(USB_5GBPS_OPERATION),
+               .bFunctionalitySupport  = ilog2(USB_5GBPS_OPERATION),
+       },
+};
+
 static inline void
 ss_hub_descriptor(struct usb_hub_descriptor *desc)
 {
@@ -2006,6 +2027,18 @@ static int dummy_hub_control(
                else
                        hub_descriptor((struct usb_hub_descriptor *) buf);
                break;
+
+       case DeviceRequest | USB_REQ_GET_DESCRIPTOR:
+               if (hcd->speed != HCD_USB3)
+                       goto error;
+
+               if ((wValue >> 8) != USB_DT_BOS)
+                       goto error;
+
+               memcpy(buf, &usb3_bos_desc, sizeof(usb3_bos_desc));
+               retval = sizeof(usb3_bos_desc);
+               break;
+
        case GetHubStatus:
                *(__le32 *) buf = cpu_to_le32(0);
                break;
@@ -2503,10 +2536,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
        hs_hcd->has_tt = 1;
 
        retval = usb_add_hcd(hs_hcd, 0, 0);
-       if (retval != 0) {
-               usb_put_hcd(hs_hcd);
-               return retval;
-       }
+       if (retval)
+               goto put_usb2_hcd;
 
        if (mod_data.is_super_speed) {
                ss_hcd = usb_create_shared_hcd(&dummy_hcd, &pdev->dev,
@@ -2525,6 +2556,8 @@ static int dummy_hcd_probe(struct platform_device *pdev)
 put_usb3_hcd:
        usb_put_hcd(ss_hcd);
 dealloc_usb2_hcd:
+       usb_remove_hcd(hs_hcd);
+put_usb2_hcd:
        usb_put_hcd(hs_hcd);
        the_controller.hs_hcd = the_controller.ss_hcd = NULL;
        return retval;
index 8adc79d1b40277ac15092a53bac28749627c60cf..829aba75a6dfef28f1ce79055f5b73d6df883c68 100644 (file)
 /* Debugging ****************************************************************/
 
 #ifdef VERBOSE_DEBUG
+#ifndef pr_vdebug
 #  define pr_vdebug pr_debug
+#endif /* pr_vdebug */
 #  define ffs_dump_mem(prefix, ptr, len) \
        print_hex_dump_bytes(pr_fmt(prefix ": "), DUMP_PREFIX_NONE, ptr, len)
 #else
+#ifndef pr_vdebug
 #  define pr_vdebug(...)                 do { } while (0)
+#endif /* pr_vdebug */
 #  define ffs_dump_mem(prefix, ptr, len) do { } while (0)
 #endif /* VERBOSE_DEBUG */
 
index b13e0bb5f5b8131de7cc26a928449215f2e0334c..0bb617e1dda2e0ecf2a440b6494761338f15004c 100644 (file)
@@ -3599,6 +3599,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
 
        if (hsotg->num_of_eps == 0) {
                dev_err(dev, "wrong number of EPs (zero)\n");
+               ret = -EINVAL;
                goto err_supplies;
        }
 
@@ -3606,6 +3607,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
                      GFP_KERNEL);
        if (!eps) {
                dev_err(dev, "cannot get memory\n");
+               ret = -ENOMEM;
                goto err_supplies;
        }
 
@@ -3622,6 +3624,7 @@ static int __devinit s3c_hsotg_probe(struct platform_device *pdev)
                                                     GFP_KERNEL);
        if (!hsotg->ctrl_req) {
                dev_err(dev, "failed to allocate ctrl req\n");
+               ret = -ENOMEM;
                goto err_ep_mem;
        }
 
index 5b3f5fffea92d241b50587b885c24bf69f83e878..da6d479ff9a61e5f57950be3b78e052a029eaa32 100644 (file)
@@ -132,11 +132,15 @@ static unsigned   n_ports;
 
 
 #ifdef VERBOSE_DEBUG
+#ifndef pr_vdebug
 #define pr_vdebug(fmt, arg...) \
        pr_debug(fmt, ##arg)
+#endif /* pr_vdebug */
 #else
+#ifndef pr_vdebig
 #define pr_vdebug(fmt, arg...) \
        ({ if (0) pr_debug(fmt, ##arg); })
+#endif /* pr_vdebug */
 #endif
 
 /*-------------------------------------------------------------------------*/
index 9bc39ca460c80bdfe275b313a47f4683a81e4f3c..4b66374bdc8e33f74e20ff7bc30b7894ab24698e 100644 (file)
@@ -128,9 +128,17 @@ qh_refresh (struct ehci_hcd *ehci, struct ehci_qh *qh)
        else {
                qtd = list_entry (qh->qtd_list.next,
                                struct ehci_qtd, qtd_list);
-               /* first qtd may already be partially processed */
-               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current)
+               /*
+                * first qtd may already be partially processed.
+                * If we come here during unlink, the QH overlay region
+                * might have reference to the just unlinked qtd. The
+                * qtd is updated in qh_completions(). Update the QH
+                * overlay here.
+                */
+               if (cpu_to_hc32(ehci, qtd->qtd_dma) == qh->hw->hw_current) {
+                       qh->hw->hw_qtd_next = qtd->hw_next;
                        qtd = NULL;
+               }
        }
 
        if (qtd)
index a665b3eaa74672f28e7d011b1ea4da265667187f..0bf72f943b00d392654fdc9613e4f397bfac2d32 100644 (file)
@@ -467,7 +467,8 @@ static irqreturn_t ohci_hcd_at91_overcurrent_irq(int irq, void *data)
        /* From the GPIO notifying the over-current situation, find
         * out the corresponding port */
        at91_for_each_port(port) {
-               if (gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
+               if (gpio_is_valid(pdata->overcurrent_pin[port]) &&
+                               gpio_to_irq(pdata->overcurrent_pin[port]) == irq) {
                        gpio = pdata->overcurrent_pin[port];
                        break;
                }
@@ -570,6 +571,16 @@ static int __devinit ohci_hcd_at91_drv_probe(struct platform_device *pdev)
 
        if (pdata) {
                at91_for_each_port(i) {
+                       /*
+                        * do not configure PIO if not in relation with
+                        * real USB port on board
+                        */
+                       if (i >= pdata->ports) {
+                               pdata->vbus_pin[i] = -EINVAL;
+                               pdata->overcurrent_pin[i] = -EINVAL;
+                               break;
+                       }
+
                        if (!gpio_is_valid(pdata->vbus_pin[i]))
                                continue;
                        gpio = pdata->vbus_pin[i];
index c5e9e4a76f148d4eed0c4785cf46fb38d143a074..966d1484ee79a2db8c5e78e135c5e0760814d183 100644 (file)
@@ -75,7 +75,9 @@
 #define        NB_PIF0_PWRDOWN_1       0x01100013
 
 #define USB_INTEL_XUSB2PR      0xD0
+#define USB_INTEL_USB2PRM      0xD4
 #define USB_INTEL_USB3_PSSEN   0xD8
+#define USB_INTEL_USB3PRM      0xDC
 
 static struct amd_chipset_info {
        struct pci_dev  *nb_dev;
@@ -772,10 +774,18 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
                return;
        }
 
-       ports_available = 0xffffffff;
+       /* Read USB3PRM, the USB 3.0 Port Routing Mask Register
+        * Indicate the ports that can be changed from OS.
+        */
+       pci_read_config_dword(xhci_pdev, USB_INTEL_USB3PRM,
+                       &ports_available);
+
+       dev_dbg(&xhci_pdev->dev, "Configurable ports to enable SuperSpeed: 0x%x\n",
+                       ports_available);
+
        /* Write USB3_PSSEN, the USB 3.0 Port SuperSpeed Enable
-        * Register, to turn on SuperSpeed terminations for all
-        * available ports.
+        * Register, to turn on SuperSpeed terminations for the
+        * switchable ports.
         */
        pci_write_config_dword(xhci_pdev, USB_INTEL_USB3_PSSEN,
                        cpu_to_le32(ports_available));
@@ -785,7 +795,16 @@ void usb_enable_xhci_ports(struct pci_dev *xhci_pdev)
        dev_dbg(&xhci_pdev->dev, "USB 3.0 ports that are now enabled "
                        "under xHCI: 0x%x\n", ports_available);
 
-       ports_available = 0xffffffff;
+       /* Read XUSB2PRM, xHCI USB 2.0 Port Routing Mask Register
+        * Indicate the USB 2.0 ports to be controlled by the xHCI host.
+        */
+
+       pci_read_config_dword(xhci_pdev, USB_INTEL_USB2PRM,
+                       &ports_available);
+
+       dev_dbg(&xhci_pdev->dev, "Configurable USB 2.0 ports to hand over to xCHI: 0x%x\n",
+                       ports_available);
+
        /* Write XUSB2PR, the xHC USB 2.0 Port Routing Register, to
         * switch the USB 2.0 power and data lines over to the xHCI
         * host.
@@ -822,12 +841,12 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
        void __iomem *op_reg_base;
        u32 val;
        int timeout;
+       int len = pci_resource_len(pdev, 0);
 
        if (!mmio_resource_enabled(pdev, 0))
                return;
 
-       base = ioremap_nocache(pci_resource_start(pdev, 0),
-                               pci_resource_len(pdev, 0));
+       base = ioremap_nocache(pci_resource_start(pdev, 0), len);
        if (base == NULL)
                return;
 
@@ -837,9 +856,17 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
         */
        ext_cap_offset = xhci_find_next_cap_offset(base, XHCI_HCC_PARAMS_OFFSET);
        do {
+               if ((ext_cap_offset + sizeof(val)) > len) {
+                       /* We're reading garbage from the controller */
+                       dev_warn(&pdev->dev,
+                                "xHCI controller failing to respond");
+                       return;
+               }
+
                if (!ext_cap_offset)
                        /* We've reached the end of the extended capabilities */
                        goto hc_init;
+
                val = readl(base + ext_cap_offset);
                if (XHCI_EXT_CAPS_ID(val) == XHCI_EXT_CAPS_LEGACY)
                        break;
@@ -870,9 +897,10 @@ static void __devinit quirk_usb_handoff_xhci(struct pci_dev *pdev)
        /* Disable any BIOS SMIs and clear all SMI events*/
        writel(val, base + ext_cap_offset + XHCI_LEGACY_CONTROL_OFFSET);
 
+hc_init:
        if (usb_is_intel_switchable_xhci(pdev))
                usb_enable_xhci_ports(pdev);
-hc_init:
+
        op_reg_base = base + XHCI_HC_LENGTH(readl(base));
 
        /* Wait for the host controller to be ready before writing any
index ef004a5de20f176c27801f83bd9ae2456570e6b1..7f69a39163ce3b5560f9e0e24a0a9d86e7f77cef 100644 (file)
@@ -15,6 +15,7 @@ void usb_disable_xhci_ports(struct pci_dev *xhci_pdev);
 static inline void usb_amd_quirk_pll_disable(void) {}
 static inline void usb_amd_quirk_pll_enable(void) {}
 static inline void usb_amd_dev_put(void) {}
+static inline void usb_disable_xhci_ports(struct pci_dev *xhci_pdev) {}
 #endif  /* CONFIG_PCI */
 
 #endif  /*  __LINUX_USB_PCI_QUIRKS_H  */
index 74bfc868b7ade609dc67cea66195bd499f92b067..d5eb357aa5c42cff5575bdf1297f3ebbafa49d85 100644 (file)
@@ -493,11 +493,48 @@ static void xhci_hub_report_link_state(u32 *status, u32 status_reg)
                 * when this bit is set.
                 */
                pls |= USB_PORT_STAT_CONNECTION;
+       } else {
+               /*
+                * If CAS bit isn't set but the Port is already at
+                * Compliance Mode, fake a connection so the USB core
+                * notices the Compliance state and resets the port.
+                * This resolves an issue generated by the SN65LVPE502CP
+                * in which sometimes the port enters compliance mode
+                * caused by a delay on the host-device negotiation.
+                */
+               if (pls == USB_SS_PORT_LS_COMP_MOD)
+                       pls |= USB_PORT_STAT_CONNECTION;
        }
+
        /* update status field */
        *status |= pls;
 }
 
+/*
+ * Function for Compliance Mode Quirk.
+ *
+ * This Function verifies if all xhc USB3 ports have entered U0, if so,
+ * the compliance mode timer is deleted. A port won't enter
+ * compliance mode if it has previously entered U0.
+ */
+void xhci_del_comp_mod_timer(struct xhci_hcd *xhci, u32 status, u16 wIndex)
+{
+       u32 all_ports_seen_u0 = ((1 << xhci->num_usb3_ports)-1);
+       bool port_in_u0 = ((status & PORT_PLS_MASK) == XDEV_U0);
+
+       if (!(xhci->quirks & XHCI_COMP_MODE_QUIRK))
+               return;
+
+       if ((xhci->port_status_u0 != all_ports_seen_u0) && port_in_u0) {
+               xhci->port_status_u0 |= 1 << wIndex;
+               if (xhci->port_status_u0 == all_ports_seen_u0) {
+                       del_timer_sync(&xhci->comp_mode_recovery_timer);
+                       xhci_dbg(xhci, "All USB3 ports have entered U0 already!\n");
+                       xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted.\n");
+               }
+       }
+}
+
 int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                u16 wIndex, char *buf, u16 wLength)
 {
@@ -651,6 +688,11 @@ int xhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue,
                /* Update Port Link State for super speed ports*/
                if (hcd->speed == HCD_USB3) {
                        xhci_hub_report_link_state(&status, temp);
+                       /*
+                        * Verify if all USB3 Ports Have entered U0 already.
+                        * Delete Compliance Mode Timer if so.
+                        */
+                       xhci_del_comp_mod_timer(xhci, temp, wIndex);
                }
                if (bus_state->port_c_suspend & (1 << wIndex))
                        status |= 1 << USB_PORT_FEAT_C_SUSPEND;
index 689bc18b051d6c1d1ae8e381e887a01edbdfc9e9..df90fe51b4aa2d406b8b2f8bfa591c410df89a35 100644 (file)
@@ -118,7 +118,7 @@ static int xhci_plat_probe(struct platform_device *pdev)
                goto put_hcd;
        }
 
-       hcd->regs = ioremap(hcd->rsrc_start, hcd->rsrc_len);
+       hcd->regs = ioremap_nocache(hcd->rsrc_start, hcd->rsrc_len);
        if (!hcd->regs) {
                dev_dbg(&pdev->dev, "error mapping memory\n");
                ret = -EFAULT;
index c59d5b5b6c7d227a8005ca520e8b9badad5207b1..6ece0ed288d4da9398bb96ecc8223f31b6ce8e0c 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/module.h>
 #include <linux/moduleparam.h>
 #include <linux/slab.h>
+#include <linux/dmi.h>
 
 #include "xhci.h"
 
@@ -398,6 +399,95 @@ static void xhci_msix_sync_irqs(struct xhci_hcd *xhci)
 
 #endif
 
+static void compliance_mode_recovery(unsigned long arg)
+{
+       struct xhci_hcd *xhci;
+       struct usb_hcd *hcd;
+       u32 temp;
+       int i;
+
+       xhci = (struct xhci_hcd *)arg;
+
+       for (i = 0; i < xhci->num_usb3_ports; i++) {
+               temp = xhci_readl(xhci, xhci->usb3_ports[i]);
+               if ((temp & PORT_PLS_MASK) == USB_SS_PORT_LS_COMP_MOD) {
+                       /*
+                        * Compliance Mode Detected. Letting USB Core
+                        * handle the Warm Reset
+                        */
+                       xhci_dbg(xhci, "Compliance Mode Detected->Port %d!\n",
+                                       i + 1);
+                       xhci_dbg(xhci, "Attempting Recovery routine!\n");
+                       hcd = xhci->shared_hcd;
+
+                       if (hcd->state == HC_STATE_SUSPENDED)
+                               usb_hcd_resume_root_hub(hcd);
+
+                       usb_hcd_poll_rh_status(hcd);
+               }
+       }
+
+       if (xhci->port_status_u0 != ((1 << xhci->num_usb3_ports)-1))
+               mod_timer(&xhci->comp_mode_recovery_timer,
+                       jiffies + msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
+}
+
+/*
+ * Quirk to work around issue generated by the SN65LVPE502CP USB3.0 re-driver
+ * that causes ports behind that hardware to enter compliance mode sometimes.
+ * The quirk creates a timer that polls every 2 seconds the link state of
+ * each host controller's port and recovers it by issuing a Warm reset
+ * if Compliance mode is detected, otherwise the port will become "dead" (no
+ * device connections or disconnections will be detected anymore). Becasue no
+ * status event is generated when entering compliance mode (per xhci spec),
+ * this quirk is needed on systems that have the failing hardware installed.
+ */
+static void compliance_mode_recovery_timer_init(struct xhci_hcd *xhci)
+{
+       xhci->port_status_u0 = 0;
+       init_timer(&xhci->comp_mode_recovery_timer);
+
+       xhci->comp_mode_recovery_timer.data = (unsigned long) xhci;
+       xhci->comp_mode_recovery_timer.function = compliance_mode_recovery;
+       xhci->comp_mode_recovery_timer.expires = jiffies +
+                       msecs_to_jiffies(COMP_MODE_RCVRY_MSECS);
+
+       set_timer_slack(&xhci->comp_mode_recovery_timer,
+                       msecs_to_jiffies(COMP_MODE_RCVRY_MSECS));
+       add_timer(&xhci->comp_mode_recovery_timer);
+       xhci_dbg(xhci, "Compliance Mode Recovery Timer Initialized.\n");
+}
+
+/*
+ * This function identifies the systems that have installed the SN65LVPE502CP
+ * USB3.0 re-driver and that need the Compliance Mode Quirk.
+ * Systems:
+ * Vendor: Hewlett-Packard -> System Models: Z420, Z620 and Z820
+ */
+static bool compliance_mode_recovery_timer_quirk_check(void)
+{
+       const char *dmi_product_name, *dmi_sys_vendor;
+
+       dmi_product_name = dmi_get_system_info(DMI_PRODUCT_NAME);
+       dmi_sys_vendor = dmi_get_system_info(DMI_SYS_VENDOR);
+
+       if (!(strstr(dmi_sys_vendor, "Hewlett-Packard")))
+               return false;
+
+       if (strstr(dmi_product_name, "Z420") ||
+                       strstr(dmi_product_name, "Z620") ||
+                       strstr(dmi_product_name, "Z820"))
+               return true;
+
+       return false;
+}
+
+static int xhci_all_ports_seen_u0(struct xhci_hcd *xhci)
+{
+       return (xhci->port_status_u0 == ((1 << xhci->num_usb3_ports)-1));
+}
+
+
 /*
  * Initialize memory for HCD and xHC (one-time init).
  *
@@ -421,6 +511,12 @@ int xhci_init(struct usb_hcd *hcd)
        retval = xhci_mem_init(xhci, GFP_KERNEL);
        xhci_dbg(xhci, "Finished xhci_init\n");
 
+       /* Initializing Compliance Mode Recovery Data If Needed */
+       if (compliance_mode_recovery_timer_quirk_check()) {
+               xhci->quirks |= XHCI_COMP_MODE_QUIRK;
+               compliance_mode_recovery_timer_init(xhci);
+       }
+
        return retval;
 }
 
@@ -629,6 +725,11 @@ void xhci_stop(struct usb_hcd *hcd)
        del_timer_sync(&xhci->event_ring_timer);
 #endif
 
+       /* Deleting Compliance Mode Recovery Timer */
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                       (!(xhci_all_ports_seen_u0(xhci))))
+               del_timer_sync(&xhci->comp_mode_recovery_timer);
+
        if (xhci->quirks & XHCI_AMD_PLL_FIX)
                usb_amd_dev_put();
 
@@ -659,7 +760,7 @@ void xhci_shutdown(struct usb_hcd *hcd)
 {
        struct xhci_hcd *xhci = hcd_to_xhci(hcd);
 
-       if (xhci->quirks && XHCI_SPURIOUS_REBOOT)
+       if (xhci->quirks & XHCI_SPURIOUS_REBOOT)
                usb_disable_xhci_ports(to_pci_dev(hcd->self.controller));
 
        spin_lock_irq(&xhci->lock);
@@ -806,6 +907,16 @@ int xhci_suspend(struct xhci_hcd *xhci)
        }
        spin_unlock_irq(&xhci->lock);
 
+       /*
+        * Deleting Compliance Mode Recovery Timer because the xHCI Host
+        * is about to be suspended.
+        */
+       if ((xhci->quirks & XHCI_COMP_MODE_QUIRK) &&
+                       (!(xhci_all_ports_seen_u0(xhci)))) {
+               del_timer_sync(&xhci->comp_mode_recovery_timer);
+               xhci_dbg(xhci, "Compliance Mode Recovery Timer Deleted!\n");
+       }
+
        /* step 5: remove core well power */
        /* synchronize irq when using MSI-X */
        xhci_msix_sync_irqs(xhci);
@@ -938,6 +1049,16 @@ int xhci_resume(struct xhci_hcd *xhci, bool hibernated)
                usb_hcd_resume_root_hub(hcd);
                usb_hcd_resume_root_hub(xhci->shared_hcd);
        }
+
+       /*
+        * If system is subject to the Quirk, Compliance Mode Timer needs to
+        * be re-initialized Always after a system resume. Ports are subject
+        * to suffer the Compliance Mode issue again. It doesn't matter if
+        * ports have entered previously to U0 before system's suspension.
+        */
+       if (xhci->quirks & XHCI_COMP_MODE_QUIRK)
+               compliance_mode_recovery_timer_init(xhci);
+
        return retval;
 }
 #endif /* CONFIG_PM */
index c713256297acd073e7589f2fdfd936390fb8bbd0..1a05908c66737ce94a77f880d1bc14cb7e40134a 100644 (file)
@@ -1495,6 +1495,7 @@ struct xhci_hcd {
 #define XHCI_LPM_SUPPORT       (1 << 11)
 #define XHCI_INTEL_HOST                (1 << 12)
 #define XHCI_SPURIOUS_REBOOT   (1 << 13)
+#define XHCI_COMP_MODE_QUIRK   (1 << 14)
        unsigned int            num_active_eps;
        unsigned int            limit_active_eps;
        /* There are two roothubs to keep track of bus suspend info for */
@@ -1511,6 +1512,11 @@ struct xhci_hcd {
        unsigned                sw_lpm_support:1;
        /* support xHCI 1.0 spec USB2 hardware LPM */
        unsigned                hw_lpm_support:1;
+       /* Compliance Mode Recovery Data */
+       struct timer_list       comp_mode_recovery_timer;
+       u32                     port_status_u0;
+/* Compliance Mode Timer Triggered every 2 seconds */
+#define COMP_MODE_RCVRY_MSECS 2000
 };
 
 /* convert between an HCD pointer and the corresponding EHCI_HCD */
index 4bb717d0bd41b12a8b0f6fd879c987286a8059b5..1ae378d5fc6f25b5861eb2e3ef79b32a76a4885f 100644 (file)
@@ -2049,7 +2049,7 @@ static int musb_urb_enqueue(
         * we only have work to do in the former case.
         */
        spin_lock_irqsave(&musb->lock, flags);
-       if (hep->hcpriv) {
+       if (hep->hcpriv || !next_urb(qh)) {
                /* some concurrent activity submitted another urb to hep...
                 * odd, rare, error prone, but legal.
                 */
index 57a608584e160248708aca39570a7e30bf55d7a5..c1be687e00ec722524f8807ff8d628ec7a5d0798 100644 (file)
@@ -388,7 +388,7 @@ dma_controller_create(struct musb *musb, void __iomem *base)
        struct platform_device *pdev = to_platform_device(dev);
        int irq = platform_get_irq_byname(pdev, "dma");
 
-       if (irq == 0) {
+       if (irq <= 0) {
                dev_err(dev, "No DMA interrupt line!\n");
                return NULL;
        }
index 1a1bd9cf40c5ce7c1d6f7ef1ac46360d0b6884a4..341625442377ec6f1daac69450269c95f4148eb5 100644 (file)
@@ -1215,7 +1215,7 @@ static int __devinit tusb_probe(struct platform_device *pdev)
        ret = platform_device_add(musb);
        if (ret) {
                dev_err(&pdev->dev, "failed to register musb device\n");
-               goto err1;
+               goto err2;
        }
 
        return 0;
index ecd173032fd480cc5954c48f03aa61e7b5c439e8..143c4e9e1be45cc24c0a612d38e590a5ad136be9 100644 (file)
@@ -818,7 +818,7 @@ static int usbhsf_dma_prepare_push(struct usbhs_pkt *pkt, int *is_done)
            usbhs_pipe_is_dcp(pipe))
                goto usbhsf_pio_prepare_push;
 
-       if (len % 4) /* 32bit alignment */
+       if (len & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_push;
 
        if ((uintptr_t)(pkt->buf + pkt->actual) & 0x7) /* 8byte alignment */
@@ -905,7 +905,7 @@ static int usbhsf_dma_try_pop(struct usbhs_pkt *pkt, int *is_done)
        /* use PIO if packet is less than pio_dma_border */
        len = usbhsf_fifo_rcv_len(priv, fifo);
        len = min(pkt->length - pkt->actual, len);
-       if (len % 4) /* 32bit alignment */
+       if (len & 0x7) /* 8byte alignment */
                goto usbhsf_pio_prepare_pop_unselect;
 
        if (len < usbhs_get_dparam(priv, pio_dma_border))
index 5620db6469e586f85ea8eacfa79798b1b4a676d8..f906b3aec2179ceb708c9cce772cd85a4e1a1724 100644 (file)
@@ -704,6 +704,7 @@ static struct usb_device_id id_table_combined [] = {
        { USB_DEVICE(FTDI_VID, FTDI_PCDJ_DAC2_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_RRCIRKITS_LOCOBUFFER_PID) },
        { USB_DEVICE(FTDI_VID, FTDI_ASK_RDR400_PID) },
+       { USB_DEVICE(FTDI_VID, FTDI_NZR_SEM_USB_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_ID_1_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_OPC_U_UC_PID) },
        { USB_DEVICE(ICOM_VID, ICOM_ID_RP2C1_PID) },
@@ -804,13 +805,32 @@ static struct usb_device_id id_table_combined [] = {
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(ADI_VID, ADI_GNICEPLUS_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
-       { USB_DEVICE(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID) },
+       { USB_DEVICE_AND_INTERFACE_INFO(MICROCHIP_VID, MICROCHIP_USB_BOARD_PID,
+                                       USB_CLASS_VENDOR_SPEC,
+                                       USB_SUBCLASS_VENDOR_SPEC, 0x00) },
        { USB_DEVICE(JETI_VID, JETI_SPC1201_PID) },
        { USB_DEVICE(MARVELL_VID, MARVELL_SHEEVAPLUG_PID),
                .driver_info = (kernel_ulong_t)&ftdi_jtag_quirk },
        { USB_DEVICE(LARSENBRUSGAARD_VID, LB_ALTITRACK_PID) },
        { USB_DEVICE(GN_OTOMETRICS_VID, AURICAL_USB_PID) },
+       { USB_DEVICE(FTDI_VID, PI_C865_PID) },
+       { USB_DEVICE(FTDI_VID, PI_C857_PID) },
+       { USB_DEVICE(PI_VID, PI_C866_PID) },
+       { USB_DEVICE(PI_VID, PI_C663_PID) },
+       { USB_DEVICE(PI_VID, PI_C725_PID) },
+       { USB_DEVICE(PI_VID, PI_E517_PID) },
+       { USB_DEVICE(PI_VID, PI_C863_PID) },
        { USB_DEVICE(PI_VID, PI_E861_PID) },
+       { USB_DEVICE(PI_VID, PI_C867_PID) },
+       { USB_DEVICE(PI_VID, PI_E609_PID) },
+       { USB_DEVICE(PI_VID, PI_E709_PID) },
+       { USB_DEVICE(PI_VID, PI_100F_PID) },
+       { USB_DEVICE(PI_VID, PI_1011_PID) },
+       { USB_DEVICE(PI_VID, PI_1012_PID) },
+       { USB_DEVICE(PI_VID, PI_1013_PID) },
+       { USB_DEVICE(PI_VID, PI_1014_PID) },
+       { USB_DEVICE(PI_VID, PI_1015_PID) },
+       { USB_DEVICE(PI_VID, PI_1016_PID) },
        { USB_DEVICE(KONDO_VID, KONDO_USB_SERIAL_PID) },
        { USB_DEVICE(BAYER_VID, BAYER_CONTOUR_CABLE_PID) },
        { USB_DEVICE(FTDI_VID, MARVELL_OPENRD_PID),
index 5dd96ca6c380a0971921d198e12399e1902663db..41fe5826100c0ad27a62d21d16e8d5845dfa25cc 100644 (file)
@@ -75,6 +75,9 @@
 #define FTDI_OPENDCC_GATEWAY_PID       0xBFDB
 #define FTDI_OPENDCC_GBM_PID   0xBFDC
 
+/* NZR SEM 16+ USB (http://www.nzr.de) */
+#define FTDI_NZR_SEM_USB_PID   0xC1E0  /* NZR SEM-LOG16+ */
+
 /*
  * RR-CirKits LocoBuffer USB (http://www.rr-cirkits.com)
  */
 /*
  * Microchip Technology, Inc.
  *
- * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are also used by:
+ * MICROCHIP_VID (0x04D8) and MICROCHIP_USB_BOARD_PID (0x000A) are
+ * used by single function CDC ACM class based firmware demo
+ * applications.  The VID/PID has also been used in firmware
+ * emulating FTDI serial chips by:
  * Hornby Elite - Digital Command Control Console
  * http://www.hornby.com/hornby-dcc/controllers/
  */
  * Physik Instrumente
  * http://www.physikinstrumente.com/en/products/
  */
+/* These two devices use the VID of FTDI */
+#define PI_C865_PID    0xe0a0  /* PI C-865 Piezomotor Controller */
+#define PI_C857_PID    0xe0a1  /* PI Encoder Trigger Box */
+
 #define PI_VID              0x1a72  /* Vendor ID */
-#define PI_E861_PID         0x1008  /* E-861 piezo controller USB connection */
+#define PI_C866_PID    0x1000  /* PI C-866 Piezomotor Controller */
+#define PI_C663_PID    0x1001  /* PI C-663 Mercury-Step */
+#define PI_C725_PID    0x1002  /* PI C-725 Piezomotor Controller */
+#define PI_E517_PID    0x1005  /* PI E-517 Digital Piezo Controller Operation Module */
+#define PI_C863_PID    0x1007  /* PI C-863 */
+#define PI_E861_PID    0x1008  /* PI E-861 Piezomotor Controller */
+#define PI_C867_PID    0x1009  /* PI C-867 Piezomotor Controller */
+#define PI_E609_PID    0x100D  /* PI E-609 Digital Piezo Controller */
+#define PI_E709_PID    0x100E  /* PI E-709 Digital Piezo Controller */
+#define PI_100F_PID    0x100F  /* PI Digital Piezo Controller */
+#define PI_1011_PID    0x1011  /* PI Digital Piezo Controller */
+#define PI_1012_PID    0x1012  /* PI Motion Controller */
+#define PI_1013_PID    0x1013  /* PI Motion Controller */
+#define PI_1014_PID    0x1014  /* PI Device */
+#define PI_1015_PID    0x1015  /* PI Device */
+#define PI_1016_PID    0x1016  /* PI Digital Servo Module */
 
 /*
  * Kondo Kagaku Co.Ltd.
index cc40f47ecea13ff2041389d5aa7d5526159e58d8..5ce88d1bc6f1e3ac15ac91290ad8cb2fd5935361 100644 (file)
@@ -886,8 +886,6 @@ static const struct usb_device_id option_ids[] = {
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1010, 0xff, 0xff, 0xff),
          .driver_info = (kernel_ulong_t)&net_intf4_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1012, 0xff, 0xff, 0xff) },
-       { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1018, 0xff, 0xff, 0xff),
-         .driver_info = (kernel_ulong_t)&net_intf3_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1057, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1058, 0xff, 0xff, 0xff) },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0x1059, 0xff, 0xff, 0xff) },
@@ -1092,6 +1090,10 @@ static const struct usb_device_id option_ids[] = {
         .driver_info = (kernel_ulong_t)&zte_ad3812_z_blacklist },
        { USB_DEVICE_AND_INTERFACE_INFO(ZTE_VENDOR_ID, ZTE_PRODUCT_MC2716, 0xff, 0xff, 0xff),
         .driver_info = (kernel_ulong_t)&zte_mc2716_z_blacklist },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x01) },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x02, 0x05) },
+       { USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, 0xff, 0x86, 0x10) },
+
        { USB_DEVICE(BENQ_VENDOR_ID, BENQ_PRODUCT_H10) },
        { USB_DEVICE(DLINK_VENDOR_ID, DLINK_PRODUCT_DWM_652) },
        { USB_DEVICE(ALINK_VENDOR_ID, DLINK_PRODUCT_DWM_652_U5) }, /* Yes, ALINK_VENDOR_ID */
index 211a4920b88a577216ed9905db510c691cdb4d84..d8dedc7d3910c7bdc362dac6e099326642f0f1fb 100644 (file)
@@ -76,9 +76,24 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void *key)
                        schedule_work(&virqfd->inject);
        }
 
-       if (flags & POLLHUP)
-               /* The eventfd is closing, detach from VFIO */
-               virqfd_deactivate(virqfd);
+       if (flags & POLLHUP) {
+               unsigned long flags;
+               spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+
+               /*
+                * The eventfd is closing, if the virqfd has not yet been
+                * queued for release, as determined by testing whether the
+                * vdev pointer to it is still valid, queue it now.  As
+                * with kvm irqfds, we know we won't race against the virqfd
+                * going away because we hold wqh->lock to get here.
+                */
+               if (*(virqfd->pvirqfd) == virqfd) {
+                       *(virqfd->pvirqfd) = NULL;
+                       virqfd_deactivate(virqfd);
+               }
+
+               spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+       }
 
        return 0;
 }
@@ -93,7 +108,6 @@ static void virqfd_ptable_queue_proc(struct file *file,
 static void virqfd_shutdown(struct work_struct *work)
 {
        struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-       struct virqfd **pvirqfd = virqfd->pvirqfd;
        u64 cnt;
 
        eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
@@ -101,7 +115,6 @@ static void virqfd_shutdown(struct work_struct *work)
        eventfd_ctx_put(virqfd->eventfd);
 
        kfree(virqfd);
-       *pvirqfd = NULL;
 }
 
 static void virqfd_inject(struct work_struct *work)
@@ -122,15 +135,11 @@ static int virqfd_enable(struct vfio_pci_device *vdev,
        int ret = 0;
        unsigned int events;
 
-       if (*pvirqfd)
-               return -EBUSY;
-
        virqfd = kzalloc(sizeof(*virqfd), GFP_KERNEL);
        if (!virqfd)
                return -ENOMEM;
 
        virqfd->pvirqfd = pvirqfd;
-       *pvirqfd = virqfd;
        virqfd->vdev = vdev;
        virqfd->handler = handler;
        virqfd->thread = thread;
@@ -153,6 +162,23 @@ static int virqfd_enable(struct vfio_pci_device *vdev,
 
        virqfd->eventfd = ctx;
 
+       /*
+        * virqfds can be released by closing the eventfd or directly
+        * through ioctl.  These are both done through a workqueue, so
+        * we update the pointer to the virqfd under lock to avoid
+        * pushing multiple jobs to release the same virqfd.
+        */
+       spin_lock_irq(&vdev->irqlock);
+
+       if (*pvirqfd) {
+               spin_unlock_irq(&vdev->irqlock);
+               ret = -EBUSY;
+               goto fail;
+       }
+       *pvirqfd = virqfd;
+
+       spin_unlock_irq(&vdev->irqlock);
+
        /*
         * Install our own custom wake-up handling so we are notified via
         * a callback whenever someone signals the underlying eventfd.
@@ -187,19 +213,29 @@ fail:
                fput(file);
 
        kfree(virqfd);
-       *pvirqfd = NULL;
 
        return ret;
 }
 
-static void virqfd_disable(struct virqfd *virqfd)
+static void virqfd_disable(struct vfio_pci_device *vdev,
+                          struct virqfd **pvirqfd)
 {
-       if (!virqfd)
-               return;
+       unsigned long flags;
+
+       spin_lock_irqsave(&vdev->irqlock, flags);
+
+       if (*pvirqfd) {
+               virqfd_deactivate(*pvirqfd);
+               *pvirqfd = NULL;
+       }
 
-       virqfd_deactivate(virqfd);
+       spin_unlock_irqrestore(&vdev->irqlock, flags);
 
-       /* Block until we know all outstanding shutdown jobs have completed. */
+       /*
+        * Block until we know all outstanding shutdown jobs have completed.
+        * Even if we don't queue the job, flush the wq to be sure it's
+        * been released.
+        */
        flush_workqueue(vfio_irqfd_cleanup_wq);
 }
 
@@ -392,8 +428,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device *vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
        vfio_intx_set_signal(vdev, -1);
-       virqfd_disable(vdev->ctx[0].unmask);
-       virqfd_disable(vdev->ctx[0].mask);
+       virqfd_disable(vdev, &vdev->ctx[0].unmask);
+       virqfd_disable(vdev, &vdev->ctx[0].mask);
        vdev->irq_type = VFIO_PCI_NUM_IRQS;
        vdev->num_ctx = 0;
        kfree(vdev->ctx);
@@ -539,8 +575,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, bool msix)
        vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
        for (i = 0; i < vdev->num_ctx; i++) {
-               virqfd_disable(vdev->ctx[i].unmask);
-               virqfd_disable(vdev->ctx[i].mask);
+               virqfd_disable(vdev, &vdev->ctx[i].unmask);
+               virqfd_disable(vdev, &vdev->ctx[i].mask);
        }
 
        if (msix) {
@@ -577,7 +613,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device *vdev,
                                             vfio_send_intx_eventfd, NULL,
                                             &vdev->ctx[0].unmask, fd);
 
-               virqfd_disable(vdev->ctx[0].unmask);
+               virqfd_disable(vdev, &vdev->ctx[0].unmask);
        }
 
        return 0;
index 77da6a2f43dc986a5b6eb17d065b9f53b80dce69..c03ecdd31e4c6133f31a54c143038682c694dc87 100644 (file)
@@ -987,7 +987,6 @@ err_regfb:
        fb_dealloc_cmap(&info->cmap);
 err_cmap:
        fb_deferred_io_cleanup(info);
-       kfree(info->fbdefio);
 err_defio:
        vfree((void *)info->screen_base);
 err_irq:
@@ -1022,7 +1021,6 @@ int  __devexit auok190x_common_remove(struct platform_device *pdev)
        fb_dealloc_cmap(&info->cmap);
 
        fb_deferred_io_cleanup(info);
-       kfree(info->fbdefio);
 
        vfree((void *)info->screen_base);
 
index 28b1a834906b1f59d31c49421e771aa5e6f8aae7..61b182bf32a22962492cc79a3b1e60f3f49ef388 100644 (file)
@@ -162,7 +162,7 @@ static void bit_putcs(struct vc_data *vc, struct fb_info *info,
        image.depth = 1;
 
        if (attribute) {
-               buf = kmalloc(cellsize, GFP_KERNEL);
+               buf = kmalloc(cellsize, GFP_ATOMIC);
                if (!buf)
                        return;
        }
index 88e92041d8f02d6136458535c61c3090c304e576..fdefa8fd72c4da070787d95260b2744d6a9a7dab 100644 (file)
@@ -449,7 +449,7 @@ static int __init fb_console_setup(char *this_opt)
 
        while ((options = strsep(&this_opt, ",")) != NULL) {
                if (!strncmp(options, "font:", 5))
-                       strcpy(fontname, options + 5);
+                       strlcpy(fontname, options + 5, sizeof(fontname));
                
                if (!strncmp(options, "scrollback:", 11)) {
                        options += 11;
index 00ce1f34b4965aa1d20f9bc33c709046551f2eca..57d940be5f3d7eaa25b2358c83e169947a779bdf 100644 (file)
@@ -328,6 +328,8 @@ static int mb862xxfb_ioctl(struct fb_info *fbi, unsigned int cmd,
        case MB862XX_L1_SET_CFG:
                if (copy_from_user(l1_cfg, argp, sizeof(*l1_cfg)))
                        return -EFAULT;
+               if (l1_cfg->dh == 0 || l1_cfg->dw == 0)
+                       return -EINVAL;
                if ((l1_cfg->sw >= l1_cfg->dw) && (l1_cfg->sh >= l1_cfg->dh)) {
                        /* downscaling */
                        outreg(cap, GC_CAP_CSC,
index 5d31699fbd3caf4c885840b77c76fd4512d52ed9..f43bfe17b3b699289152cb9ff195afcb69f137f2 100644 (file)
@@ -105,6 +105,20 @@ int omapdss_sdi_display_enable(struct omap_dss_device *dssdev)
 
        sdi_config_lcd_manager(dssdev);
 
+       /*
+        * LCLK and PCLK divisors are located in shadow registers, and we
+        * normally write them to DISPC registers when enabling the output.
+        * However, SDI uses pck-free as source clock for its PLL, and pck-free
+        * is affected by the divisors. And as we need the PLL before enabling
+        * the output, we need to write the divisors early.
+        *
+        * It seems just writing to the DISPC register is enough, and we don't
+        * need to care about the shadow register mechanism for pck-free. The
+        * exact reason for this is unknown.
+        */
+       dispc_mgr_set_clock_div(dssdev->manager->id,
+                       &sdi.mgr_config.clock_info);
+
        dss_sdi_init(dssdev->phy.sdi.datapairs);
        r = dss_sdi_enable();
        if (r)
index 08ec1a7103f2b728420f9e534a2002b20f457d45..fc671d3d8004899ba36064954fc1343ddefb85e2 100644 (file)
@@ -1192,7 +1192,7 @@ static int _setcolreg(struct fb_info *fbi, u_int regno, u_int red, u_int green,
                        break;
 
                if (regno < 16) {
-                       u16 pal;
+                       u32 pal;
                        pal = ((red >> (16 - var->red.length)) <<
                                        var->red.offset) |
                                ((green >> (16 - var->green.length)) <<
index 3fe82d0e8caae583a2bdd8ac41a30bec5540fa43..5b06d31ab6a98678320b8c88456f0d3abde2cb35 100644 (file)
@@ -166,18 +166,17 @@ static long booke_wdt_ioctl(struct file *file,
 
        switch (cmd) {
        case WDIOC_GETSUPPORT:
-               if (copy_to_user((void *)arg, &ident, sizeof(ident)))
-                       return -EFAULT;
+               return copy_to_user(p, &ident, sizeof(ident)) ? -EFAULT : 0;
        case WDIOC_GETSTATUS:
                return put_user(0, p);
        case WDIOC_GETBOOTSTATUS:
                /* XXX: something is clearing TSR */
                tmp = mfspr(SPRN_TSR) & TSR_WRS(3);
                /* returns CARDRESET if last reset was caused by the WDT */
-               return (tmp ? WDIOF_CARDRESET : 0);
+               return put_user((tmp ? WDIOF_CARDRESET : 0), p);
        case WDIOC_SETOPTIONS:
                if (get_user(tmp, p))
-                       return -EINVAL;
+                       return -EFAULT;
                if (tmp == WDIOS_ENABLECARD) {
                        booke_wdt_ping();
                        break;
index 3f75129eb0a9f06cd0a7d194a3c390f5ee9bfd3f..f7abbaeebcaf51466efbc493c2fb433b01408bf3 100644 (file)
@@ -21,7 +21,6 @@
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/jiffies.h>
-#include <linux/delay.h>
 
 #include <linux/mfd/da9052/reg.h>
 #include <linux/mfd/da9052/da9052.h>
index 1eff743ec4970071f8451704fb51d4b06de70950..ae60406ea8a1878cefd03d29868eda31b955578f 100644 (file)
@@ -814,6 +814,9 @@ static int __devinit hpwdt_init_one(struct pci_dev *dev,
        hpwdt_timer_reg = pci_mem_addr + 0x70;
        hpwdt_timer_con = pci_mem_addr + 0x72;
 
+       /* Make sure that timer is disabled until /dev/watchdog is opened */
+       hpwdt_stop();
+
        /* Make sure that we have a valid soft_margin */
        if (hpwdt_change_timer(soft_margin))
                hpwdt_change_timer(DEFAULT_MARGIN);
index 6aa46a90ff028691f97627765f593d864bc885a1..3796434991faa83466c85c8779a072db1278ef33 100644 (file)
@@ -128,11 +128,12 @@ EXPORT_SYMBOL_GPL(watchdog_register_device);
 void watchdog_unregister_device(struct watchdog_device *wdd)
 {
        int ret;
-       int devno = wdd->cdev.dev;
+       int devno;
 
        if (wdd == NULL)
                return;
 
+       devno = wdd->cdev.dev;
        ret = watchdog_dev_unregister(wdd);
        if (ret)
                pr_err("error unregistering /dev/watchdog (err=%d)\n", ret);
index 1ffd03bf8e10dcb6b015e3e0b94a2a460f0d0dcd..7f1241608489de05a33e957a77145f4faa605f0e 100644 (file)
@@ -314,8 +314,9 @@ static int __unmap_grant_pages(struct grant_map *map, int offset, int pages)
                }
        }
 
-       err = gnttab_unmap_refs(map->unmap_ops + offset, map->pages + offset,
-                               pages, true);
+       err = gnttab_unmap_refs(map->unmap_ops + offset,
+                       use_ptemod ? map->kmap_ops + offset : NULL, map->pages + offset,
+                       pages);
        if (err)
                return err;
 
index 0bfc1ef11259eccaa937eb8d0913e4e14e04832e..006726688baf4f0a535896dd38c9a3ea2198c617 100644 (file)
@@ -870,7 +870,8 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
 EXPORT_SYMBOL_GPL(gnttab_map_refs);
 
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
-                     struct page **pages, unsigned int count, bool clear_pte)
+                     struct gnttab_map_grant_ref *kmap_ops,
+                     struct page **pages, unsigned int count)
 {
        int i, ret;
        bool lazy = false;
@@ -888,7 +889,8 @@ int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
        }
 
        for (i = 0; i < count; i++) {
-               ret = m2p_remove_override(pages[i], clear_pte);
+               ret = m2p_remove_override(pages[i], kmap_ops ?
+                                      &kmap_ops[i] : NULL);
                if (ret)
                        return ret;
        }
index d4c50d63acbc14b03b8bcf3aac7d8c80fb1ea2d7..97ca359ae2bdfb8d072ee62348114a252660adf9 100644 (file)
@@ -101,19 +101,6 @@ static int platform_pci_resume(struct pci_dev *pdev)
        return 0;
 }
 
-static void __devinit prepare_shared_info(void)
-{
-#ifdef CONFIG_KEXEC
-       unsigned long addr;
-       struct shared_info *hvm_shared_info;
-
-       addr = alloc_xen_mmio(PAGE_SIZE);
-       hvm_shared_info = ioremap(addr, PAGE_SIZE);
-       memset(hvm_shared_info, 0, PAGE_SIZE);
-       xen_hvm_prepare_kexec(hvm_shared_info, addr >> PAGE_SHIFT);
-#endif
-}
-
 static int __devinit platform_pci_init(struct pci_dev *pdev,
                                       const struct pci_device_id *ent)
 {
@@ -151,8 +138,6 @@ static int __devinit platform_pci_init(struct pci_dev *pdev,
        platform_mmio = mmio_addr;
        platform_mmiolen = mmio_len;
 
-       prepare_shared_info();
-
        if (!xen_have_vector_callback) {
                ret = xen_allocate_irq(pdev);
                if (ret) {
index 1afb4fba11b430b5b7cf0f0b16cd2afa8fb61f08..4d519488d3045355672b8f48e3c1e2eb4ac64864 100644 (file)
@@ -232,7 +232,7 @@ xen_swiotlb_alloc_coherent(struct device *hwdev, size_t size,
                return ret;
 
        if (hwdev && hwdev->coherent_dma_mask)
-               dma_mask = hwdev->coherent_dma_mask;
+               dma_mask = dma_alloc_coherent_mask(hwdev, flags);
 
        phys = virt_to_phys(ret);
        dev_addr = xen_phys_to_bus(phys);
index 097e536e8672d68ff32da41406156a75ed05a996..03342728bf2352ff751f21c333b58bd5cb8756b6 100644 (file)
@@ -353,16 +353,16 @@ static int __devinit pcistub_init_device(struct pci_dev *dev)
        if (err)
                goto config_release;
 
-       dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
-       __pci_reset_function_locked(dev);
-
        /* We need the device active to save the state. */
        dev_dbg(&dev->dev, "save state of device\n");
        pci_save_state(dev);
        dev_data->pci_saved_state = pci_store_saved_state(dev);
        if (!dev_data->pci_saved_state)
                dev_err(&dev->dev, "Could not store PCI conf saved state!\n");
-
+       else {
+               dev_dbg(&dev->dev, "reseting (FLR, D3, etc) the device\n");
+               __pci_reset_function_locked(dev);
+       }
        /* Now disable the device (this also ensures some private device
         * data is setup before we export)
         */
index 5eaa70c9d96e6bb3900930d63beb224f38d15c8f..71072ab99128aadf1090e2ceab32bae67827dc9c 100644 (file)
--- a/fs/bio.c
+++ b/fs/bio.c
@@ -73,7 +73,7 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
 {
        unsigned int sz = sizeof(struct bio) + extra_size;
        struct kmem_cache *slab = NULL;
-       struct bio_slab *bslab;
+       struct bio_slab *bslab, *new_bio_slabs;
        unsigned int i, entry = -1;
 
        mutex_lock(&bio_slab_lock);
@@ -97,11 +97,12 @@ static struct kmem_cache *bio_find_or_create_slab(unsigned int extra_size)
 
        if (bio_slab_nr == bio_slab_max && entry == -1) {
                bio_slab_max <<= 1;
-               bio_slabs = krealloc(bio_slabs,
-                                    bio_slab_max * sizeof(struct bio_slab),
-                                    GFP_KERNEL);
-               if (!bio_slabs)
+               new_bio_slabs = krealloc(bio_slabs,
+                                        bio_slab_max * sizeof(struct bio_slab),
+                                        GFP_KERNEL);
+               if (!new_bio_slabs)
                        goto out_unlock;
+               bio_slabs = new_bio_slabs;
        }
        if (entry == -1)
                entry = bio_slab_nr++;
index 1e519195d45bd1ab466f8b7ee12505f35a45d271..38e721b35d45388cb0febed8021a02277a4a2f1b 100644 (file)
@@ -1578,10 +1578,12 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                         unsigned long nr_segs, loff_t pos)
 {
        struct file *file = iocb->ki_filp;
+       struct blk_plug plug;
        ssize_t ret;
 
        BUG_ON(iocb->ki_pos != pos);
 
+       blk_start_plug(&plug);
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        if (ret > 0 || ret == -EIOCBQUEUED) {
                ssize_t err;
@@ -1590,6 +1592,7 @@ ssize_t blkdev_aio_write(struct kiocb *iocb, const struct iovec *iov,
                if (err < 0 && ret > 0)
                        ret = err;
        }
+       blk_finish_plug(&plug);
        return ret;
 }
 EXPORT_SYMBOL_GPL(blkdev_aio_write);
index a256f3b2a845f22ef1c0c8dd1310364a96b651f5..ff6475f409d64aaade5499f9d0cee64c2989a80c 100644 (file)
@@ -1438,10 +1438,10 @@ int iterate_inodes_from_logical(u64 logical, struct btrfs_fs_info *fs_info,
        ret = extent_from_logical(fs_info, logical, path,
                                        &found_key);
        btrfs_release_path(path);
-       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
-               ret = -EINVAL;
        if (ret < 0)
                return ret;
+       if (ret & BTRFS_EXTENT_FLAG_TREE_BLOCK)
+               return -EINVAL;
 
        extent_item_pos = logical - found_key.objectid;
        ret = iterate_extent_inodes(fs_info, found_key.objectid,
index 86eff48dab786d525d3395d31dcf3f45a11dafc1..43d1c5a3a030888544d8dd8f7b36239386552d08 100644 (file)
@@ -818,6 +818,7 @@ static void free_workspace(int type, struct list_head *workspace)
        btrfs_compress_op[idx]->free_workspace(workspace);
        atomic_dec(alloc_workspace);
 wake:
+       smp_mb();
        if (waitqueue_active(workspace_wait))
                wake_up(workspace_wait);
 }
index 9d7621f271ff1e5b3f2b57931d96dad265678d7d..6d183f60d63a0521e8c4461e4d5fd705163d17d1 100644 (file)
@@ -420,12 +420,6 @@ void btrfs_put_tree_mod_seq(struct btrfs_fs_info *fs_info,
        }
        spin_unlock(&fs_info->tree_mod_seq_lock);
 
-       /*
-        * we removed the lowest blocker from the blocker list, so there may be
-        * more processible delayed refs.
-        */
-       wake_up(&fs_info->tree_mod_seq_wait);
-
        /*
         * anything that's lower than the lowest existing (read: blocked)
         * sequence number can be removed from the tree.
@@ -631,6 +625,9 @@ __tree_mod_log_free_eb(struct btrfs_fs_info *fs_info, struct extent_buffer *eb)
        u32 nritems;
        int ret;
 
+       if (btrfs_header_level(eb) == 0)
+               return;
+
        nritems = btrfs_header_nritems(eb);
        for (i = nritems - 1; i >= 0; i--) {
                ret = tree_mod_log_insert_key_locked(fs_info, eb, i,
index 4bab807227ad938c87039ea2aa1ef8f94fe46146..0d195b5076604b4350f88de9a58e9f4836fd785a 100644 (file)
@@ -1252,7 +1252,6 @@ struct btrfs_fs_info {
        atomic_t tree_mod_seq;
        struct list_head tree_mod_seq_list;
        struct seq_list tree_mod_seq_elem;
-       wait_queue_head_t tree_mod_seq_wait;
 
        /* this protects tree_mod_log */
        rwlock_t tree_mod_log_lock;
@@ -3192,7 +3191,7 @@ int btrfs_del_csums(struct btrfs_trans_handle *trans,
 int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
                          struct bio *bio, u32 *dst);
 int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
-                             struct bio *bio, u64 logical_offset, u32 *dst);
+                             struct bio *bio, u64 logical_offset);
 int btrfs_insert_file_extent(struct btrfs_trans_handle *trans,
                             struct btrfs_root *root,
                             u64 objectid, u64 pos,
index 335605c8ceab730394d45d9975adaa7025203dd7..07d5eeb1e6f1df1f8ae2ddf94218b1f45298aeda 100644 (file)
@@ -512,8 +512,8 @@ static void __btrfs_remove_delayed_item(struct btrfs_delayed_item *delayed_item)
 
        rb_erase(&delayed_item->rb_node, root);
        delayed_item->delayed_node->count--;
-       atomic_dec(&delayed_root->items);
-       if (atomic_read(&delayed_root->items) < BTRFS_DELAYED_BACKGROUND &&
+       if (atomic_dec_return(&delayed_root->items) <
+           BTRFS_DELAYED_BACKGROUND &&
            waitqueue_active(&delayed_root->wait))
                wake_up(&delayed_root->wait);
 }
@@ -1028,9 +1028,10 @@ do_again:
                btrfs_release_delayed_item(prev);
                ret = 0;
                btrfs_release_path(path);
-               if (curr)
+               if (curr) {
+                       mutex_unlock(&node->mutex);
                        goto do_again;
-               else
+               else
                        goto delete_fail;
        }
 
@@ -1055,8 +1056,7 @@ static void btrfs_release_delayed_inode(struct btrfs_delayed_node *delayed_node)
                delayed_node->count--;
 
                delayed_root = delayed_node->root->fs_info->delayed_root;
-               atomic_dec(&delayed_root->items);
-               if (atomic_read(&delayed_root->items) <
+               if (atomic_dec_return(&delayed_root->items) <
                    BTRFS_DELAYED_BACKGROUND &&
                    waitqueue_active(&delayed_root->wait))
                        wake_up(&delayed_root->wait);
index da7419ed01bb7e520cfbcac0fbef44ef607a92e5..ae94117733973e2d7aa8ea590c171fcf2e6bd26a 100644 (file)
 static int comp_tree_refs(struct btrfs_delayed_tree_ref *ref2,
                          struct btrfs_delayed_tree_ref *ref1)
 {
-       if (ref1->node.type == BTRFS_TREE_BLOCK_REF_KEY) {
-               if (ref1->root < ref2->root)
-                       return -1;
-               if (ref1->root > ref2->root)
-                       return 1;
-       } else {
-               if (ref1->parent < ref2->parent)
-                       return -1;
-               if (ref1->parent > ref2->parent)
-                       return 1;
-       }
+       if (ref1->root < ref2->root)
+               return -1;
+       if (ref1->root > ref2->root)
+               return 1;
+       if (ref1->parent < ref2->parent)
+               return -1;
+       if (ref1->parent > ref2->parent)
+               return 1;
        return 0;
 }
 
@@ -85,7 +82,8 @@ static int comp_data_refs(struct btrfs_delayed_data_ref *ref2,
  * type of the delayed backrefs and content of delayed backrefs.
  */
 static int comp_entry(struct btrfs_delayed_ref_node *ref2,
-                     struct btrfs_delayed_ref_node *ref1)
+                     struct btrfs_delayed_ref_node *ref1,
+                     bool compare_seq)
 {
        if (ref1->bytenr < ref2->bytenr)
                return -1;
@@ -102,10 +100,12 @@ static int comp_entry(struct btrfs_delayed_ref_node *ref2,
        if (ref1->type > ref2->type)
                return 1;
        /* merging of sequenced refs is not allowed */
-       if (ref1->seq < ref2->seq)
-               return -1;
-       if (ref1->seq > ref2->seq)
-               return 1;
+       if (compare_seq) {
+               if (ref1->seq < ref2->seq)
+                       return -1;
+               if (ref1->seq > ref2->seq)
+                       return 1;
+       }
        if (ref1->type == BTRFS_TREE_BLOCK_REF_KEY ||
            ref1->type == BTRFS_SHARED_BLOCK_REF_KEY) {
                return comp_tree_refs(btrfs_delayed_node_to_tree_ref(ref2),
@@ -139,7 +139,7 @@ static struct btrfs_delayed_ref_node *tree_insert(struct rb_root *root,
                entry = rb_entry(parent_node, struct btrfs_delayed_ref_node,
                                 rb_node);
 
-               cmp = comp_entry(entry, ins);
+               cmp = comp_entry(entry, ins, 1);
                if (cmp < 0)
                        p = &(*p)->rb_left;
                else if (cmp > 0)
@@ -233,6 +233,114 @@ int btrfs_delayed_ref_lock(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static void inline drop_delayed_ref(struct btrfs_trans_handle *trans,
+                                   struct btrfs_delayed_ref_root *delayed_refs,
+                                   struct btrfs_delayed_ref_node *ref)
+{
+       rb_erase(&ref->rb_node, &delayed_refs->root);
+       ref->in_tree = 0;
+       btrfs_put_delayed_ref(ref);
+       delayed_refs->num_entries--;
+       if (trans->delayed_ref_updates)
+               trans->delayed_ref_updates--;
+}
+
+static int merge_ref(struct btrfs_trans_handle *trans,
+                    struct btrfs_delayed_ref_root *delayed_refs,
+                    struct btrfs_delayed_ref_node *ref, u64 seq)
+{
+       struct rb_node *node;
+       int merged = 0;
+       int mod = 0;
+       int done = 0;
+
+       node = rb_prev(&ref->rb_node);
+       while (node) {
+               struct btrfs_delayed_ref_node *next;
+
+               next = rb_entry(node, struct btrfs_delayed_ref_node, rb_node);
+               node = rb_prev(node);
+               if (next->bytenr != ref->bytenr)
+                       break;
+               if (seq && next->seq >= seq)
+                       break;
+               if (comp_entry(ref, next, 0))
+                       continue;
+
+               if (ref->action == next->action) {
+                       mod = next->ref_mod;
+               } else {
+                       if (ref->ref_mod < next->ref_mod) {
+                               struct btrfs_delayed_ref_node *tmp;
+
+                               tmp = ref;
+                               ref = next;
+                               next = tmp;
+                               done = 1;
+                       }
+                       mod = -next->ref_mod;
+               }
+
+               merged++;
+               drop_delayed_ref(trans, delayed_refs, next);
+               ref->ref_mod += mod;
+               if (ref->ref_mod == 0) {
+                       drop_delayed_ref(trans, delayed_refs, ref);
+                       break;
+               } else {
+                       /*
+                        * You can't have multiples of the same ref on a tree
+                        * block.
+                        */
+                       WARN_ON(ref->type == BTRFS_TREE_BLOCK_REF_KEY ||
+                               ref->type == BTRFS_SHARED_BLOCK_REF_KEY);
+               }
+
+               if (done)
+                       break;
+               node = rb_prev(&ref->rb_node);
+       }
+
+       return merged;
+}
+
+void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+                             struct btrfs_fs_info *fs_info,
+                             struct btrfs_delayed_ref_root *delayed_refs,
+                             struct btrfs_delayed_ref_head *head)
+{
+       struct rb_node *node;
+       u64 seq = 0;
+
+       spin_lock(&fs_info->tree_mod_seq_lock);
+       if (!list_empty(&fs_info->tree_mod_seq_list)) {
+               struct seq_list *elem;
+
+               elem = list_first_entry(&fs_info->tree_mod_seq_list,
+                                       struct seq_list, list);
+               seq = elem->seq;
+       }
+       spin_unlock(&fs_info->tree_mod_seq_lock);
+
+       node = rb_prev(&head->node.rb_node);
+       while (node) {
+               struct btrfs_delayed_ref_node *ref;
+
+               ref = rb_entry(node, struct btrfs_delayed_ref_node,
+                              rb_node);
+               if (ref->bytenr != head->node.bytenr)
+                       break;
+
+               /* We can't merge refs that are outside of our seq count */
+               if (seq && ref->seq >= seq)
+                       break;
+               if (merge_ref(trans, delayed_refs, ref, seq))
+                       node = rb_prev(&head->node.rb_node);
+               else
+                       node = rb_prev(node);
+       }
+}
+
 int btrfs_check_delayed_seq(struct btrfs_fs_info *fs_info,
                            struct btrfs_delayed_ref_root *delayed_refs,
                            u64 seq)
@@ -336,18 +444,11 @@ update_existing_ref(struct btrfs_trans_handle *trans,
                 * every changing the extent allocation tree.
                 */
                existing->ref_mod--;
-               if (existing->ref_mod == 0) {
-                       rb_erase(&existing->rb_node,
-                                &delayed_refs->root);
-                       existing->in_tree = 0;
-                       btrfs_put_delayed_ref(existing);
-                       delayed_refs->num_entries--;
-                       if (trans->delayed_ref_updates)
-                               trans->delayed_ref_updates--;
-               } else {
+               if (existing->ref_mod == 0)
+                       drop_delayed_ref(trans, delayed_refs, existing);
+               else
                        WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY ||
                                existing->type == BTRFS_SHARED_BLOCK_REF_KEY);
-               }
        } else {
                WARN_ON(existing->type == BTRFS_TREE_BLOCK_REF_KEY ||
                        existing->type == BTRFS_SHARED_BLOCK_REF_KEY);
@@ -662,9 +763,6 @@ int btrfs_add_delayed_tree_ref(struct btrfs_fs_info *fs_info,
        add_delayed_tree_ref(fs_info, trans, &ref->node, bytenr,
                                   num_bytes, parent, ref_root, level, action,
                                   for_cow);
-       if (!need_ref_seq(for_cow, ref_root) &&
-           waitqueue_active(&fs_info->tree_mod_seq_wait))
-               wake_up(&fs_info->tree_mod_seq_wait);
        spin_unlock(&delayed_refs->lock);
        if (need_ref_seq(for_cow, ref_root))
                btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
@@ -713,9 +811,6 @@ int btrfs_add_delayed_data_ref(struct btrfs_fs_info *fs_info,
        add_delayed_data_ref(fs_info, trans, &ref->node, bytenr,
                                   num_bytes, parent, ref_root, owner, offset,
                                   action, for_cow);
-       if (!need_ref_seq(for_cow, ref_root) &&
-           waitqueue_active(&fs_info->tree_mod_seq_wait))
-               wake_up(&fs_info->tree_mod_seq_wait);
        spin_unlock(&delayed_refs->lock);
        if (need_ref_seq(for_cow, ref_root))
                btrfs_qgroup_record_ref(trans, &ref->node, extent_op);
@@ -744,8 +839,6 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
                                   num_bytes, BTRFS_UPDATE_DELAYED_HEAD,
                                   extent_op->is_data);
 
-       if (waitqueue_active(&fs_info->tree_mod_seq_wait))
-               wake_up(&fs_info->tree_mod_seq_wait);
        spin_unlock(&delayed_refs->lock);
        return 0;
 }
index 0d7c90c366b629152796c0c717c0e4cd5f50e9b1..ab5300595847e20602c307620a3a5059ca258b06 100644 (file)
@@ -167,6 +167,10 @@ int btrfs_add_delayed_extent_op(struct btrfs_fs_info *fs_info,
                                struct btrfs_trans_handle *trans,
                                u64 bytenr, u64 num_bytes,
                                struct btrfs_delayed_extent_op *extent_op);
+void btrfs_merge_delayed_refs(struct btrfs_trans_handle *trans,
+                             struct btrfs_fs_info *fs_info,
+                             struct btrfs_delayed_ref_root *delayed_refs,
+                             struct btrfs_delayed_ref_head *head);
 
 struct btrfs_delayed_ref_head *
 btrfs_find_delayed_ref_head(struct btrfs_trans_handle *trans, u64 bytenr);
index 62e0cafd6e250d5d1717656d3d5821e2d1bfec42..22e98e04c2eabbc0b4baeb2618033657a9344fb9 100644 (file)
@@ -377,9 +377,13 @@ static int btree_read_extent_buffer_pages(struct btrfs_root *root,
                ret = read_extent_buffer_pages(io_tree, eb, start,
                                               WAIT_COMPLETE,
                                               btree_get_extent, mirror_num);
-               if (!ret && !verify_parent_transid(io_tree, eb,
+               if (!ret) {
+                       if (!verify_parent_transid(io_tree, eb,
                                                   parent_transid, 0))
-                       break;
+                               break;
+                       else
+                               ret = -EIO;
+               }
 
                /*
                 * This buffer's crc is fine, but its contents are corrupted, so
@@ -754,9 +758,7 @@ static void run_one_async_done(struct btrfs_work *work)
        limit = btrfs_async_submit_limit(fs_info);
        limit = limit * 2 / 3;
 
-       atomic_dec(&fs_info->nr_async_submits);
-
-       if (atomic_read(&fs_info->nr_async_submits) < limit &&
+       if (atomic_dec_return(&fs_info->nr_async_submits) < limit &&
            waitqueue_active(&fs_info->async_submit_wait))
                wake_up(&fs_info->async_submit_wait);
 
@@ -2032,8 +2034,6 @@ int open_ctree(struct super_block *sb,
        fs_info->free_chunk_space = 0;
        fs_info->tree_mod_log = RB_ROOT;
 
-       init_waitqueue_head(&fs_info->tree_mod_seq_wait);
-
        /* readahead state */
        INIT_RADIX_TREE(&fs_info->reada_tree, GFP_NOFS & ~__GFP_WAIT);
        spin_lock_init(&fs_info->reada_lock);
@@ -2528,8 +2528,7 @@ retry_root_backup:
                goto fail_trans_kthread;
 
        /* do not make disk changes in broken FS */
-       if (btrfs_super_log_root(disk_super) != 0 &&
-           !(fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)) {
+       if (btrfs_super_log_root(disk_super) != 0) {
                u64 bytenr = btrfs_super_log_root(disk_super);
 
                if (fs_devices->rw_devices == 0) {
@@ -3189,30 +3188,14 @@ int close_ctree(struct btrfs_root *root)
        /* clear out the rbtree of defraggable inodes */
        btrfs_run_defrag_inodes(fs_info);
 
-       /*
-        * Here come 2 situations when btrfs is broken to flip readonly:
-        *
-        * 1. when btrfs flips readonly somewhere else before
-        * btrfs_commit_super, sb->s_flags has MS_RDONLY flag,
-        * and btrfs will skip to write sb directly to keep
-        * ERROR state on disk.
-        *
-        * 2. when btrfs flips readonly just in btrfs_commit_super,
-        * and in such case, btrfs cannot write sb via btrfs_commit_super,
-        * and since fs_state has been set BTRFS_SUPER_FLAG_ERROR flag,
-        * btrfs will cleanup all FS resources first and write sb then.
-        */
        if (!(fs_info->sb->s_flags & MS_RDONLY)) {
                ret = btrfs_commit_super(root);
                if (ret)
                        printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
        }
 
-       if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
-               ret = btrfs_error_commit_super(root);
-               if (ret)
-                       printk(KERN_ERR "btrfs: commit super ret %d\n", ret);
-       }
+       if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR)
+               btrfs_error_commit_super(root);
 
        btrfs_put_block_group_cache(fs_info);
 
@@ -3434,18 +3417,11 @@ static int btrfs_check_super_valid(struct btrfs_fs_info *fs_info,
        if (read_only)
                return 0;
 
-       if (fs_info->fs_state & BTRFS_SUPER_FLAG_ERROR) {
-               printk(KERN_WARNING "warning: mount fs with errors, "
-                      "running btrfsck is recommended\n");
-       }
-
        return 0;
 }
 
-int btrfs_error_commit_super(struct btrfs_root *root)
+void btrfs_error_commit_super(struct btrfs_root *root)
 {
-       int ret;
-
        mutex_lock(&root->fs_info->cleaner_mutex);
        btrfs_run_delayed_iputs(root);
        mutex_unlock(&root->fs_info->cleaner_mutex);
@@ -3455,10 +3431,6 @@ int btrfs_error_commit_super(struct btrfs_root *root)
 
        /* cleanup FS via transaction */
        btrfs_cleanup_transaction(root);
-
-       ret = write_ctree_super(NULL, root, 0);
-
-       return ret;
 }
 
 static void btrfs_destroy_ordered_operations(struct btrfs_root *root)
@@ -3782,14 +3754,17 @@ int btrfs_cleanup_transaction(struct btrfs_root *root)
                /* FIXME: cleanup wait for commit */
                t->in_commit = 1;
                t->blocked = 1;
+               smp_mb();
                if (waitqueue_active(&root->fs_info->transaction_blocked_wait))
                        wake_up(&root->fs_info->transaction_blocked_wait);
 
                t->blocked = 0;
+               smp_mb();
                if (waitqueue_active(&root->fs_info->transaction_wait))
                        wake_up(&root->fs_info->transaction_wait);
 
                t->commit_done = 1;
+               smp_mb();
                if (waitqueue_active(&t->commit_wait))
                        wake_up(&t->commit_wait);
 
index 95e147eea23952c689ee9e87cfd39e7d61fde96b..c5b00a735fefac258b7914223139d902efacbf99 100644 (file)
@@ -54,7 +54,7 @@ int write_ctree_super(struct btrfs_trans_handle *trans,
                      struct btrfs_root *root, int max_mirrors);
 struct buffer_head *btrfs_read_dev_super(struct block_device *bdev);
 int btrfs_commit_super(struct btrfs_root *root);
-int btrfs_error_commit_super(struct btrfs_root *root);
+void btrfs_error_commit_super(struct btrfs_root *root);
 struct extent_buffer *btrfs_find_tree_block(struct btrfs_root *root,
                                            u64 bytenr, u32 blocksize);
 struct btrfs_root *btrfs_read_fs_root_no_radix(struct btrfs_root *tree_root,
index 4e1b153b7c47c99e00adffd8ee6d24e2db29093d..ba58024d40d3eaf486c50d96cd116c3b828b9c75 100644 (file)
@@ -2251,6 +2251,16 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                        }
                }
 
+               /*
+                * We need to try and merge add/drops of the same ref since we
+                * can run into issues with relocate dropping the implicit ref
+                * and then it being added back again before the drop can
+                * finish.  If we merged anything we need to re-loop so we can
+                * get a good ref.
+                */
+               btrfs_merge_delayed_refs(trans, fs_info, delayed_refs,
+                                        locked_ref);
+
                /*
                 * locked_ref is the head node, so we have to go one
                 * node back for any delayed ref updates
@@ -2318,12 +2328,23 @@ static noinline int run_clustered_refs(struct btrfs_trans_handle *trans,
                ref->in_tree = 0;
                rb_erase(&ref->rb_node, &delayed_refs->root);
                delayed_refs->num_entries--;
-               /*
-                * we modified num_entries, but as we're currently running
-                * delayed refs, skip
-                *     wake_up(&delayed_refs->seq_wait);
-                * here.
-                */
+               if (locked_ref) {
+                       /*
+                        * when we play the delayed ref, also correct the
+                        * ref_mod on head
+                        */
+                       switch (ref->action) {
+                       case BTRFS_ADD_DELAYED_REF:
+                       case BTRFS_ADD_DELAYED_EXTENT:
+                               locked_ref->node.ref_mod -= ref->ref_mod;
+                               break;
+                       case BTRFS_DROP_DELAYED_REF:
+                               locked_ref->node.ref_mod += ref->ref_mod;
+                               break;
+                       default:
+                               WARN_ON(1);
+                       }
+               }
                spin_unlock(&delayed_refs->lock);
 
                ret = run_one_delayed_ref(trans, root, ref, extent_op,
@@ -2350,22 +2371,6 @@ next:
        return count;
 }
 
-static void wait_for_more_refs(struct btrfs_fs_info *fs_info,
-                              struct btrfs_delayed_ref_root *delayed_refs,
-                              unsigned long num_refs,
-                              struct list_head *first_seq)
-{
-       spin_unlock(&delayed_refs->lock);
-       pr_debug("waiting for more refs (num %ld, first %p)\n",
-                num_refs, first_seq);
-       wait_event(fs_info->tree_mod_seq_wait,
-                  num_refs != delayed_refs->num_entries ||
-                  fs_info->tree_mod_seq_list.next != first_seq);
-       pr_debug("done waiting for more refs (num %ld, first %p)\n",
-                delayed_refs->num_entries, fs_info->tree_mod_seq_list.next);
-       spin_lock(&delayed_refs->lock);
-}
-
 #ifdef SCRAMBLE_DELAYED_REFS
 /*
  * Normally delayed refs get processed in ascending bytenr order. This
@@ -2460,13 +2465,11 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        struct btrfs_delayed_ref_root *delayed_refs;
        struct btrfs_delayed_ref_node *ref;
        struct list_head cluster;
-       struct list_head *first_seq = NULL;
        int ret;
        u64 delayed_start;
        int run_all = count == (unsigned long)-1;
        int run_most = 0;
-       unsigned long num_refs = 0;
-       int consider_waiting;
+       int loops;
 
        /* We'll clean this up in btrfs_cleanup_transaction */
        if (trans->aborted)
@@ -2484,7 +2487,7 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
        delayed_refs = &trans->transaction->delayed_refs;
        INIT_LIST_HEAD(&cluster);
 again:
-       consider_waiting = 0;
+       loops = 0;
        spin_lock(&delayed_refs->lock);
 
 #ifdef SCRAMBLE_DELAYED_REFS
@@ -2512,31 +2515,6 @@ again:
                if (ret)
                        break;
 
-               if (delayed_start >= delayed_refs->run_delayed_start) {
-                       if (consider_waiting == 0) {
-                               /*
-                                * btrfs_find_ref_cluster looped. let's do one
-                                * more cycle. if we don't run any delayed ref
-                                * during that cycle (because we can't because
-                                * all of them are blocked) and if the number of
-                                * refs doesn't change, we avoid busy waiting.
-                                */
-                               consider_waiting = 1;
-                               num_refs = delayed_refs->num_entries;
-                               first_seq = root->fs_info->tree_mod_seq_list.next;
-                       } else {
-                               wait_for_more_refs(root->fs_info, delayed_refs,
-                                                  num_refs, first_seq);
-                               /*
-                                * after waiting, things have changed. we
-                                * dropped the lock and someone else might have
-                                * run some refs, built new clusters and so on.
-                                * therefore, we restart staleness detection.
-                                */
-                               consider_waiting = 0;
-                       }
-               }
-
                ret = run_clustered_refs(trans, root, &cluster);
                if (ret < 0) {
                        spin_unlock(&delayed_refs->lock);
@@ -2549,9 +2527,26 @@ again:
                if (count == 0)
                        break;
 
-               if (ret || delayed_refs->run_delayed_start == 0) {
+               if (delayed_start >= delayed_refs->run_delayed_start) {
+                       if (loops == 0) {
+                               /*
+                                * btrfs_find_ref_cluster looped. let's do one
+                                * more cycle. if we don't run any delayed ref
+                                * during that cycle (because we can't because
+                                * all of them are blocked), bail out.
+                                */
+                               loops = 1;
+                       } else {
+                               /*
+                                * no runnable refs left, stop trying
+                                */
+                               BUG_ON(run_all);
+                               break;
+                       }
+               }
+               if (ret) {
                        /* refs were run, let's reset staleness detection */
-                       consider_waiting = 0;
+                       loops = 0;
                }
        }
 
@@ -3007,17 +3002,16 @@ again:
        }
        spin_unlock(&block_group->lock);
 
-       num_pages = (int)div64_u64(block_group->key.offset, 1024 * 1024 * 1024);
+       /*
+        * Try to preallocate enough space based on how big the block group is.
+        * Keep in mind this has to include any pinned space which could end up
+        * taking up quite a bit since it's not folded into the other space
+        * cache.
+        */
+       num_pages = (int)div64_u64(block_group->key.offset, 256 * 1024 * 1024);
        if (!num_pages)
                num_pages = 1;
 
-       /*
-        * Just to make absolutely sure we have enough space, we're going to
-        * preallocate 12 pages worth of space for each block group.  In
-        * practice we ought to use at most 8, but we need extra space so we can
-        * add our header and have a terminator between the extents and the
-        * bitmaps.
-        */
        num_pages *= 16;
        num_pages *= PAGE_CACHE_SIZE;
 
@@ -4571,8 +4565,10 @@ int btrfs_delalloc_reserve_metadata(struct inode *inode, u64 num_bytes)
        if (root->fs_info->quota_enabled) {
                ret = btrfs_qgroup_reserve(root, num_bytes +
                                           nr_extents * root->leafsize);
-               if (ret)
+               if (ret) {
+                       mutex_unlock(&BTRFS_I(inode)->delalloc_mutex);
                        return ret;
+               }
        }
 
        ret = reserve_metadata_bytes(root, block_rsv, to_reserve, flush);
@@ -5294,9 +5290,6 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
        rb_erase(&head->node.rb_node, &delayed_refs->root);
 
        delayed_refs->num_entries--;
-       smp_mb();
-       if (waitqueue_active(&root->fs_info->tree_mod_seq_wait))
-               wake_up(&root->fs_info->tree_mod_seq_wait);
 
        /*
         * we don't take a ref on the node because we're removing it from the
index 45c81bb4ac820323c7fd4282a0cf71f7cc2d190d..4c878476bb91ce0985dabc25464622442aaca54a 100644 (file)
@@ -2330,23 +2330,10 @@ static void end_bio_extent_readpage(struct bio *bio, int err)
                if (uptodate && tree->ops && tree->ops->readpage_end_io_hook) {
                        ret = tree->ops->readpage_end_io_hook(page, start, end,
                                                              state, mirror);
-                       if (ret) {
-                               /* no IO indicated but software detected errors
-                                * in the block, either checksum errors or
-                                * issues with the contents */
-                               struct btrfs_root *root =
-                                       BTRFS_I(page->mapping->host)->root;
-                               struct btrfs_device *device;
-
+                       if (ret)
                                uptodate = 0;
-                               device = btrfs_find_device_for_logical(
-                                               root, start, mirror);
-                               if (device)
-                                       btrfs_dev_stat_inc_and_print(device,
-                                               BTRFS_DEV_STAT_CORRUPTION_ERRS);
-                       } else {
+                       else
                                clean_io_failure(start, page);
-                       }
                }
 
                if (!uptodate && tree->ops && tree->ops->readpage_io_failed_hook) {
index b45b9de0c21d0f773f19f45ee10ae9803fa36f3a..857d93cd01dc579eb46838624349442fef07cf00 100644 (file)
@@ -272,9 +272,9 @@ int btrfs_lookup_bio_sums(struct btrfs_root *root, struct inode *inode,
 }
 
 int btrfs_lookup_bio_sums_dio(struct btrfs_root *root, struct inode *inode,
-                             struct bio *bio, u64 offset, u32 *dst)
+                             struct bio *bio, u64 offset)
 {
-       return __btrfs_lookup_bio_sums(root, inode, bio, offset, dst, 1);
+       return __btrfs_lookup_bio_sums(root, inode, bio, offset, NULL, 1);
 }
 
 int btrfs_lookup_csums_range(struct btrfs_root *root, u64 start, u64 end,
index 6e8f416773d4b221713c30079eb1de1f732e5ded..ec154f95464696cfa7df3cd6ab87ac4a0185ed03 100644 (file)
@@ -1008,9 +1008,7 @@ static noinline void async_cow_submit(struct btrfs_work *work)
        nr_pages = (async_cow->end - async_cow->start + PAGE_CACHE_SIZE) >>
                PAGE_CACHE_SHIFT;
 
-       atomic_sub(nr_pages, &root->fs_info->async_delalloc_pages);
-
-       if (atomic_read(&root->fs_info->async_delalloc_pages) <
+       if (atomic_sub_return(nr_pages, &root->fs_info->async_delalloc_pages) <
            5 * 1024 * 1024 &&
            waitqueue_active(&root->fs_info->async_submit_wait))
                wake_up(&root->fs_info->async_submit_wait);
@@ -1885,8 +1883,11 @@ static int btrfs_finish_ordered_io(struct btrfs_ordered_extent *ordered_extent)
                                trans = btrfs_join_transaction_nolock(root);
                        else
                                trans = btrfs_join_transaction(root);
-                       if (IS_ERR(trans))
-                               return PTR_ERR(trans);
+                       if (IS_ERR(trans)) {
+                               ret = PTR_ERR(trans);
+                               trans = NULL;
+                               goto out;
+                       }
                        trans->block_rsv = &root->fs_info->delalloc_block_rsv;
                        ret = btrfs_update_inode_fallback(trans, root, inode);
                        if (ret) /* -ENOMEM or corruption */
@@ -3174,7 +3175,7 @@ int btrfs_unlink_subvol(struct btrfs_trans_handle *trans,
        btrfs_i_size_write(dir, dir->i_size - name_len * 2);
        inode_inc_iversion(dir);
        dir->i_mtime = dir->i_ctime = CURRENT_TIME;
-       ret = btrfs_update_inode(trans, root, dir);
+       ret = btrfs_update_inode_fallback(trans, root, dir);
        if (ret)
                btrfs_abort_transaction(trans, root, ret);
 out:
@@ -5774,18 +5775,112 @@ out:
        return ret;
 }
 
+static int lock_extent_direct(struct inode *inode, u64 lockstart, u64 lockend,
+                             struct extent_state **cached_state, int writing)
+{
+       struct btrfs_ordered_extent *ordered;
+       int ret = 0;
+
+       while (1) {
+               lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+                                0, cached_state);
+               /*
+                * We're concerned with the entire range that we're going to be
+                * doing DIO to, so we need to make sure theres no ordered
+                * extents in this range.
+                */
+               ordered = btrfs_lookup_ordered_range(inode, lockstart,
+                                                    lockend - lockstart + 1);
+
+               /*
+                * We need to make sure there are no buffered pages in this
+                * range either, we could have raced between the invalidate in
+                * generic_file_direct_write and locking the extent.  The
+                * invalidate needs to happen so that reads after a write do not
+                * get stale data.
+                */
+               if (!ordered && (!writing ||
+                   !test_range_bit(&BTRFS_I(inode)->io_tree,
+                                   lockstart, lockend, EXTENT_UPTODATE, 0,
+                                   *cached_state)))
+                       break;
+
+               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+                                    cached_state, GFP_NOFS);
+
+               if (ordered) {
+                       btrfs_start_ordered_extent(inode, ordered, 1);
+                       btrfs_put_ordered_extent(ordered);
+               } else {
+                       /* Screw you mmap */
+                       ret = filemap_write_and_wait_range(inode->i_mapping,
+                                                          lockstart,
+                                                          lockend);
+                       if (ret)
+                               break;
+
+                       /*
+                        * If we found a page that couldn't be invalidated just
+                        * fall back to buffered.
+                        */
+                       ret = invalidate_inode_pages2_range(inode->i_mapping,
+                                       lockstart >> PAGE_CACHE_SHIFT,
+                                       lockend >> PAGE_CACHE_SHIFT);
+                       if (ret)
+                               break;
+               }
+
+               cond_resched();
+       }
+
+       return ret;
+}
+
 static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                                   struct buffer_head *bh_result, int create)
 {
        struct extent_map *em;
        struct btrfs_root *root = BTRFS_I(inode)->root;
+       struct extent_state *cached_state = NULL;
        u64 start = iblock << inode->i_blkbits;
+       u64 lockstart, lockend;
        u64 len = bh_result->b_size;
        struct btrfs_trans_handle *trans;
+       int unlock_bits = EXTENT_LOCKED;
+       int ret;
+
+       if (create) {
+               ret = btrfs_delalloc_reserve_space(inode, len);
+               if (ret)
+                       return ret;
+               unlock_bits |= EXTENT_DELALLOC | EXTENT_DIRTY;
+       } else {
+               len = min_t(u64, len, root->sectorsize);
+       }
+
+       lockstart = start;
+       lockend = start + len - 1;
+
+       /*
+        * If this errors out it's because we couldn't invalidate pagecache for
+        * this range and we need to fallback to buffered.
+        */
+       if (lock_extent_direct(inode, lockstart, lockend, &cached_state, create))
+               return -ENOTBLK;
+
+       if (create) {
+               ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+                                    lockend, EXTENT_DELALLOC, NULL,
+                                    &cached_state, GFP_NOFS);
+               if (ret)
+                       goto unlock_err;
+       }
 
        em = btrfs_get_extent(inode, NULL, 0, start, len, 0);
-       if (IS_ERR(em))
-               return PTR_ERR(em);
+       if (IS_ERR(em)) {
+               ret = PTR_ERR(em);
+               goto unlock_err;
+       }
 
        /*
         * Ok for INLINE and COMPRESSED extents we need to fallback on buffered
@@ -5804,17 +5899,16 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
        if (test_bit(EXTENT_FLAG_COMPRESSED, &em->flags) ||
            em->block_start == EXTENT_MAP_INLINE) {
                free_extent_map(em);
-               return -ENOTBLK;
+               ret = -ENOTBLK;
+               goto unlock_err;
        }
 
        /* Just a good old fashioned hole, return */
        if (!create && (em->block_start == EXTENT_MAP_HOLE ||
                        test_bit(EXTENT_FLAG_PREALLOC, &em->flags))) {
                free_extent_map(em);
-               /* DIO will do one hole at a time, so just unlock a sector */
-               unlock_extent(&BTRFS_I(inode)->io_tree, start,
-                             start + root->sectorsize - 1);
-               return 0;
+               ret = 0;
+               goto unlock_err;
        }
 
        /*
@@ -5827,8 +5921,9 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
         *
         */
        if (!create) {
-               len = em->len - (start - em->start);
-               goto map;
+               len = min(len, em->len - (start - em->start));
+               lockstart = start + len;
+               goto unlock;
        }
 
        if (test_bit(EXTENT_FLAG_PREALLOC, &em->flags) ||
@@ -5860,7 +5955,7 @@ static int btrfs_get_blocks_direct(struct inode *inode, sector_t iblock,
                        btrfs_end_transaction(trans, root);
                        if (ret) {
                                free_extent_map(em);
-                               return ret;
+                               goto unlock_err;
                        }
                        goto unlock;
                }
@@ -5873,14 +5968,12 @@ must_cow:
         */
        len = bh_result->b_size;
        em = btrfs_new_extent_direct(inode, em, start, len);
-       if (IS_ERR(em))
-               return PTR_ERR(em);
+       if (IS_ERR(em)) {
+               ret = PTR_ERR(em);
+               goto unlock_err;
+       }
        len = min(len, em->len - (start - em->start));
 unlock:
-       clear_extent_bit(&BTRFS_I(inode)->io_tree, start, start + len - 1,
-                         EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DIRTY, 1,
-                         0, NULL, GFP_NOFS);
-map:
        bh_result->b_blocknr = (em->block_start + (start - em->start)) >>
                inode->i_blkbits;
        bh_result->b_size = len;
@@ -5898,9 +5991,44 @@ map:
                        i_size_write(inode, start + len);
        }
 
+       /*
+        * In the case of write we need to clear and unlock the entire range,
+        * in the case of read we need to unlock only the end area that we
+        * aren't using if there is any left over space.
+        */
+       if (lockstart < lockend) {
+               if (create && len < lockend - lockstart) {
+                       clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+                                        lockstart + len - 1, unlock_bits, 1, 0,
+                                        &cached_state, GFP_NOFS);
+                       /*
+                        * Beside unlock, we also need to cleanup reserved space
+                        * for the left range by attaching EXTENT_DO_ACCOUNTING.
+                        */
+                       clear_extent_bit(&BTRFS_I(inode)->io_tree,
+                                        lockstart + len, lockend,
+                                        unlock_bits | EXTENT_DO_ACCOUNTING,
+                                        1, 0, NULL, GFP_NOFS);
+               } else {
+                       clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
+                                        lockend, unlock_bits, 1, 0,
+                                        &cached_state, GFP_NOFS);
+               }
+       } else {
+               free_extent_state(cached_state);
+       }
+
        free_extent_map(em);
 
        return 0;
+
+unlock_err:
+       if (create)
+               unlock_bits |= EXTENT_DO_ACCOUNTING;
+
+       clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
+                        unlock_bits, 1, 0, &cached_state, GFP_NOFS);
+       return ret;
 }
 
 struct btrfs_dio_private {
@@ -5908,7 +6036,6 @@ struct btrfs_dio_private {
        u64 logical_offset;
        u64 disk_bytenr;
        u64 bytes;
-       u32 *csums;
        void *private;
 
        /* number of bios pending for this dio */
@@ -5928,7 +6055,6 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
        struct inode *inode = dip->inode;
        struct btrfs_root *root = BTRFS_I(inode)->root;
        u64 start;
-       u32 *private = dip->csums;
 
        start = dip->logical_offset;
        do {
@@ -5936,8 +6062,12 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
                        struct page *page = bvec->bv_page;
                        char *kaddr;
                        u32 csum = ~(u32)0;
+                       u64 private = ~(u32)0;
                        unsigned long flags;
 
+                       if (get_state_private(&BTRFS_I(inode)->io_tree,
+                                             start, &private))
+                               goto failed;
                        local_irq_save(flags);
                        kaddr = kmap_atomic(page);
                        csum = btrfs_csum_data(root, kaddr + bvec->bv_offset,
@@ -5947,18 +6077,18 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
                        local_irq_restore(flags);
 
                        flush_dcache_page(bvec->bv_page);
-                       if (csum != *private) {
+                       if (csum != private) {
+failed:
                                printk(KERN_ERR "btrfs csum failed ino %llu off"
                                      " %llu csum %u private %u\n",
                                      (unsigned long long)btrfs_ino(inode),
                                      (unsigned long long)start,
-                                     csum, *private);
+                                     csum, (unsigned)private);
                                err = -EIO;
                        }
                }
 
                start += bvec->bv_len;
-               private++;
                bvec++;
        } while (bvec <= bvec_end);
 
@@ -5966,7 +6096,6 @@ static void btrfs_endio_direct_read(struct bio *bio, int err)
                      dip->logical_offset + dip->bytes - 1);
        bio->bi_private = dip->private;
 
-       kfree(dip->csums);
        kfree(dip);
 
        /* If we had a csum failure make sure to clear the uptodate flag */
@@ -6072,7 +6201,7 @@ static struct bio *btrfs_dio_bio_alloc(struct block_device *bdev,
 
 static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
                                         int rw, u64 file_offset, int skip_sum,
-                                        u32 *csums, int async_submit)
+                                        int async_submit)
 {
        int write = rw & REQ_WRITE;
        struct btrfs_root *root = BTRFS_I(inode)->root;
@@ -6105,8 +6234,7 @@ static inline int __btrfs_submit_dio_bio(struct bio *bio, struct inode *inode,
                if (ret)
                        goto err;
        } else if (!skip_sum) {
-               ret = btrfs_lookup_bio_sums_dio(root, inode, bio,
-                                         file_offset, csums);
+               ret = btrfs_lookup_bio_sums_dio(root, inode, bio, file_offset);
                if (ret)
                        goto err;
        }
@@ -6132,10 +6260,8 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
        u64 submit_len = 0;
        u64 map_length;
        int nr_pages = 0;
-       u32 *csums = dip->csums;
        int ret = 0;
        int async_submit = 0;
-       int write = rw & REQ_WRITE;
 
        map_length = orig_bio->bi_size;
        ret = btrfs_map_block(map_tree, READ, start_sector << 9,
@@ -6171,16 +6297,13 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
                        atomic_inc(&dip->pending_bios);
                        ret = __btrfs_submit_dio_bio(bio, inode, rw,
                                                     file_offset, skip_sum,
-                                                    csums, async_submit);
+                                                    async_submit);
                        if (ret) {
                                bio_put(bio);
                                atomic_dec(&dip->pending_bios);
                                goto out_err;
                        }
 
-                       /* Write's use the ordered csums */
-                       if (!write && !skip_sum)
-                               csums = csums + nr_pages;
                        start_sector += submit_len >> 9;
                        file_offset += submit_len;
 
@@ -6210,7 +6333,7 @@ static int btrfs_submit_direct_hook(int rw, struct btrfs_dio_private *dip,
 
 submit:
        ret = __btrfs_submit_dio_bio(bio, inode, rw, file_offset, skip_sum,
-                                    csums, async_submit);
+                                    async_submit);
        if (!ret)
                return 0;
 
@@ -6246,17 +6369,6 @@ static void btrfs_submit_direct(int rw, struct bio *bio, struct inode *inode,
                ret = -ENOMEM;
                goto free_ordered;
        }
-       dip->csums = NULL;
-
-       /* Write's use the ordered csum stuff, so we don't need dip->csums */
-       if (!write && !skip_sum) {
-               dip->csums = kmalloc(sizeof(u32) * bio->bi_vcnt, GFP_NOFS);
-               if (!dip->csums) {
-                       kfree(dip);
-                       ret = -ENOMEM;
-                       goto free_ordered;
-               }
-       }
 
        dip->private = bio->bi_private;
        dip->inode = inode;
@@ -6341,132 +6453,22 @@ static ssize_t check_direct_IO(struct btrfs_root *root, int rw, struct kiocb *io
 out:
        return retval;
 }
+
 static ssize_t btrfs_direct_IO(int rw, struct kiocb *iocb,
                        const struct iovec *iov, loff_t offset,
                        unsigned long nr_segs)
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
-       struct btrfs_ordered_extent *ordered;
-       struct extent_state *cached_state = NULL;
-       u64 lockstart, lockend;
-       ssize_t ret;
-       int writing = rw & WRITE;
-       int write_bits = 0;
-       size_t count = iov_length(iov, nr_segs);
 
        if (check_direct_IO(BTRFS_I(inode)->root, rw, iocb, iov,
-                           offset, nr_segs)) {
+                           offset, nr_segs))
                return 0;
-       }
-
-       lockstart = offset;
-       lockend = offset + count - 1;
-
-       if (writing) {
-               ret = btrfs_delalloc_reserve_space(inode, count);
-               if (ret)
-                       goto out;
-       }
-
-       while (1) {
-               lock_extent_bits(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                                0, &cached_state);
-               /*
-                * We're concerned with the entire range that we're going to be
-                * doing DIO to, so we need to make sure theres no ordered
-                * extents in this range.
-                */
-               ordered = btrfs_lookup_ordered_range(inode, lockstart,
-                                                    lockend - lockstart + 1);
-
-               /*
-                * We need to make sure there are no buffered pages in this
-                * range either, we could have raced between the invalidate in
-                * generic_file_direct_write and locking the extent.  The
-                * invalidate needs to happen so that reads after a write do not
-                * get stale data.
-                */
-               if (!ordered && (!writing ||
-                   !test_range_bit(&BTRFS_I(inode)->io_tree,
-                                   lockstart, lockend, EXTENT_UPTODATE, 0,
-                                   cached_state)))
-                       break;
-
-               unlock_extent_cached(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                                    &cached_state, GFP_NOFS);
-
-               if (ordered) {
-                       btrfs_start_ordered_extent(inode, ordered, 1);
-                       btrfs_put_ordered_extent(ordered);
-               } else {
-                       /* Screw you mmap */
-                       ret = filemap_write_and_wait_range(file->f_mapping,
-                                                          lockstart,
-                                                          lockend);
-                       if (ret)
-                               goto out;
-
-                       /*
-                        * If we found a page that couldn't be invalidated just
-                        * fall back to buffered.
-                        */
-                       ret = invalidate_inode_pages2_range(file->f_mapping,
-                                       lockstart >> PAGE_CACHE_SHIFT,
-                                       lockend >> PAGE_CACHE_SHIFT);
-                       if (ret) {
-                               if (ret == -EBUSY)
-                                       ret = 0;
-                               goto out;
-                       }
-               }
-
-               cond_resched();
-       }
 
-       /*
-        * we don't use btrfs_set_extent_delalloc because we don't want
-        * the dirty or uptodate bits
-        */
-       if (writing) {
-               write_bits = EXTENT_DELALLOC | EXTENT_DO_ACCOUNTING;
-               ret = set_extent_bit(&BTRFS_I(inode)->io_tree, lockstart, lockend,
-                                    EXTENT_DELALLOC, NULL, &cached_state,
-                                    GFP_NOFS);
-               if (ret) {
-                       clear_extent_bit(&BTRFS_I(inode)->io_tree, lockstart,
-                                        lockend, EXTENT_LOCKED | write_bits,
-                                        1, 0, &cached_state, GFP_NOFS);
-                       goto out;
-               }
-       }
-
-       free_extent_state(cached_state);
-       cached_state = NULL;
-
-       ret = __blockdev_direct_IO(rw, iocb, inode,
+       return __blockdev_direct_IO(rw, iocb, inode,
                   BTRFS_I(inode)->root->fs_info->fs_devices->latest_bdev,
                   iov, offset, nr_segs, btrfs_get_blocks_direct, NULL,
                   btrfs_submit_direct, 0);
-
-       if (ret < 0 && ret != -EIOCBQUEUED) {
-               clear_extent_bit(&BTRFS_I(inode)->io_tree, offset,
-                             offset + iov_length(iov, nr_segs) - 1,
-                             EXTENT_LOCKED | write_bits, 1, 0,
-                             &cached_state, GFP_NOFS);
-       } else if (ret >= 0 && ret < iov_length(iov, nr_segs)) {
-               /*
-                * We're falling back to buffered, unlock the section we didn't
-                * do IO on.
-                */
-               clear_extent_bit(&BTRFS_I(inode)->io_tree, offset + ret,
-                             offset + iov_length(iov, nr_segs) - 1,
-                             EXTENT_LOCKED | write_bits, 1, 0,
-                             &cached_state, GFP_NOFS);
-       }
-out:
-       free_extent_state(cached_state);
-       return ret;
 }
 
 static int btrfs_fiemap(struct inode *inode, struct fiemap_extent_info *fieinfo,
index 7bb755677a220f71fd0540932c0c19565aec6a23..9df50fa8a0781ba387553297fbe442ed964e671e 100644 (file)
@@ -424,7 +424,7 @@ static noinline int create_subvol(struct btrfs_root *root,
        uuid_le_gen(&new_uuid);
        memcpy(root_item.uuid, new_uuid.b, BTRFS_UUID_SIZE);
        root_item.otime.sec = cpu_to_le64(cur_time.tv_sec);
-       root_item.otime.nsec = cpu_to_le64(cur_time.tv_nsec);
+       root_item.otime.nsec = cpu_to_le32(cur_time.tv_nsec);
        root_item.ctime = root_item.otime;
        btrfs_set_root_ctransid(&root_item, trans->transid);
        btrfs_set_root_otransid(&root_item, trans->transid);
index a44eff0748051b1627448e54f281ca04cd77c719..2a1762c660416c662d32f95060046ba2557ab903 100644 (file)
@@ -67,7 +67,7 @@ void btrfs_clear_lock_blocking_rw(struct extent_buffer *eb, int rw)
 {
        if (eb->lock_nested) {
                read_lock(&eb->lock);
-               if (&eb->lock_nested && current->pid == eb->lock_owner) {
+               if (eb->lock_nested && current->pid == eb->lock_owner) {
                        read_unlock(&eb->lock);
                        return;
                }
index bc424ae5a81a49ef15cadb0159812f80acf0221f..b65015581744a6eefb9b3ed720478673b888d336 100644 (file)
@@ -1364,8 +1364,10 @@ int btrfs_qgroup_inherit(struct btrfs_trans_handle *trans,
        spin_lock(&fs_info->qgroup_lock);
 
        dstgroup = add_qgroup_rb(fs_info, objectid);
-       if (!dstgroup)
+       if (IS_ERR(dstgroup)) {
+               ret = PTR_ERR(dstgroup);
                goto unlock;
+       }
 
        if (srcid) {
                srcgroup = find_qgroup_rb(fs_info, srcid);
index 6bb465cca20f5c68804ac3c4f78d4aa650fee96c..10d8e4d88071747651afd3a875eae0fb407c22e4 100644 (file)
@@ -544,8 +544,8 @@ void btrfs_update_root_times(struct btrfs_trans_handle *trans,
        struct timespec ct = CURRENT_TIME;
 
        spin_lock(&root->root_times_lock);
-       item->ctransid = trans->transid;
+       item->ctransid = cpu_to_le64(trans->transid);
        item->ctime.sec = cpu_to_le64(ct.tv_sec);
-       item->ctime.nsec = cpu_to_le64(ct.tv_nsec);
+       item->ctime.nsec = cpu_to_le32(ct.tv_nsec);
        spin_unlock(&root->root_times_lock);
 }
index f2eb24c477a3ca1c60ee95b51040354dd5a869ba..83d6f9f9c2209861efdec86dec9ad54d629deeb9 100644 (file)
@@ -838,7 +838,6 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
        struct btrfs_trans_handle *trans;
        struct btrfs_fs_info *fs_info = btrfs_sb(sb);
        struct btrfs_root *root = fs_info->tree_root;
-       int ret;
 
        trace_btrfs_sync_fs(wait);
 
@@ -849,11 +848,17 @@ int btrfs_sync_fs(struct super_block *sb, int wait)
 
        btrfs_wait_ordered_extents(root, 0, 0);
 
-       trans = btrfs_start_transaction(root, 0);
+       spin_lock(&fs_info->trans_lock);
+       if (!fs_info->running_transaction) {
+               spin_unlock(&fs_info->trans_lock);
+               return 0;
+       }
+       spin_unlock(&fs_info->trans_lock);
+
+       trans = btrfs_join_transaction(root);
        if (IS_ERR(trans))
                return PTR_ERR(trans);
-       ret = btrfs_commit_transaction(trans, root);
-       return ret;
+       return btrfs_commit_transaction(trans, root);
 }
 
 static int btrfs_show_options(struct seq_file *seq, struct dentry *dentry)
@@ -1530,6 +1535,8 @@ static int btrfs_show_devname(struct seq_file *m, struct dentry *root)
        while (cur_devices) {
                head = &cur_devices->devices;
                list_for_each_entry(dev, head, dev_list) {
+                       if (dev->missing)
+                               continue;
                        if (!first_dev || dev->devid < first_dev->devid)
                                first_dev = dev;
                }
index 17be3dedacbab1c47084270153ed059719984470..27c26004e050a33211674363cfd80c02c98d1063 100644 (file)
@@ -1031,6 +1031,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
 
        btrfs_i_size_write(parent_inode, parent_inode->i_size +
                                         dentry->d_name.len * 2);
+       parent_inode->i_mtime = parent_inode->i_ctime = CURRENT_TIME;
        ret = btrfs_update_inode(trans, parent_root, parent_inode);
        if (ret)
                goto abort_trans_dput;
@@ -1066,7 +1067,7 @@ static noinline int create_pending_snapshot(struct btrfs_trans_handle *trans,
        memcpy(new_root_item->parent_uuid, root->root_item.uuid,
                        BTRFS_UUID_SIZE);
        new_root_item->otime.sec = cpu_to_le64(cur_time.tv_sec);
-       new_root_item->otime.nsec = cpu_to_le64(cur_time.tv_nsec);
+       new_root_item->otime.nsec = cpu_to_le32(cur_time.tv_nsec);
        btrfs_set_root_otransid(new_root_item, trans->transid);
        memset(&new_root_item->stime, 0, sizeof(new_root_item->stime));
        memset(&new_root_item->rtime, 0, sizeof(new_root_item->rtime));
index e86ae04abe6a78e72dd86b3a813bce3107a8802e..88b969aeeb71a53128ae941e569ad19f7b1038c3 100644 (file)
@@ -227,9 +227,8 @@ loop_lock:
                cur = pending;
                pending = pending->bi_next;
                cur->bi_next = NULL;
-               atomic_dec(&fs_info->nr_async_bios);
 
-               if (atomic_read(&fs_info->nr_async_bios) < limit &&
+               if (atomic_dec_return(&fs_info->nr_async_bios) < limit &&
                    waitqueue_active(&fs_info->async_submit_wait))
                        wake_up(&fs_info->async_submit_wait);
 
@@ -569,9 +568,11 @@ static int __btrfs_close_devices(struct btrfs_fs_devices *fs_devices)
                memcpy(new_device, device, sizeof(*new_device));
 
                /* Safe because we are under uuid_mutex */
-               name = rcu_string_strdup(device->name->str, GFP_NOFS);
-               BUG_ON(device->name && !name); /* -ENOMEM */
-               rcu_assign_pointer(new_device->name, name);
+               if (device->name) {
+                       name = rcu_string_strdup(device->name->str, GFP_NOFS);
+                       BUG_ON(device->name && !name); /* -ENOMEM */
+                       rcu_assign_pointer(new_device->name, name);
+               }
                new_device->bdev = NULL;
                new_device->writeable = 0;
                new_device->in_fs_metadata = 0;
@@ -4605,28 +4606,6 @@ int btrfs_read_sys_array(struct btrfs_root *root)
        return ret;
 }
 
-struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
-                                                  u64 logical, int mirror_num)
-{
-       struct btrfs_mapping_tree *map_tree = &root->fs_info->mapping_tree;
-       int ret;
-       u64 map_length = 0;
-       struct btrfs_bio *bbio = NULL;
-       struct btrfs_device *device;
-
-       BUG_ON(mirror_num == 0);
-       ret = btrfs_map_block(map_tree, WRITE, logical, &map_length, &bbio,
-                             mirror_num);
-       if (ret) {
-               BUG_ON(bbio != NULL);
-               return NULL;
-       }
-       BUG_ON(mirror_num != bbio->mirror_num);
-       device = bbio->stripes[mirror_num - 1].dev;
-       kfree(bbio);
-       return device;
-}
-
 int btrfs_read_chunk_tree(struct btrfs_root *root)
 {
        struct btrfs_path *path;
index 5479325987b3c8af40e0760790d5365fda0efc8d..53c06af92e8da94270dab4f24906b937441d8a8f 100644 (file)
@@ -289,8 +289,6 @@ int btrfs_cancel_balance(struct btrfs_fs_info *fs_info);
 int btrfs_chunk_readonly(struct btrfs_root *root, u64 chunk_offset);
 int find_free_dev_extent(struct btrfs_device *device, u64 num_bytes,
                         u64 *start, u64 *max_avail);
-struct btrfs_device *btrfs_find_device_for_logical(struct btrfs_root *root,
-                                                  u64 logical, int mirror_num);
 void btrfs_dev_stat_print_on_error(struct btrfs_device *device);
 void btrfs_dev_stat_inc_and_print(struct btrfs_device *dev, int index);
 int btrfs_get_dev_stats(struct btrfs_root *root,
index 9f6d2e41281d69752f77d9c68772a46c855a8453..58e2e7b7737264fac2da09e2a71d451497e25e83 100644 (file)
@@ -914,7 +914,7 @@ link_dev_buffers(struct page *page, struct buffer_head *head)
 /*
  * Initialise the state of a blockdev page's buffers.
  */ 
-static void
+static sector_t
 init_page_buffers(struct page *page, struct block_device *bdev,
                        sector_t block, int size)
 {
@@ -936,33 +936,41 @@ init_page_buffers(struct page *page, struct block_device *bdev,
                block++;
                bh = bh->b_this_page;
        } while (bh != head);
+
+       /*
+        * Caller needs to validate requested block against end of device.
+        */
+       return end_block;
 }
 
 /*
  * Create the page-cache page that contains the requested block.
  *
- * This is user purely for blockdev mappings.
+ * This is used purely for blockdev mappings.
  */
-static struct page *
+static int
 grow_dev_page(struct block_device *bdev, sector_t block,
-               pgoff_t index, int size)
+               pgoff_t index, int size, int sizebits)
 {
        struct inode *inode = bdev->bd_inode;
        struct page *page;
        struct buffer_head *bh;
+       sector_t end_block;
+       int ret = 0;            /* Will call free_more_memory() */
 
        page = find_or_create_page(inode->i_mapping, index,
                (mapping_gfp_mask(inode->i_mapping) & ~__GFP_FS)|__GFP_MOVABLE);
        if (!page)
-               return NULL;
+               return ret;
 
        BUG_ON(!PageLocked(page));
 
        if (page_has_buffers(page)) {
                bh = page_buffers(page);
                if (bh->b_size == size) {
-                       init_page_buffers(page, bdev, block, size);
-                       return page;
+                       end_block = init_page_buffers(page, bdev,
+                                               index << sizebits, size);
+                       goto done;
                }
                if (!try_to_free_buffers(page))
                        goto failed;
@@ -982,14 +990,14 @@ grow_dev_page(struct block_device *bdev, sector_t block,
         */
        spin_lock(&inode->i_mapping->private_lock);
        link_dev_buffers(page, bh);
-       init_page_buffers(page, bdev, block, size);
+       end_block = init_page_buffers(page, bdev, index << sizebits, size);
        spin_unlock(&inode->i_mapping->private_lock);
-       return page;
-
+done:
+       ret = (block < end_block) ? 1 : -ENXIO;
 failed:
        unlock_page(page);
        page_cache_release(page);
-       return NULL;
+       return ret;
 }
 
 /*
@@ -999,7 +1007,6 @@ failed:
 static int
 grow_buffers(struct block_device *bdev, sector_t block, int size)
 {
-       struct page *page;
        pgoff_t index;
        int sizebits;
 
@@ -1023,22 +1030,14 @@ grow_buffers(struct block_device *bdev, sector_t block, int size)
                        bdevname(bdev, b));
                return -EIO;
        }
-       block = index << sizebits;
+
        /* Create a page with the proper size buffers.. */
-       page = grow_dev_page(bdev, block, index, size);
-       if (!page)
-               return 0;
-       unlock_page(page);
-       page_cache_release(page);
-       return 1;
+       return grow_dev_page(bdev, block, index, size, sizebits);
 }
 
 static struct buffer_head *
 __getblk_slow(struct block_device *bdev, sector_t block, int size)
 {
-       int ret;
-       struct buffer_head *bh;
-
        /* Size must be multiple of hard sectorsize */
        if (unlikely(size & (bdev_logical_block_size(bdev)-1) ||
                        (size < 512 || size > PAGE_SIZE))) {
@@ -1051,21 +1050,20 @@ __getblk_slow(struct block_device *bdev, sector_t block, int size)
                return NULL;
        }
 
-retry:
-       bh = __find_get_block(bdev, block, size);
-       if (bh)
-               return bh;
+       for (;;) {
+               struct buffer_head *bh;
+               int ret;
 
-       ret = grow_buffers(bdev, block, size);
-       if (ret == 0) {
-               free_more_memory();
-               goto retry;
-       } else if (ret > 0) {
                bh = __find_get_block(bdev, block, size);
                if (bh)
                        return bh;
+
+               ret = grow_buffers(bdev, block, size);
+               if (ret < 0)
+                       return NULL;
+               if (ret == 0)
+                       free_more_memory();
        }
-       return NULL;
 }
 
 /*
@@ -1321,10 +1319,6 @@ EXPORT_SYMBOL(__find_get_block);
  * which corresponds to the passed block_device, block and size. The
  * returned buffer has its reference count incremented.
  *
- * __getblk() cannot fail - it just keeps trying.  If you pass it an
- * illegal block number, __getblk() will happily return a buffer_head
- * which represents the non-existent block.  Very weird.
- *
  * __getblk() will lock up the machine if grow_dev_page's try_to_free_buffers()
  * attempt is failing.  FIXME, perhaps?
  */
index 7dab9c04ad524117a386c08fb21d7a886e9ca82d..53cf2aabce877ce2a8e15844ab667cf6f26a2d63 100644 (file)
@@ -328,7 +328,7 @@ cifsConvertToUTF16(__le16 *target, const char *source, int srclen,
        }
 
 ctoUTF16_out:
-       return i;
+       return j;
 }
 
 #ifdef CONFIG_CIFS_SMB2
index 074923ce593d7d53da6ae010128dffc8c080815b..f0cf934ba877d8549d8631787a4aea8da871b371 100644 (file)
@@ -1576,9 +1576,14 @@ cifs_readv_callback(struct mid_q_entry *mid)
                /* result already set, check signature */
                if (server->sec_mode &
                    (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
-                       if (cifs_verify_signature(rdata->iov, rdata->nr_iov,
-                                         server, mid->sequence_number + 1))
-                               cERROR(1, "Unexpected SMB signature");
+                       int rc = 0;
+
+                       rc = cifs_verify_signature(rdata->iov, rdata->nr_iov,
+                                                  server,
+                                                  mid->sequence_number + 1);
+                       if (rc)
+                               cERROR(1, "SMB signature verification returned "
+                                      "error = %d", rc);
                }
                /* FIXME: should this be counted toward the initiating task? */
                task_io_account_read(rdata->bytes);
index cbe709ad6663485cdcec49dbce9d1156de510c5d..781025be48bc47581c7484e8d55948914d588848 100644 (file)
@@ -356,19 +356,12 @@ cifs_create_get_file_info:
 cifs_create_set_dentry:
        if (rc != 0) {
                cFYI(1, "Create worked, get_inode_info failed rc = %d", rc);
+               CIFSSMBClose(xid, tcon, *fileHandle);
                goto out;
        }
        d_drop(direntry);
        d_add(direntry, newinode);
 
-       /* ENOENT for create?  How weird... */
-       rc = -ENOENT;
-       if (!newinode) {
-               CIFSSMBClose(xid, tcon, *fileHandle);
-               goto out;
-       }
-       rc = 0;
-
 out:
        kfree(buf);
        kfree(full_path);
index 9154192b0683e368a521ddf118961e1cdd592355..71e9ad9f59610aedef820784e558e1652973a553 100644 (file)
@@ -917,7 +917,7 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
        if (!buf) {
                mutex_unlock(&cinode->lock_mutex);
                free_xid(xid);
-               return rc;
+               return -ENOMEM;
        }
 
        for (i = 0; i < 2; i++) {
index 7354877fa3bd825519ea981b1c6208fd886dff11..cb79c7edecb0f3b2856ce8817c3515e8ad827e59 100644 (file)
@@ -124,10 +124,10 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
 {
        struct cifsInodeInfo *cifs_i = CIFS_I(inode);
        struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
-       unsigned long oldtime = cifs_i->time;
 
        cifs_revalidate_cache(inode, fattr);
 
+       spin_lock(&inode->i_lock);
        inode->i_atime = fattr->cf_atime;
        inode->i_mtime = fattr->cf_mtime;
        inode->i_ctime = fattr->cf_ctime;
@@ -148,9 +148,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
        else
                cifs_i->time = jiffies;
 
-       cFYI(1, "inode 0x%p old_time=%ld new_time=%ld", inode,
-                oldtime, cifs_i->time);
-
        cifs_i->delete_pending = fattr->cf_flags & CIFS_FATTR_DELETE_PENDING;
 
        cifs_i->server_eof = fattr->cf_eof;
@@ -158,7 +155,6 @@ cifs_fattr_to_inode(struct inode *inode, struct cifs_fattr *fattr)
         * Can't safely change the file size here if the client is writing to
         * it due to potential races.
         */
-       spin_lock(&inode->i_lock);
        if (is_size_safe_to_change(cifs_i, fattr->cf_eof)) {
                i_size_write(inode, fattr->cf_eof);
 
@@ -859,12 +855,14 @@ struct inode *cifs_root_iget(struct super_block *sb)
 
        if (rc && tcon->ipc) {
                cFYI(1, "ipc connection - fake read inode");
+               spin_lock(&inode->i_lock);
                inode->i_mode |= S_IFDIR;
                set_nlink(inode, 2);
                inode->i_op = &cifs_ipc_inode_ops;
                inode->i_fop = &simple_dir_operations;
                inode->i_uid = cifs_sb->mnt_uid;
                inode->i_gid = cifs_sb->mnt_gid;
+               spin_unlock(&inode->i_lock);
        } else if (rc) {
                iget_failed(inode);
                inode = ERR_PTR(rc);
@@ -1110,6 +1108,15 @@ undo_setattr:
        goto out_close;
 }
 
+/* copied from fs/nfs/dir.c with small changes */
+static void
+cifs_drop_nlink(struct inode *inode)
+{
+       spin_lock(&inode->i_lock);
+       if (inode->i_nlink > 0)
+               drop_nlink(inode);
+       spin_unlock(&inode->i_lock);
+}
 
 /*
  * If dentry->d_inode is null (usually meaning the cached dentry
@@ -1166,13 +1173,13 @@ retry_std_delete:
 psx_del_no_retry:
        if (!rc) {
                if (inode)
-                       drop_nlink(inode);
+                       cifs_drop_nlink(inode);
        } else if (rc == -ENOENT) {
                d_drop(dentry);
        } else if (rc == -ETXTBSY) {
                rc = cifs_rename_pending_delete(full_path, dentry, xid);
                if (rc == 0)
-                       drop_nlink(inode);
+                       cifs_drop_nlink(inode);
        } else if ((rc == -EACCES) && (dosattr == 0) && inode) {
                attrs = kzalloc(sizeof(*attrs), GFP_KERNEL);
                if (attrs == NULL) {
@@ -1241,9 +1248,10 @@ cifs_mkdir_qinfo(struct inode *inode, struct dentry *dentry, umode_t mode,
         * setting nlink not necessary except in cases where we failed to get it
         * from the server or was set bogus
         */
+       spin_lock(&dentry->d_inode->i_lock);
        if ((dentry->d_inode) && (dentry->d_inode->i_nlink < 2))
                set_nlink(dentry->d_inode, 2);
-
+       spin_unlock(&dentry->d_inode->i_lock);
        mode &= ~current_umask();
        /* must turn on setgid bit if parent dir has it */
        if (inode->i_mode & S_ISGID)
index 09e4b3ae45640e3d0c1bd8757cc6da935fca65f5..e6ce3b1128756be4496494b2623fab27fa0d165f 100644 (file)
@@ -433,7 +433,9 @@ cifs_hardlink(struct dentry *old_file, struct inode *inode,
        if (old_file->d_inode) {
                cifsInode = CIFS_I(old_file->d_inode);
                if (rc == 0) {
+                       spin_lock(&old_file->d_inode->i_lock);
                        inc_nlink(old_file->d_inode);
+                       spin_unlock(&old_file->d_inode->i_lock);
 /* BB should we make this contingent on superblock flag NOATIME? */
 /*                     old_file->d_inode->i_ctime = CURRENT_TIME;*/
                        /* parent dir timestamps will update from srv
index a4ff5d547554d174466bc48eb7c8fccb48c8f668..e4d3b99641673670b681ca41e443d3a3083359c1 100644 (file)
@@ -52,7 +52,8 @@ check_smb2_hdr(struct smb2_hdr *hdr, __u64 mid)
                        cERROR(1, "Bad protocol string signature header %x",
                                  *(unsigned int *) hdr->ProtocolId);
                if (mid != hdr->MessageId)
-                       cERROR(1, "Mids do not match");
+                       cERROR(1, "Mids do not match: %llu and %llu", mid,
+                                 hdr->MessageId);
        }
        cERROR(1, "Bad SMB detected. The Mid=%llu", hdr->MessageId);
        return 1;
@@ -107,7 +108,7 @@ smb2_check_message(char *buf, unsigned int length)
         * ie Validate the wct via smb2_struct_sizes table above
         */
 
-       if (length < 2 + sizeof(struct smb2_hdr)) {
+       if (length < sizeof(struct smb2_pdu)) {
                if ((length >= sizeof(struct smb2_hdr)) && (hdr->Status != 0)) {
                        pdu->StructureSize2 = 0;
                        /*
@@ -121,15 +122,15 @@ smb2_check_message(char *buf, unsigned int length)
                return 1;
        }
        if (len > CIFSMaxBufSize + MAX_SMB2_HDR_SIZE - 4) {
-               cERROR(1, "SMB length greater than maximum, mid=%lld", mid);
+               cERROR(1, "SMB length greater than maximum, mid=%llu", mid);
                return 1;
        }
 
        if (check_smb2_hdr(hdr, mid))
                return 1;
 
-       if (hdr->StructureSize != SMB2_HEADER_SIZE) {
-               cERROR(1, "Illegal structure size %d",
+       if (hdr->StructureSize != SMB2_HEADER_STRUCTURE_SIZE) {
+               cERROR(1, "Illegal structure size %u",
                          le16_to_cpu(hdr->StructureSize));
                return 1;
        }
@@ -161,8 +162,9 @@ smb2_check_message(char *buf, unsigned int length)
        if (4 + len != clc_len) {
                cFYI(1, "Calculated size %u length %u mismatch mid %llu",
                        clc_len, 4 + len, mid);
-               if (clc_len == 4 + len + 1) /* BB FIXME (fix samba) */
-                       return 0; /* BB workaround Samba 3 bug SessSetup rsp */
+               /* server can return one byte more */
+               if (clc_len == 4 + len + 1)
+                       return 0;
                return 1;
        }
        return 0;
index f37a1b41b402b76e9f5ce7ae155e7bd5bb3a08a3..15dc8eea82731fb8c00485d67493ab30d3a39318 100644 (file)
 
 #define SMB2_PROTO_NUMBER __constant_cpu_to_le32(0x424d53fe)
 
-#define SMB2_HEADER_SIZE __constant_le16_to_cpu(64)
-
-#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_le16_to_cpu(9)
-
 /*
  * SMB2 Header Definition
  *
@@ -99,6 +95,9 @@
  * "PDU" :  "Protocol Data Unit" (ie a network "frame")
  *
  */
+
+#define SMB2_HEADER_STRUCTURE_SIZE __constant_cpu_to_le16(64)
+
 struct smb2_hdr {
        __be32 smb2_buf_length; /* big endian on wire */
                                /* length is only two or three bytes - with
@@ -140,6 +139,9 @@ struct smb2_pdu {
  *  command code name for the struct. Note that structures must be packed.
  *
  */
+
+#define SMB2_ERROR_STRUCTURE_SIZE2 __constant_cpu_to_le16(9)
+
 struct smb2_err_rsp {
        struct smb2_hdr hdr;
        __le16 StructureSize;
index 83867ef348dfe15276d83379f12ae5c46399f7a0..d9b639b95fa8b8a5167ecf58fa3285f90ff2520f 100644 (file)
@@ -503,13 +503,16 @@ cifs_check_receive(struct mid_q_entry *mid, struct TCP_Server_Info *server,
        /* convert the length into a more usable form */
        if (server->sec_mode & (SECMODE_SIGN_REQUIRED | SECMODE_SIGN_ENABLED)) {
                struct kvec iov;
+               int rc = 0;
 
                iov.iov_base = mid->resp_buf;
                iov.iov_len = len;
                /* FIXME: add code to kill session */
-               if (cifs_verify_signature(&iov, 1, server,
-                                         mid->sequence_number + 1) != 0)
-                       cERROR(1, "Unexpected SMB signature");
+               rc = cifs_verify_signature(&iov, 1, server,
+                                          mid->sequence_number + 1);
+               if (rc)
+                       cERROR(1, "SMB signature verification returned error = "
+                              "%d", rc);
        }
 
        /* BB special case reconnect tid and uid here? */
index 8086636bf796ab328219d4a898608af1be2fdb2b..693f95bf1caeb8769517aa7046702f86b6494fa7 100644 (file)
@@ -389,7 +389,7 @@ static struct dentry *d_kill(struct dentry *dentry, struct dentry *parent)
         * Inform try_to_ascend() that we are no longer attached to the
         * dentry tree
         */
-       dentry->d_flags |= DCACHE_DISCONNECTED;
+       dentry->d_flags |= DCACHE_DENTRY_KILLED;
        if (parent)
                spin_unlock(&parent->d_lock);
        dentry_iput(dentry);
@@ -1048,7 +1048,7 @@ static struct dentry *try_to_ascend(struct dentry *old, int locked, unsigned seq
         * or deletion
         */
        if (new != old->d_parent ||
-                (old->d_flags & DCACHE_DISCONNECTED) ||
+                (old->d_flags & DCACHE_DENTRY_KILLED) ||
                 (!locked && read_seqretry(&rename_lock, seq))) {
                spin_unlock(&new->d_lock);
                new = NULL;
@@ -1134,6 +1134,8 @@ positive:
        return 1;
 
 rename_retry:
+       if (locked)
+               goto again;
        locked = 1;
        write_seqlock(&rename_lock);
        goto again;
@@ -1141,7 +1143,7 @@ rename_retry:
 EXPORT_SYMBOL(have_submounts);
 
 /*
- * Search the dentry child list for the specified parent,
+ * Search the dentry child list of the specified parent,
  * and move any unused dentries to the end of the unused
  * list for prune_dcache(). We descend to the next level
  * whenever the d_subdirs list is non-empty and continue
@@ -1236,6 +1238,8 @@ out:
 rename_retry:
        if (found)
                return found;
+       if (locked)
+               goto again;
        locked = 1;
        write_seqlock(&rename_lock);
        goto again;
@@ -3035,6 +3039,8 @@ resume:
        return;
 
 rename_retry:
+       if (locked)
+               goto again;
        locked = 1;
        write_seqlock(&rename_lock);
        goto again;
index 2340f6978d6e29e01c9b90ddaa9abd33beb0ee11..c5ca6ae5a30cc750e5a33b42ce746da6cf2f4591 100644 (file)
@@ -526,73 +526,51 @@ struct array_data {
        u32 elements;
 };
 
-static int u32_array_open(struct inode *inode, struct file *file)
-{
-       file->private_data = NULL;
-       return nonseekable_open(inode, file);
-}
-
-static size_t format_array(char *buf, size_t bufsize, const char *fmt,
-                          u32 *array, u32 array_size)
+static size_t u32_format_array(char *buf, size_t bufsize,
+                              u32 *array, int array_size)
 {
        size_t ret = 0;
-       u32 i;
 
-       for (i = 0; i < array_size; i++) {
+       while (--array_size >= 0) {
                size_t len;
+               char term = array_size ? ' ' : '\n';
 
-               len = snprintf(buf, bufsize, fmt, array[i]);
-               len++;  /* ' ' or '\n' */
+               len = snprintf(buf, bufsize, "%u%c", *array++, term);
                ret += len;
 
-               if (buf) {
-                       buf += len;
-                       bufsize -= len;
-                       buf[-1] = (i == array_size-1) ? '\n' : ' ';
-               }
+               buf += len;
+               bufsize -= len;
        }
-
-       ret++;          /* \0 */
-       if (buf)
-               *buf = '\0';
-
        return ret;
 }
 
-static char *format_array_alloc(const char *fmt, u32 *array,
-                                               u32 array_size)
+static int u32_array_open(struct inode *inode, struct file *file)
 {
-       size_t len = format_array(NULL, 0, fmt, array, array_size);
-       char *ret;
-
-       ret = kmalloc(len, GFP_KERNEL);
-       if (ret == NULL)
-               return NULL;
+       struct array_data *data = inode->i_private;
+       int size, elements = data->elements;
+       char *buf;
+
+       /*
+        * Max size:
+        *  - 10 digits + ' '/'\n' = 11 bytes per number
+        *  - terminating NUL character
+        */
+       size = elements*11;
+       buf = kmalloc(size+1, GFP_KERNEL);
+       if (!buf)
+               return -ENOMEM;
+       buf[size] = 0;
+
+       file->private_data = buf;
+       u32_format_array(buf, size, data->array, data->elements);
 
-       format_array(ret, len, fmt, array, array_size);
-       return ret;
+       return nonseekable_open(inode, file);
 }
 
 static ssize_t u32_array_read(struct file *file, char __user *buf, size_t len,
                              loff_t *ppos)
 {
-       struct inode *inode = file->f_path.dentry->d_inode;
-       struct array_data *data = inode->i_private;
-       size_t size;
-
-       if (*ppos == 0) {
-               if (file->private_data) {
-                       kfree(file->private_data);
-                       file->private_data = NULL;
-               }
-
-               file->private_data = format_array_alloc("%u", data->array,
-                                                             data->elements);
-       }
-
-       size = 0;
-       if (file->private_data)
-               size = strlen(file->private_data);
+       size_t size = strlen(file->private_data);
 
        return simple_read_from_buffer(buf, len, ppos,
                                        file->private_data, size);
index 1faf4cb56f3963d0945d8004b8640464b9e3b6fd..f86c720dba0eeea72d7ecefdefa8ad0b52886011 100644 (file)
@@ -1062,6 +1062,7 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        unsigned long user_addr;
        size_t bytes;
        struct buffer_head map_bh = { 0, };
+       struct blk_plug plug;
 
        if (rw & WRITE)
                rw = WRITE_ODIRECT;
@@ -1177,6 +1178,8 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
                                PAGE_SIZE - user_addr / PAGE_SIZE);
        }
 
+       blk_start_plug(&plug);
+
        for (seg = 0; seg < nr_segs; seg++) {
                user_addr = (unsigned long)iov[seg].iov_base;
                sdio.size += bytes = iov[seg].iov_len;
@@ -1235,6 +1238,8 @@ do_blockdev_direct_IO(int rw, struct kiocb *iocb, struct inode *inode,
        if (sdio.bio)
                dio_bio_submit(dio, &sdio);
 
+       blk_finish_plug(&plug);
+
        /*
         * It is possible that, we return short IO due to end of file.
         * In that case, we need to release all the pages we got hold on.
index 44ce5c6a541d65b7ceae1e7d67655a2e3f0f109a..d45ba4568128eb17baf60535d6dc00e663196afa 100644 (file)
@@ -275,8 +275,14 @@ out:
 
 static int ecryptfs_flush(struct file *file, fl_owner_t td)
 {
-       return file->f_mode & FMODE_WRITE
-              ? filemap_write_and_wait(file->f_mapping) : 0;
+       struct file *lower_file = ecryptfs_file_to_lower(file);
+
+       if (lower_file->f_op && lower_file->f_op->flush) {
+               filemap_write_and_wait(file->f_mapping);
+               return lower_file->f_op->flush(lower_file, td);
+       }
+
+       return 0;
 }
 
 static int ecryptfs_release(struct inode *inode, struct file *file)
index 534b129ea676500c4df149d95cb9bd5be517dc54..cc7709e7c508d81a1429ffa25bace9c7a101a832 100644 (file)
@@ -619,6 +619,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        struct dentry *lower_old_dir_dentry;
        struct dentry *lower_new_dir_dentry;
        struct dentry *trap = NULL;
+       struct inode *target_inode;
 
        lower_old_dentry = ecryptfs_dentry_to_lower(old_dentry);
        lower_new_dentry = ecryptfs_dentry_to_lower(new_dentry);
@@ -626,6 +627,7 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
        dget(lower_new_dentry);
        lower_old_dir_dentry = dget_parent(lower_old_dentry);
        lower_new_dir_dentry = dget_parent(lower_new_dentry);
+       target_inode = new_dentry->d_inode;
        trap = lock_rename(lower_old_dir_dentry, lower_new_dir_dentry);
        /* source should not be ancestor of target */
        if (trap == lower_old_dentry) {
@@ -641,6 +643,9 @@ ecryptfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                        lower_new_dir_dentry->d_inode, lower_new_dentry);
        if (rc)
                goto out_lock;
+       if (target_inode)
+               fsstack_copy_attr_all(target_inode,
+                                     ecryptfs_inode_to_lower(target_inode));
        fsstack_copy_attr_all(new_dir, lower_new_dir_dentry->d_inode);
        if (new_dir != old_dir)
                fsstack_copy_attr_all(old_dir, lower_old_dir_dentry->d_inode);
index 2768138eefeef85707f9ee29652532b25d50dfcb..9b627c15010a3af35e1f2ec85ccafc2b18d97d44 100644 (file)
@@ -162,6 +162,7 @@ void ecryptfs_put_lower_file(struct inode *inode)
        inode_info = ecryptfs_inode_to_private(inode);
        if (atomic_dec_and_mutex_lock(&inode_info->lower_file_count,
                                      &inode_info->lower_file_mutex)) {
+               filemap_write_and_wait(inode->i_mapping);
                fput(inode_info->lower_file);
                inode_info->lower_file = NULL;
                mutex_unlock(&inode_info->lower_file_mutex);
index a07597307fd1cd221b20997d9e0268caa6bc9138..ff574b4e345efd09a7c2e6f2511213210fbcc92d 100644 (file)
@@ -3072,6 +3072,8 @@ static int ext3_do_update_inode(handle_t *handle,
        struct ext3_inode_info *ei = EXT3_I(inode);
        struct buffer_head *bh = iloc->bh;
        int err = 0, rc, block;
+       int need_datasync = 0;
+       __le32 disksize;
        uid_t i_uid;
        gid_t i_gid;
 
@@ -3113,7 +3115,11 @@ again:
                raw_inode->i_gid_high = 0;
        }
        raw_inode->i_links_count = cpu_to_le16(inode->i_nlink);
-       raw_inode->i_size = cpu_to_le32(ei->i_disksize);
+       disksize = cpu_to_le32(ei->i_disksize);
+       if (disksize != raw_inode->i_size) {
+               need_datasync = 1;
+               raw_inode->i_size = disksize;
+       }
        raw_inode->i_atime = cpu_to_le32(inode->i_atime.tv_sec);
        raw_inode->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec);
        raw_inode->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec);
@@ -3129,8 +3135,11 @@ again:
        if (!S_ISREG(inode->i_mode)) {
                raw_inode->i_dir_acl = cpu_to_le32(ei->i_dir_acl);
        } else {
-               raw_inode->i_size_high =
-                       cpu_to_le32(ei->i_disksize >> 32);
+               disksize = cpu_to_le32(ei->i_disksize >> 32);
+               if (disksize != raw_inode->i_size_high) {
+                       raw_inode->i_size_high = disksize;
+                       need_datasync = 1;
+               }
                if (ei->i_disksize > 0x7fffffffULL) {
                        struct super_block *sb = inode->i_sb;
                        if (!EXT3_HAS_RO_COMPAT_FEATURE(sb,
@@ -3183,6 +3192,8 @@ again:
        ext3_clear_inode_state(inode, EXT3_STATE_NEW);
 
        atomic_set(&ei->i_sync_tid, handle->h_transaction->t_tid);
+       if (need_datasync)
+               atomic_set(&ei->i_datasync_tid, handle->h_transaction->t_tid);
 out_brelse:
        brelse (bh);
        ext3_std_error(inode->i_sb, err);
index 03ff5b1eba93ec21e11d9ca31f9c8b3f22e65d36..75a20c092dd43b573c4f24788d067b3e6b1bfef0 100644 (file)
@@ -117,7 +117,7 @@ static ssize_t fuse_conn_max_background_write(struct file *file,
                                              const char __user *buf,
                                              size_t count, loff_t *ppos)
 {
-       unsigned val;
+       unsigned uninitialized_var(val);
        ssize_t ret;
 
        ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
@@ -154,7 +154,7 @@ static ssize_t fuse_conn_congestion_threshold_write(struct file *file,
                                                    const char __user *buf,
                                                    size_t count, loff_t *ppos)
 {
-       unsigned val;
+       unsigned uninitialized_var(val);
        ssize_t ret;
 
        ret = fuse_conn_limit_write(file, buf, count, ppos, &val,
index 3426521f3205cce09a98b8a1bd01ffe9e44f84c0..ee8d55042298272f6ac6c76982f4ecd5efb745ca 100644 (file)
@@ -396,7 +396,7 @@ err_device:
 err_region:
        unregister_chrdev_region(devt, 1);
 err:
-       fc->conn_error = 1;
+       fuse_conn_kill(fc);
        goto out;
 }
 
@@ -532,8 +532,6 @@ static int cuse_channel_release(struct inode *inode, struct file *file)
                cdev_del(cc->cdev);
        }
 
-       /* kill connection and shutdown channel */
-       fuse_conn_kill(&cc->fc);
        rc = fuse_dev_release(inode, file);     /* puts the base reference */
 
        return rc;
index 7df2b5e8fbe187af6599504f935d1ed463a40c64..f4246cfc8d876db6ac39a6ef058b144c73d503af 100644 (file)
@@ -1576,6 +1576,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
                req->pages[req->num_pages] = page;
                req->num_pages++;
 
+               offset = 0;
                num -= this_num;
                total_len += this_num;
                index++;
index ce0a2838ccd097a5392d469fc0650d2e7b0d7e8d..fca222dabe3ccc4a791e894d325bdc4e4f78b7f3 100644 (file)
@@ -367,11 +367,6 @@ void fuse_conn_kill(struct fuse_conn *fc)
        wake_up_all(&fc->waitq);
        wake_up_all(&fc->blocked_waitq);
        wake_up_all(&fc->reserved_req_waitq);
-       mutex_lock(&fuse_mutex);
-       list_del(&fc->entry);
-       fuse_ctl_remove_conn(fc);
-       mutex_unlock(&fuse_mutex);
-       fuse_bdi_destroy(fc);
 }
 EXPORT_SYMBOL_GPL(fuse_conn_kill);
 
@@ -380,7 +375,14 @@ static void fuse_put_super(struct super_block *sb)
        struct fuse_conn *fc = get_fuse_conn_super(sb);
 
        fuse_send_destroy(fc);
+
        fuse_conn_kill(fc);
+       mutex_lock(&fuse_mutex);
+       list_del(&fc->entry);
+       fuse_ctl_remove_conn(fc);
+       mutex_unlock(&fuse_mutex);
+       fuse_bdi_destroy(fc);
+
        fuse_conn_put(fc);
 }
 
index d1d791ef38de2188852551254a63f974a605feff..382000ffac1f7e892163665a27982e587b9d83e7 100644 (file)
@@ -322,6 +322,29 @@ static long gfs2_ioctl(struct file *filp, unsigned int cmd, unsigned long arg)
        return -ENOTTY;
 }
 
+/**
+ * gfs2_size_hint - Give a hint to the size of a write request
+ * @file: The struct file
+ * @offset: The file offset of the write
+ * @size: The length of the write
+ *
+ * When we are about to do a write, this function records the total
+ * write size in order to provide a suitable hint to the lower layers
+ * about how many blocks will be required.
+ *
+ */
+
+static void gfs2_size_hint(struct file *filep, loff_t offset, size_t size)
+{
+       struct inode *inode = filep->f_dentry->d_inode;
+       struct gfs2_sbd *sdp = GFS2_SB(inode);
+       struct gfs2_inode *ip = GFS2_I(inode);
+       size_t blks = (size + sdp->sd_sb.sb_bsize - 1) >> sdp->sd_sb.sb_bsize_shift;
+       int hint = min_t(size_t, INT_MAX, blks);
+
+       atomic_set(&ip->i_res->rs_sizehint, hint);
+}
+
 /**
  * gfs2_allocate_page_backing - Use bmap to allocate blocks
  * @page: The (locked) page to allocate backing for
@@ -382,8 +405,7 @@ static int gfs2_page_mkwrite(struct vm_area_struct *vma, struct vm_fault *vmf)
        if (ret)
                return ret;
 
-       atomic_set(&ip->i_res->rs_sizehint,
-                  PAGE_CACHE_SIZE >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(vma->vm_file, pos, PAGE_CACHE_SIZE);
 
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
@@ -663,7 +685,8 @@ static ssize_t gfs2_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
        if (ret)
                return ret;
 
-       atomic_set(&ip->i_res->rs_sizehint, writesize >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(file, pos, writesize);
+
        if (file->f_flags & O_APPEND) {
                struct gfs2_holder gh;
 
@@ -789,7 +812,7 @@ static long gfs2_fallocate(struct file *file, int mode, loff_t offset,
        if (unlikely(error))
                goto out_uninit;
 
-       atomic_set(&ip->i_res->rs_sizehint, len >> sdp->sd_sb.sb_bsize_shift);
+       gfs2_size_hint(file, offset, len);
 
        while (len > 0) {
                if (len < bytes)
index 4ce22e54730806e02ed0ba70f7e7fc847d513142..753af3d86bbcecaa76f5c01cb54d81b0006c4fac 100644 (file)
@@ -1722,7 +1722,9 @@ static int gfs2_setxattr(struct dentry *dentry, const char *name,
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = generic_setxattr(dentry, name, data, size, flags);
+               ret = gfs2_rs_alloc(ip);
+               if (ret == 0)
+                       ret = generic_setxattr(dentry, name, data, size, flags);
                gfs2_glock_dq(&gh);
        }
        gfs2_holder_uninit(&gh);
@@ -1757,7 +1759,9 @@ static int gfs2_removexattr(struct dentry *dentry, const char *name)
        gfs2_holder_init(ip->i_gl, LM_ST_EXCLUSIVE, 0, &gh);
        ret = gfs2_glock_nq(&gh);
        if (ret == 0) {
-               ret = generic_removexattr(dentry, name);
+               ret = gfs2_rs_alloc(ip);
+               if (ret == 0)
+                       ret = generic_removexattr(dentry, name);
                gfs2_glock_dq(&gh);
        }
        gfs2_holder_uninit(&gh);
index 4d34887a601d966660549b0d0a27517353c1ed5e..c9ed814eeb6f9652eaa927e2ab13fc42c906da14 100644 (file)
@@ -1961,7 +1961,7 @@ static void gfs2_rgrp_error(struct gfs2_rgrpd *rgd)
  * @dinode: 1 if this block is a dinode block, otherwise data block
  * @nblocks: desired extent length
  *
- * Lay claim to previously allocated block reservation blocks.
+ * Lay claim to previously reserved blocks.
  * Returns: Starting block number of the blocks claimed.
  * Sets *nblocks to the actual extent length allocated.
  */
@@ -1970,19 +1970,17 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,
 {
        struct gfs2_blkreserv *rs = ip->i_res;
        struct gfs2_rgrpd *rgd = rs->rs_rgd;
-       struct gfs2_sbd *sdp = GFS2_SB(&ip->i_inode);
        struct gfs2_bitmap *bi;
        u64 start_block = gfs2_rs_startblk(rs);
        const unsigned int elen = *nblocks;
 
-       /*BUG_ON(!gfs2_glock_is_locked_by_me(ip->i_gl));*/
-       gfs2_assert_withdraw(sdp, rgd);
-       /*BUG_ON(!gfs2_glock_is_locked_by_me(rgd->rd_gl));*/
        bi = rs->rs_bi;
        gfs2_trans_add_bh(rgd->rd_gl, bi->bi_bh, 1);
 
        for (*nblocks = 0; *nblocks < elen && rs->rs_free; (*nblocks)++) {
-               /* Make sure the bitmap hasn't changed */
+               if (gfs2_testbit(rgd, bi->bi_bh->b_data + bi->bi_offset,
+                                bi->bi_len, rs->rs_biblk) != GFS2_BLKST_FREE)
+                       break;
                gfs2_setbit(rgd, bi->bi_clone, bi, rs->rs_biblk,
                            dinode ? GFS2_BLKST_DINODE : GFS2_BLKST_USED);
                rs->rs_biblk++;
@@ -1991,20 +1989,12 @@ static u64 claim_reserved_blks(struct gfs2_inode *ip, bool dinode,
                BUG_ON(!rgd->rd_reserved);
                rgd->rd_reserved--;
                dinode = false;
-               trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM);
        }
 
-       if (!rs->rs_free) {
-               struct gfs2_rgrpd *rgd = ip->i_res->rs_rgd;
-
+       trace_gfs2_rs(ip, rs, TRACE_RS_CLAIM);
+       if (!rs->rs_free || *nblocks != elen)
                gfs2_rs_deltree(rs);
-               /* -nblocks because we haven't returned to do the math yet.
-                  I'm doing the math backwards to prevent negative numbers,
-                  but think of it as:
-                  if (unclaimed_blocks(rgd) - *nblocks >= RGRP_RSRV_MINBLKS */
-               if (unclaimed_blocks(rgd) >= RGRP_RSRV_MINBLKS + *nblocks)
-                       rg_mblk_search(rgd, ip);
-       }
+
        return start_block;
 }
 
@@ -2037,34 +2027,34 @@ int gfs2_alloc_blocks(struct gfs2_inode *ip, u64 *bn, unsigned int *nblocks,
        if (ip->i_res->rs_requested == 0)
                return -ECANCELED;
 
-       /* Check if we have a multi-block reservation, and if so, claim the
-          next free block from it. */
+       /* If we have a reservation, claim blocks from it. */
        if (gfs2_rs_active(ip->i_res)) {
                BUG_ON(!ip->i_res->rs_free);
                rgd = ip->i_res->rs_rgd;
                block = claim_reserved_blks(ip, dinode, nblocks);
-       } else {
-               rgd = ip->i_rgd;
+               if (*nblocks)
+                       goto found_blocks;
+       }
 
-               if (!dinode && rgrp_contains_block(rgd, ip->i_goal))
-                       goal = ip->i_goal - rgd->rd_data0;
-               else
-                       goal = rgd->rd_last_alloc;
-
-               blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi);
-
-               /* Since all blocks are reserved in advance, this shouldn't
-                  happen */
-               if (blk == BFITNOENT) {
-                       printk(KERN_WARNING "BFITNOENT, nblocks=%u\n",
-                              *nblocks);
-                       printk(KERN_WARNING "FULL=%d\n",
-                              test_bit(GBF_FULL, &rgd->rd_bits->bi_flags));
-                       goto rgrp_error;
-               }
+       rgd = ip->i_rgd;
 
-               block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks);
+       if (!dinode && rgrp_contains_block(rgd, ip->i_goal))
+               goal = ip->i_goal - rgd->rd_data0;
+       else
+               goal = rgd->rd_last_alloc;
+
+       blk = rgblk_search(rgd, goal, GFS2_BLKST_FREE, &bi);
+
+       /* Since all blocks are reserved in advance, this shouldn't happen */
+       if (blk == BFITNOENT) {
+               printk(KERN_WARNING "BFITNOENT, nblocks=%u\n", *nblocks);
+               printk(KERN_WARNING "FULL=%d\n",
+                      test_bit(GBF_FULL, &rgd->rd_bits->bi_flags));
+               goto rgrp_error;
        }
+
+       block = gfs2_alloc_extent(rgd, bi, blk, dinode, nblocks);
+found_blocks:
        ndata = *nblocks;
        if (dinode)
                ndata--;
index 09357508ec9ae5aebbac1e2ccbd44d42087bfd4a..a2862339323b2a5f1e08dd7e25a779e1b683b828 100644 (file)
@@ -1113,6 +1113,11 @@ static void mark_journal_empty(journal_t *journal)
 
        BUG_ON(!mutex_is_locked(&journal->j_checkpoint_mutex));
        spin_lock(&journal->j_state_lock);
+       /* Is it already empty? */
+       if (sb->s_start == 0) {
+               spin_unlock(&journal->j_state_lock);
+               return;
+       }
        jbd_debug(1, "JBD: Marking journal as empty (seq %d)\n",
                  journal->j_tail_sequence);
 
index fb1a2bedbe9789a8fcca5618b4637d70b25fb8ab..8d80c990dffdfc34b9f0168c39d208b99018c01e 100644 (file)
@@ -289,7 +289,6 @@ static void nlmsvc_free_block(struct kref *kref)
        dprintk("lockd: freeing block %p...\n", block);
 
        /* Remove block from file's list of blocks */
-       mutex_lock(&file->f_mutex);
        list_del_init(&block->b_flist);
        mutex_unlock(&file->f_mutex);
 
@@ -303,7 +302,7 @@ static void nlmsvc_free_block(struct kref *kref)
 static void nlmsvc_release_block(struct nlm_block *block)
 {
        if (block != NULL)
-               kref_put(&block->b_count, nlmsvc_free_block);
+               kref_put_mutex(&block->b_count, nlmsvc_free_block, &block->b_file->f_mutex);
 }
 
 /*
index df0de27c273349c22ee6b8770b589663801c68f5..e784a217b50067919ad3ebffe559b3552b58a9bc 100644 (file)
@@ -26,6 +26,7 @@ static int sync_request(struct page *page, struct block_device *bdev, int rw)
        struct completion complete;
 
        bio_init(&bio);
+       bio.bi_max_vecs = 1;
        bio.bi_io_vec = &bio_vec;
        bio_vec.bv_page = page;
        bio_vec.bv_len = PAGE_SIZE;
@@ -95,12 +96,11 @@ static int __bdev_writeseg(struct super_block *sb, u64 ofs, pgoff_t index,
        struct address_space *mapping = super->s_mapping_inode->i_mapping;
        struct bio *bio;
        struct page *page;
-       struct request_queue *q = bdev_get_queue(sb->s_bdev);
-       unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+       unsigned int max_pages;
        int i;
 
-       if (max_pages > BIO_MAX_PAGES)
-               max_pages = BIO_MAX_PAGES;
+       max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
        bio = bio_alloc(GFP_NOFS, max_pages);
        BUG_ON(!bio);
 
@@ -190,12 +190,11 @@ static int do_erase(struct super_block *sb, u64 ofs, pgoff_t index,
 {
        struct logfs_super *super = logfs_super(sb);
        struct bio *bio;
-       struct request_queue *q = bdev_get_queue(sb->s_bdev);
-       unsigned int max_pages = queue_max_hw_sectors(q) >> (PAGE_SHIFT - 9);
+       unsigned int max_pages;
        int i;
 
-       if (max_pages > BIO_MAX_PAGES)
-               max_pages = BIO_MAX_PAGES;
+       max_pages = min(nr_pages, (size_t) bio_get_nr_vecs(super->s_bdev));
+
        bio = bio_alloc(GFP_NOFS, max_pages);
        BUG_ON(!bio);
 
index a422f42238b250764011fa421d24a1a0858dd153..6984562738d36bc4142a3e0556730ae9e3bf3a57 100644 (file)
@@ -156,10 +156,26 @@ static void __logfs_destroy_inode(struct inode *inode)
        call_rcu(&inode->i_rcu, logfs_i_callback);
 }
 
+static void __logfs_destroy_meta_inode(struct inode *inode)
+{
+       struct logfs_inode *li = logfs_inode(inode);
+       BUG_ON(li->li_block);
+       call_rcu(&inode->i_rcu, logfs_i_callback);
+}
+
 static void logfs_destroy_inode(struct inode *inode)
 {
        struct logfs_inode *li = logfs_inode(inode);
 
+       if (inode->i_ino < LOGFS_RESERVED_INOS) {
+               /*
+                * The reserved inodes are never destroyed unless we are in
+                * unmont path.
+                */
+               __logfs_destroy_meta_inode(inode);
+               return;
+       }
+
        BUG_ON(list_empty(&li->li_freeing_list));
        spin_lock(&logfs_inode_lock);
        li->li_refcount--;
@@ -373,8 +389,8 @@ static void logfs_put_super(struct super_block *sb)
 {
        struct logfs_super *super = logfs_super(sb);
        /* kill the meta-inodes */
-       iput(super->s_master_inode);
        iput(super->s_segfile_inode);
+       iput(super->s_master_inode);
        iput(super->s_mapping_inode);
 }
 
index 1e1c369df22bb085f62519b1100eb300053aaae8..2a09b8d73989539aedfe205fafd7f856f1122c7c 100644 (file)
@@ -565,7 +565,7 @@ static void write_wbuf(struct super_block *sb, struct logfs_area *area,
        index = ofs >> PAGE_SHIFT;
        page_ofs = ofs & (PAGE_SIZE - 1);
 
-       page = find_lock_page(mapping, index);
+       page = find_or_create_page(mapping, index, GFP_NOFS);
        BUG_ON(!page);
        memcpy(wbuf, page_address(page) + page_ofs, super->s_writesize);
        unlock_page(page);
index f1cb512c5019dacf057391ed857a9697f0b98422..5be0abef603d4f82af9e59aaca639118e280476b 100644 (file)
@@ -2189,7 +2189,6 @@ void logfs_evict_inode(struct inode *inode)
                return;
        }
 
-       BUG_ON(inode->i_ino < LOGFS_RESERVED_INOS);
        page = inode_to_page(inode);
        BUG_ON(!page); /* FIXME: Use emergency page */
        logfs_put_write_page(page);
index e28d090c98d6bbb2986d40fd4ae57e795cf7415c..038da0991794a39962fac3d4ef7ed5b18008c6f9 100644 (file)
@@ -886,7 +886,7 @@ static struct logfs_area *alloc_area(struct super_block *sb)
 
 static void map_invalidatepage(struct page *page, unsigned long l)
 {
-       BUG();
+       return;
 }
 
 static int map_releasepage(struct page *page, gfp_t g)
index 4d31f73e2561d4d0e19d85becc0223dda27b4710..7bdf7907413f0ea5f3c9e9c2de6b4002381e2064 100644 (file)
@@ -1886,8 +1886,14 @@ static int do_add_mount(struct mount *newmnt, struct path *path, int mnt_flags)
                return err;
 
        err = -EINVAL;
-       if (!(mnt_flags & MNT_SHRINKABLE) && !check_mnt(real_mount(path->mnt)))
-               goto unlock;
+       if (unlikely(!check_mnt(real_mount(path->mnt)))) {
+               /* that's acceptable only for automounts done in private ns */
+               if (!(mnt_flags & MNT_SHRINKABLE))
+                       goto unlock;
+               /* ... and for those we'd better have mountpoint still alive */
+               if (!real_mount(path->mnt)->mnt_ns)
+                       goto unlock;
+       }
 
        /* Refuse the same filesystem on the same mount point */
        err = -EBUSY;
index 75d6d0a3d32e2685bbd43f791b1f32775c87ce59..6a7fcab7ecb3115c7630573c17f4d8285a418591 100644 (file)
@@ -287,10 +287,12 @@ nfs_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        struct inode *inode = file->f_path.dentry->d_inode;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret != 0)
+               goto out;
        mutex_lock(&inode->i_mutex);
        ret = nfs_file_fsync_commit(file, start, end, datasync);
        mutex_unlock(&inode->i_mutex);
-
+out:
        return ret;
 }
 
index c6e895f0fbf36eee681a5cb5d8e4a92bfd8c0d35..9b47610338f59f03f6b4fdc0280d6aa61c266d4f 100644 (file)
@@ -154,7 +154,7 @@ static void nfs_zap_caches_locked(struct inode *inode)
        nfsi->attrtimeo = NFS_MINATTRTIMEO(inode);
        nfsi->attrtimeo_timestamp = jiffies;
 
-       memset(NFS_COOKIEVERF(inode), 0, sizeof(NFS_COOKIEVERF(inode)));
+       memset(NFS_I(inode)->cookieverf, 0, sizeof(NFS_I(inode)->cookieverf));
        if (S_ISREG(mode) || S_ISDIR(mode) || S_ISLNK(mode))
                nfsi->cache_validity |= NFS_INO_INVALID_ATTR|NFS_INO_INVALID_DATA|NFS_INO_INVALID_ACCESS|NFS_INO_INVALID_ACL|NFS_INO_REVAL_PAGECACHE;
        else
index d6b3b5f2d779acd1ce7e0324e8c52e388c7a273a..69322096c32569d4674517f7121e4fc272206ba8 100644 (file)
@@ -643,7 +643,7 @@ nfs3_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                  u64 cookie, struct page **pages, unsigned int count, int plus)
 {
        struct inode            *dir = dentry->d_inode;
-       __be32                  *verf = NFS_COOKIEVERF(dir);
+       __be32                  *verf = NFS_I(dir)->cookieverf;
        struct nfs3_readdirargs arg = {
                .fh             = NFS_FH(dir),
                .cookie         = cookie,
index acb65e7887f8437b8aac391255f4be1218524a27..eb5eb8eef4d34db3c7bafe3c84c1db0bf43e8974 100644 (file)
@@ -96,13 +96,15 @@ nfs4_file_fsync(struct file *file, loff_t start, loff_t end, int datasync)
        struct inode *inode = file->f_path.dentry->d_inode;
 
        ret = filemap_write_and_wait_range(inode->i_mapping, start, end);
+       if (ret != 0)
+               goto out;
        mutex_lock(&inode->i_mutex);
        ret = nfs_file_fsync_commit(file, start, end, datasync);
        if (!ret && !datasync)
                /* application has asked for meta-data sync */
                ret = pnfs_layoutcommit_inode(inode, true);
        mutex_unlock(&inode->i_mutex);
-
+out:
        return ret;
 }
 
index 635274140b180287668dbaa7540bd84852051181..1e50326d00ddd1f7ef8931470bc1cd0ad32b4015 100644 (file)
@@ -3215,11 +3215,11 @@ static int _nfs4_proc_readdir(struct dentry *dentry, struct rpc_cred *cred,
                        dentry->d_parent->d_name.name,
                        dentry->d_name.name,
                        (unsigned long long)cookie);
-       nfs4_setup_readdir(cookie, NFS_COOKIEVERF(dir), dentry, &args);
+       nfs4_setup_readdir(cookie, NFS_I(dir)->cookieverf, dentry, &args);
        res.pgbase = args.pgbase;
        status = nfs4_call_sync(NFS_SERVER(dir)->client, NFS_SERVER(dir), &msg, &args.seq_args, &res.seq_res, 0);
        if (status >= 0) {
-               memcpy(NFS_COOKIEVERF(dir), res.verifier.data, NFS4_VERIFIER_SIZE);
+               memcpy(NFS_I(dir)->cookieverf, res.verifier.data, NFS4_VERIFIER_SIZE);
                status += args.pgbase;
        }
 
@@ -3653,11 +3653,11 @@ static inline int nfs4_server_supports_acls(struct nfs_server *server)
                && (server->acl_bitmask & ACL4_SUPPORT_DENY_ACL);
 }
 
-/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_CACHE_SIZE, and that
- * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_CACHE_SIZE) bytes on
+/* Assuming that XATTR_SIZE_MAX is a multiple of PAGE_SIZE, and that
+ * it's OK to put sizeof(void) * (XATTR_SIZE_MAX/PAGE_SIZE) bytes on
  * the stack.
  */
-#define NFS4ACL_MAXPAGES (XATTR_SIZE_MAX >> PAGE_CACHE_SHIFT)
+#define NFS4ACL_MAXPAGES DIV_ROUND_UP(XATTR_SIZE_MAX, PAGE_SIZE)
 
 static int buf_to_pages_noslab(const void *buf, size_t buflen,
                struct page **pages, unsigned int *pgbase)
@@ -3668,7 +3668,7 @@ static int buf_to_pages_noslab(const void *buf, size_t buflen,
        spages = pages;
 
        do {
-               len = min_t(size_t, PAGE_CACHE_SIZE, buflen);
+               len = min_t(size_t, PAGE_SIZE, buflen);
                newpage = alloc_page(GFP_KERNEL);
 
                if (newpage == NULL)
@@ -3739,7 +3739,7 @@ static void nfs4_write_cached_acl(struct inode *inode, struct page **pages, size
        struct nfs4_cached_acl *acl;
        size_t buflen = sizeof(*acl) + acl_len;
 
-       if (pages && buflen <= PAGE_SIZE) {
+       if (buflen <= PAGE_SIZE) {
                acl = kmalloc(buflen, GFP_KERNEL);
                if (acl == NULL)
                        goto out;
@@ -3782,17 +3782,15 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
                .rpc_argp = &args,
                .rpc_resp = &res,
        };
-       int ret = -ENOMEM, npages, i;
-       size_t acl_len = 0;
+       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
+       int ret = -ENOMEM, i;
 
-       npages = (buflen + PAGE_SIZE - 1) >> PAGE_SHIFT;
        /* As long as we're doing a round trip to the server anyway,
         * let's be prepared for a page of acl data. */
        if (npages == 0)
                npages = 1;
-
-       /* Add an extra page to handle the bitmap returned */
-       npages++;
+       if (npages > ARRAY_SIZE(pages))
+               return -ERANGE;
 
        for (i = 0; i < npages; i++) {
                pages[i] = alloc_page(GFP_KERNEL);
@@ -3808,11 +3806,6 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        args.acl_len = npages * PAGE_SIZE;
        args.acl_pgbase = 0;
 
-       /* Let decode_getfacl know not to fail if the ACL data is larger than
-        * the page we send as a guess */
-       if (buf == NULL)
-               res.acl_flags |= NFS4_ACL_LEN_REQUEST;
-
        dprintk("%s  buf %p buflen %zu npages %d args.acl_len %zu\n",
                __func__, buf, buflen, npages, args.acl_len);
        ret = nfs4_call_sync(NFS_SERVER(inode)->client, NFS_SERVER(inode),
@@ -3820,20 +3813,19 @@ static ssize_t __nfs4_get_acl_uncached(struct inode *inode, void *buf, size_t bu
        if (ret)
                goto out_free;
 
-       acl_len = res.acl_len;
-       if (acl_len > args.acl_len)
-               nfs4_write_cached_acl(inode, NULL, 0, acl_len);
-       else
-               nfs4_write_cached_acl(inode, pages, res.acl_data_offset,
-                                     acl_len);
-       if (buf) {
+       /* Handle the case where the passed-in buffer is too short */
+       if (res.acl_flags & NFS4_ACL_TRUNC) {
+               /* Did the user only issue a request for the acl length? */
+               if (buf == NULL)
+                       goto out_ok;
                ret = -ERANGE;
-               if (acl_len > buflen)
-                       goto out_free;
-               _copy_from_pages(buf, pages, res.acl_data_offset,
-                               acl_len);
+               goto out_free;
        }
-       ret = acl_len;
+       nfs4_write_cached_acl(inode, pages, res.acl_data_offset, res.acl_len);
+       if (buf)
+               _copy_from_pages(buf, pages, res.acl_data_offset, res.acl_len);
+out_ok:
+       ret = res.acl_len;
 out_free:
        for (i = 0; i < npages; i++)
                if (pages[i])
@@ -3891,10 +3883,13 @@ static int __nfs4_proc_set_acl(struct inode *inode, const void *buf, size_t bufl
                .rpc_argp       = &arg,
                .rpc_resp       = &res,
        };
+       unsigned int npages = DIV_ROUND_UP(buflen, PAGE_SIZE);
        int ret, i;
 
        if (!nfs4_server_supports_acls(server))
                return -EOPNOTSUPP;
+       if (npages > ARRAY_SIZE(pages))
+               return -ERANGE;
        i = buf_to_pages_noslab(buf, buflen, arg.acl_pages, &arg.acl_pgbase);
        if (i < 0)
                return i;
index 1bfbd67c556d753a21f046c87edc3c9b07b0b8f0..8dba6bd485578695fb791f8aa548bc8ac99b4391 100644 (file)
@@ -5072,18 +5072,14 @@ static int decode_getacl(struct xdr_stream *xdr, struct rpc_rqst *req,
                 * are stored with the acl data to handle the problem of
                 * variable length bitmaps.*/
                res->acl_data_offset = xdr_stream_pos(xdr) - pg_offset;
-
-               /* We ignore &savep and don't do consistency checks on
-                * the attr length.  Let userspace figure it out.... */
                res->acl_len = attrlen;
-               if (attrlen > (xdr->nwords << 2)) {
-                       if (res->acl_flags & NFS4_ACL_LEN_REQUEST) {
-                               /* getxattr interface called with a NULL buf */
-                               goto out;
-                       }
+
+               /* Check for receive buffer overflow */
+               if (res->acl_len > (xdr->nwords << 2) ||
+                   res->acl_len + res->acl_data_offset > xdr->buf->page_len) {
+                       res->acl_flags |= NFS4_ACL_TRUNC;
                        dprintk("NFS: acl reply: attrlen %u > page_len %u\n",
                                        attrlen, xdr->nwords << 2);
-                       return -EINVAL;
                }
        } else
                status = -EOPNOTSUPP;
@@ -6229,7 +6225,8 @@ static int nfs4_xdr_dec_open(struct rpc_rqst *rqstp, struct xdr_stream *xdr,
        status = decode_open(xdr, res);
        if (status)
                goto out;
-       if (decode_getfh(xdr, &res->fh) != 0)
+       status = decode_getfh(xdr, &res->fh);
+       if (status)
                goto out;
        decode_getfattr(xdr, res->f_attr, res->server);
 out:
index 239aff7338eb89ee8c0d4080694178317d84929e..b8eda700584bfbd25086d898a21b3fd03959030d 100644 (file)
@@ -1867,6 +1867,7 @@ static int nfs23_validate_mount_data(void *options,
 
                memcpy(sap, &data->addr, sizeof(data->addr));
                args->nfs_server.addrlen = sizeof(data->addr);
+               args->nfs_server.port = ntohs(data->addr.sin_port);
                if (!nfs_verify_server_address(sap))
                        goto out_no_address;
 
@@ -2564,6 +2565,7 @@ static int nfs4_validate_mount_data(void *options,
                        return -EFAULT;
                if (!nfs_verify_server_address(sap))
                        goto out_no_address;
+               args->nfs_server.port = ntohs(((struct sockaddr_in *)sap)->sin_port);
 
                if (data->auth_flavourlen) {
                        if (data->auth_flavourlen > 1)
index cbaf4f8bb7b712be7e92db2a7bf102c1f8c2dc6f..4c7bd35b187687915ab4826877dc62aecca707e3 100644 (file)
@@ -651,12 +651,12 @@ static int setup_callback_client(struct nfs4_client *clp, struct nfs4_cb_conn *c
 
        if (clp->cl_minorversion == 0) {
                if (!clp->cl_cred.cr_principal &&
-                               (clp->cl_flavor >= RPC_AUTH_GSS_KRB5))
+                               (clp->cl_cred.cr_flavor >= RPC_AUTH_GSS_KRB5))
                        return -EINVAL;
                args.client_name = clp->cl_cred.cr_principal;
                args.prognumber = conn->cb_prog,
                args.protocol = XPRT_TRANSPORT_TCP;
-               args.authflavor = clp->cl_flavor;
+               args.authflavor = clp->cl_cred.cr_flavor;
                clp->cl_cb_ident = conn->cb_ident;
        } else {
                if (!conn->cb_xprt)
index e6173147f9821c816527e0bde05289d392374af7..22bd0a66c3566465ee77ca228b1979134b625ab2 100644 (file)
@@ -231,7 +231,6 @@ struct nfs4_client {
        nfs4_verifier           cl_verifier;    /* generated by client */
        time_t                  cl_time;        /* time of last lease renewal */
        struct sockaddr_storage cl_addr;        /* client ipaddress */
-       u32                     cl_flavor;      /* setclientid pseudoflavor */
        struct svc_cred         cl_cred;        /* setclientid principal */
        clientid_t              cl_clientid;    /* generated by server */
        nfs4_verifier           cl_confirm;     /* generated by server */
index dfafeb2b05a0e2ddc5481b2b2a4f445ec8086a0e..eb7cc91b7258870f89b77a60de4172dd6f1502b6 100644 (file)
@@ -462,9 +462,6 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
 
        err = ERR_PTR(-ENOMEM);
        inode = proc_sys_make_inode(dir->i_sb, h ? h : head, p);
-       if (h)
-               sysctl_head_finish(h);
-
        if (!inode)
                goto out;
 
@@ -473,6 +470,8 @@ static struct dentry *proc_sys_lookup(struct inode *dir, struct dentry *dentry,
        d_add(dentry, inode);
 
 out:
+       if (h)
+               sysctl_head_finish(h);
        sysctl_head_finish(head);
        return err;
 }
index 36a29b753c79c709175ebfd788196d1ecad948b5..c495a3055e2a3be9b5e471afebdf53ac00c6fe51 100644 (file)
@@ -1589,10 +1589,10 @@ int __dquot_alloc_space(struct inode *inode, qsize_t number, int flags)
                goto out;
        }
 
-       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++)
                warn[cnt].w_type = QUOTA_NL_NOWARN;
 
+       down_read(&sb_dqopt(inode->i_sb)->dqptr_sem);
        spin_lock(&dq_data_lock);
        for (cnt = 0; cnt < MAXQUOTAS; cnt++) {
                if (!dquots[cnt])
index 4c0c7d163d150c02535cffcad08a1aead02f53d2..a98b7740a0fcade0b894920154e65ecbe7987509 100644 (file)
@@ -1334,9 +1334,7 @@ struct buffer_head *reiserfs_read_bitmap_block(struct super_block *sb,
        else if (bitmap == 0)
                block = (REISERFS_DISK_OFFSET_IN_BYTES >> sb->s_blocksize_bits) + 1;
 
-       reiserfs_write_unlock(sb);
        bh = sb_bread(sb, block);
-       reiserfs_write_lock(sb);
        if (bh == NULL)
                reiserfs_warning(sb, "sh-2029: %s: bitmap block (#%u) "
                                 "reading failed", __func__, block);
index a6d4268fb6c11798db5f8339bd14ab297cd9b21f..855da58db1456b94d43715bb4a28bbc5f982a8d7 100644 (file)
@@ -76,10 +76,10 @@ void reiserfs_evict_inode(struct inode *inode)
                ;
        }
       out:
+       reiserfs_write_unlock_once(inode->i_sb, depth);
        clear_inode(inode);     /* note this must go after the journal_end to prevent deadlock */
        dquot_drop(inode);
        inode->i_blocks = 0;
-       reiserfs_write_unlock_once(inode->i_sb, depth);
        return;
 
 no_delete:
index b6ff11825fc8a9c37f8d45ccf01e1fbdc1115868..40780229a03281376d4d449e896745f3f169a0d3 100644 (file)
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -58,7 +58,7 @@ EXPORT_SYMBOL(vfs_getattr);
 int vfs_fstat(unsigned int fd, struct kstat *stat)
 {
        int fput_needed;
-       struct file *f = fget_light(fd, &fput_needed);
+       struct file *f = fget_raw_light(fd, &fput_needed);
        int error = -EBADF;
 
        if (f) {
index 8b8cc4e945f4014bd8e0a77d1d9bde0197f0fa76..760de723dadb4928eec6f9c4729245a40dcce5de 100644 (file)
@@ -167,7 +167,7 @@ struct ubifs_global_debug_info {
 #define ubifs_dbg_msg(type, fmt, ...) \
        pr_debug("UBIFS DBG " type ": " fmt "\n", ##__VA_ARGS__)
 
-#define DBG_KEY_BUF_LEN 32
+#define DBG_KEY_BUF_LEN 48
 #define ubifs_dbg_msg_key(type, key, fmt, ...) do {                            \
        char __tmp_key_buf[DBG_KEY_BUF_LEN];                                   \
        pr_debug("UBIFS DBG " type ": " fmt "%s\n", ##__VA_ARGS__,             \
index ce33b2beb151f92ac61e51dcefc47cd25ee8dd15..8640920766ed461896add49f69b9db767aa9569c 100644 (file)
@@ -1749,7 +1749,10 @@ int ubifs_lpt_init(struct ubifs_info *c, int rd, int wr)
        return 0;
 
 out_err:
-       ubifs_lpt_free(c, 0);
+       if (wr)
+               ubifs_lpt_free(c, 1);
+       if (rd)
+               ubifs_lpt_free(c, 0);
        return err;
 }
 
index c30d976b4be857a9d222cedd5b7192a4f90e6cfa..edeec499c048ba1d93375796b5fd4f439f38dd81 100644 (file)
@@ -788,7 +788,7 @@ struct ubifs_scan_leb *ubifs_recover_leb(struct ubifs_info *c, int lnum,
 
 corrupted_rescan:
        /* Re-scan the corrupted data with verbose messages */
-       ubifs_err("corruptio %d", ret);
+       ubifs_err("corruption %d", ret);
        ubifs_scan_a_node(c, buf, len, lnum, offs, 1);
 corrupted:
        ubifs_scanned_corruption(c, lnum, offs, buf);
index eba46d4a76192c017846c4389addf2ebdcc2a78e..94d78fc5d4e0dc11e6ea4db670f43853f569eabb 100644 (file)
@@ -1026,7 +1026,6 @@ int ubifs_replay_journal(struct ubifs_info *c)
        c->replaying = 1;
        lnum = c->ltail_lnum = c->lhead_lnum;
 
-       lnum = UBIFS_LOG_LNUM;
        do {
                err = replay_log_leb(c, lnum, 0, c->sbuf);
                if (err == 1)
@@ -1035,7 +1034,7 @@ int ubifs_replay_journal(struct ubifs_info *c)
                if (err)
                        goto out;
                lnum = ubifs_next_log_lnum(c, lnum);
-       } while (lnum != UBIFS_LOG_LNUM);
+       } while (lnum != c->ltail_lnum);
 
        err = replay_buds(c);
        if (err)
index c3fa6c5327a3bb7b6939206c118a9d6ace0ee039..71a197f0f93d24c0cc33527d4f2d69c8c3d51f7b 100644 (file)
@@ -1157,9 +1157,6 @@ static int check_free_space(struct ubifs_info *c)
  *
  * This function mounts UBIFS file system. Returns zero in case of success and
  * a negative error code in case of failure.
- *
- * Note, the function does not de-allocate resources it it fails half way
- * through, and the caller has to do this instead.
  */
 static int mount_ubifs(struct ubifs_info *c)
 {
index 7f3f7ba3df6e7526b78699dd17a7439380611461..d1c6093fd3d3c8a204b6cca9dfc8ced300da075f 100644 (file)
 #include "udf_i.h"
 #include "udf_sb.h"
 
-static int udf_adinicb_readpage(struct file *file, struct page *page)
+static void __udf_adinicb_readpage(struct page *page)
 {
        struct inode *inode = page->mapping->host;
        char *kaddr;
        struct udf_inode_info *iinfo = UDF_I(inode);
 
-       BUG_ON(!PageLocked(page));
-
        kaddr = kmap(page);
-       memset(kaddr, 0, PAGE_CACHE_SIZE);
        memcpy(kaddr, iinfo->i_ext.i_data + iinfo->i_lenEAttr, inode->i_size);
+       memset(kaddr + inode->i_size, 0, PAGE_CACHE_SIZE - inode->i_size);
        flush_dcache_page(page);
        SetPageUptodate(page);
        kunmap(page);
+}
+
+static int udf_adinicb_readpage(struct file *file, struct page *page)
+{
+       BUG_ON(!PageLocked(page));
+       __udf_adinicb_readpage(page);
        unlock_page(page);
 
        return 0;
@@ -77,6 +81,25 @@ static int udf_adinicb_writepage(struct page *page,
        return 0;
 }
 
+static int udf_adinicb_write_begin(struct file *file,
+                       struct address_space *mapping, loff_t pos,
+                       unsigned len, unsigned flags, struct page **pagep,
+                       void **fsdata)
+{
+       struct page *page;
+
+       if (WARN_ON_ONCE(pos >= PAGE_CACHE_SIZE))
+               return -EIO;
+       page = grab_cache_page_write_begin(mapping, 0, flags);
+       if (!page)
+               return -ENOMEM;
+       *pagep = page;
+
+       if (!PageUptodate(page) && len != PAGE_CACHE_SIZE)
+               __udf_adinicb_readpage(page);
+       return 0;
+}
+
 static int udf_adinicb_write_end(struct file *file,
                        struct address_space *mapping,
                        loff_t pos, unsigned len, unsigned copied,
@@ -98,8 +121,8 @@ static int udf_adinicb_write_end(struct file *file,
 const struct address_space_operations udf_adinicb_aops = {
        .readpage       = udf_adinicb_readpage,
        .writepage      = udf_adinicb_writepage,
-       .write_begin = simple_write_begin,
-       .write_end = udf_adinicb_write_end,
+       .write_begin    = udf_adinicb_write_begin,
+       .write_end      = udf_adinicb_write_end,
 };
 
 static ssize_t udf_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
index fafaad795cd6da4842a798e25446f6b426d65d65..aa233469b3c1a0deb1e3ef60b8039f5dd2e1cd55 100644 (file)
@@ -1124,14 +1124,17 @@ int udf_setsize(struct inode *inode, loff_t newsize)
                                if (err)
                                        return err;
                                down_write(&iinfo->i_data_sem);
-                       } else
+                       } else {
                                iinfo->i_lenAlloc = newsize;
+                               goto set_size;
+                       }
                }
                err = udf_extend_file(inode, newsize);
                if (err) {
                        up_write(&iinfo->i_data_sem);
                        return err;
                }
+set_size:
                truncate_setsize(inode, newsize);
                up_write(&iinfo->i_data_sem);
        } else {
index dcbf98722afcd5df2a8940f4dbd5c1c8a02c7b40..18fc038a438da4b6bbf58fa73c23c27ecd0cb721 100644 (file)
@@ -1344,6 +1344,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
                udf_err(sb, "error loading logical volume descriptor: "
                        "Partition table too long (%u > %lu)\n", table_len,
                        sb->s_blocksize - sizeof(*lvd));
+               ret = 1;
                goto out_bh;
        }
 
@@ -1388,8 +1389,10 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block,
                                                UDF_ID_SPARABLE,
                                                strlen(UDF_ID_SPARABLE))) {
                                if (udf_load_sparable_map(sb, map,
-                                   (struct sparablePartitionMap *)gpm) < 0)
+                                   (struct sparablePartitionMap *)gpm) < 0) {
+                                       ret = 1;
                                        goto out_bh;
+                               }
                        } else if (!strncmp(upm2->partIdent.ident,
                                                UDF_ID_METADATA,
                                                strlen(UDF_ID_METADATA))) {
@@ -2000,6 +2003,8 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent)
                        if (!silent)
                                pr_notice("Rescanning with blocksize %d\n",
                                          UDF_DEFAULT_BLOCKSIZE);
+                       brelse(sbi->s_lvid_bh);
+                       sbi->s_lvid_bh = NULL;
                        uopt.blocksize = UDF_DEFAULT_BLOCKSIZE;
                        ret = udf_load_vrs(sb, &uopt, silent, &fileset);
                }
index d7a9dd735e1e429a1787d8b0e8e1c9ddde5eff10..933b7930b8636da970a627d571388b11e8dabde7 100644 (file)
@@ -96,6 +96,7 @@ xfs_buf_lru_add(
                atomic_inc(&bp->b_hold);
                list_add_tail(&bp->b_lru, &btp->bt_lru);
                btp->bt_lru_nr++;
+               bp->b_lru_flags &= ~_XBF_LRU_DISPOSE;
        }
        spin_unlock(&btp->bt_lru_lock);
 }
@@ -154,7 +155,8 @@ xfs_buf_stale(
                struct xfs_buftarg *btp = bp->b_target;
 
                spin_lock(&btp->bt_lru_lock);
-               if (!list_empty(&bp->b_lru)) {
+               if (!list_empty(&bp->b_lru) &&
+                   !(bp->b_lru_flags & _XBF_LRU_DISPOSE)) {
                        list_del_init(&bp->b_lru);
                        btp->bt_lru_nr--;
                        atomic_dec(&bp->b_hold);
@@ -1501,6 +1503,7 @@ xfs_buftarg_shrink(
                 */
                list_move(&bp->b_lru, &dispose);
                btp->bt_lru_nr--;
+               bp->b_lru_flags |= _XBF_LRU_DISPOSE;
        }
        spin_unlock(&btp->bt_lru_lock);
 
index d03b73b9604e3d55d93f1fdc08201512b01449dd..7c0b6a0a1557c0d30db4b94e4bc27879d2614537 100644 (file)
@@ -38,27 +38,28 @@ typedef enum {
        XBRW_ZERO = 3,                  /* Zero target memory */
 } xfs_buf_rw_t;
 
-#define XBF_READ       (1 << 0) /* buffer intended for reading from device */
-#define XBF_WRITE      (1 << 1) /* buffer intended for writing to device */
-#define XBF_READ_AHEAD (1 << 2) /* asynchronous read-ahead */
-#define XBF_ASYNC      (1 << 4) /* initiator will not wait for completion */
-#define XBF_DONE       (1 << 5) /* all pages in the buffer uptodate */
-#define XBF_STALE      (1 << 6) /* buffer has been staled, do not find it */
+#define XBF_READ        (1 << 0) /* buffer intended for reading from device */
+#define XBF_WRITE       (1 << 1) /* buffer intended for writing to device */
+#define XBF_READ_AHEAD  (1 << 2) /* asynchronous read-ahead */
+#define XBF_ASYNC       (1 << 4) /* initiator will not wait for completion */
+#define XBF_DONE        (1 << 5) /* all pages in the buffer uptodate */
+#define XBF_STALE       (1 << 6) /* buffer has been staled, do not find it */
 
 /* I/O hints for the BIO layer */
-#define XBF_SYNCIO     (1 << 10)/* treat this buffer as synchronous I/O */
-#define XBF_FUA                (1 << 11)/* force cache write through mode */
-#define XBF_FLUSH      (1 << 12)/* flush the disk cache before a write */
+#define XBF_SYNCIO      (1 << 10)/* treat this buffer as synchronous I/O */
+#define XBF_FUA                 (1 << 11)/* force cache write through mode */
+#define XBF_FLUSH       (1 << 12)/* flush the disk cache before a write */
 
 /* flags used only as arguments to access routines */
-#define XBF_TRYLOCK    (1 << 16)/* lock requested, but do not wait */
-#define XBF_UNMAPPED   (1 << 17)/* do not map the buffer */
+#define XBF_TRYLOCK     (1 << 16)/* lock requested, but do not wait */
+#define XBF_UNMAPPED    (1 << 17)/* do not map the buffer */
 
 /* flags used only internally */
-#define _XBF_PAGES     (1 << 20)/* backed by refcounted pages */
-#define _XBF_KMEM      (1 << 21)/* backed by heap memory */
-#define _XBF_DELWRI_Q  (1 << 22)/* buffer on a delwri queue */
-#define _XBF_COMPOUND  (1 << 23)/* compound buffer */
+#define _XBF_PAGES      (1 << 20)/* backed by refcounted pages */
+#define _XBF_KMEM       (1 << 21)/* backed by heap memory */
+#define _XBF_DELWRI_Q   (1 << 22)/* buffer on a delwri queue */
+#define _XBF_COMPOUND   (1 << 23)/* compound buffer */
+#define _XBF_LRU_DISPOSE (1 << 24)/* buffer being discarded */
 
 typedef unsigned int xfs_buf_flags_t;
 
@@ -72,12 +73,13 @@ typedef unsigned int xfs_buf_flags_t;
        { XBF_SYNCIO,           "SYNCIO" }, \
        { XBF_FUA,              "FUA" }, \
        { XBF_FLUSH,            "FLUSH" }, \
-       { XBF_TRYLOCK,          "TRYLOCK" },    /* should never be set */\
+       { XBF_TRYLOCK,          "TRYLOCK" },    /* should never be set */\
        { XBF_UNMAPPED,         "UNMAPPED" },   /* ditto */\
        { _XBF_PAGES,           "PAGES" }, \
        { _XBF_KMEM,            "KMEM" }, \
        { _XBF_DELWRI_Q,        "DELWRI_Q" }, \
-       { _XBF_COMPOUND,        "COMPOUND" }
+       { _XBF_COMPOUND,        "COMPOUND" }, \
+       { _XBF_LRU_DISPOSE,     "LRU_DISPOSE" }
 
 typedef struct xfs_buftarg {
        dev_t                   bt_dev;
@@ -124,7 +126,12 @@ typedef struct xfs_buf {
        xfs_buf_flags_t         b_flags;        /* status flags */
        struct semaphore        b_sema;         /* semaphore for lockables */
 
+       /*
+        * concurrent access to b_lru and b_lru_flags are protected by
+        * bt_lru_lock and not by b_sema
+        */
        struct list_head        b_lru;          /* lru list */
+       xfs_buf_flags_t         b_lru_flags;    /* internal lru status flags */
        wait_queue_head_t       b_waiters;      /* unpin waiters */
        struct list_head        b_list;
        struct xfs_perag        *b_pag;         /* contains rbtree root */
index f9c3fe304a17fc9ae470c7754294b3f129c78bea..69cf4fcde03e2d31266f70f6dfee1b73fe71b4a7 100644 (file)
@@ -179,12 +179,14 @@ xfs_ioc_trim(
         * used by the fstrim application.  In the end it really doesn't
         * matter as trimming blocks is an advisory interface.
         */
+       if (range.start >= XFS_FSB_TO_B(mp, mp->m_sb.sb_dblocks) ||
+           range.minlen > XFS_FSB_TO_B(mp, XFS_ALLOC_AG_MAX_USABLE(mp)))
+               return -XFS_ERROR(EINVAL);
+
        start = BTOBB(range.start);
        end = start + BTOBBT(range.len) - 1;
        minlen = BTOBB(max_t(u64, granularity, range.minlen));
 
-       if (XFS_BB_TO_FSB(mp, start) >= mp->m_sb.sb_dblocks)
-               return -XFS_ERROR(EINVAL);
        if (end > XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks) - 1)
                end = XFS_FSB_TO_BB(mp, mp->m_sb.sb_dblocks)- 1;
 
index 21e37b55f7e596c6d29c0c0125a755f7a8ada7f6..5aceb3f8ecd625de029daaff00e6093a0e0213a2 100644 (file)
@@ -962,23 +962,22 @@ xfs_dialloc(
                if (!pag->pagi_freecount && !okalloc)
                        goto nextag;
 
+               /*
+                * Then read in the AGI buffer and recheck with the AGI buffer
+                * lock held.
+                */
                error = xfs_ialloc_read_agi(mp, tp, agno, &agbp);
                if (error)
                        goto out_error;
 
-               /*
-                * Once the AGI has been read in we have to recheck
-                * pagi_freecount with the AGI buffer lock held.
-                */
                if (pag->pagi_freecount) {
                        xfs_perag_put(pag);
                        goto out_alloc;
                }
 
-               if (!okalloc) {
-                       xfs_trans_brelse(tp, agbp);
-                       goto nextag;
-               }
+               if (!okalloc)
+                       goto nextag_relse_buffer;
+
 
                error = xfs_ialloc_ag_alloc(tp, agbp, &ialloced);
                if (error) {
@@ -1007,6 +1006,8 @@ xfs_dialloc(
                        return 0;
                }
 
+nextag_relse_buffer:
+               xfs_trans_brelse(tp, agbp);
 nextag:
                xfs_perag_put(pag);
                if (++agno == mp->m_sb.sb_agcount)
index 92d4331cd4f1c118ea0a0087849d399a3948f230..ca28a4ba4b548f0c379291bfb0e716ac3a9ec54e 100644 (file)
@@ -857,7 +857,7 @@ xfs_rtbuf_get(
        xfs_buf_t       *bp;            /* block buffer, result */
        xfs_inode_t     *ip;            /* bitmap or summary inode */
        xfs_bmbt_irec_t map;
-       int             nmap;
+       int             nmap = 1;
        int             error;          /* error value */
 
        ip = issum ? mp->m_rsumip : mp->m_rbmip;
index bdaf4cb9f4a2d19fc8b781f232f61d88c529ac2a..19e2380fb8679d2e8641e691eaeb0b200456bfb4 100644 (file)
@@ -919,6 +919,7 @@ xfs_fs_put_super(
        struct xfs_mount        *mp = XFS_M(sb);
 
        xfs_filestream_unmount(mp);
+       cancel_delayed_work_sync(&mp->m_sync_work);
        xfs_unmountfs(mp);
        xfs_syncd_stop(mp);
        xfs_freesb(mp);
index 991ef01cd77eac4fa6b9469dc2ad4c53640f3950..3748ec92dcbcdb988bad96406e7d53b664118152 100644 (file)
@@ -691,9 +691,11 @@ __SC_COMP(__NR_process_vm_readv, sys_process_vm_readv, \
 #define __NR_process_vm_writev 271
 __SC_COMP(__NR_process_vm_writev, sys_process_vm_writev, \
           compat_sys_process_vm_writev)
+#define __NR_kcmp 272
+__SYSCALL(__NR_kcmp, sys_kcmp)
 
 #undef __NR_syscalls
-#define __NR_syscalls 272
+#define __NR_syscalls 273
 
 /*
  * All syscalls below here should go away really,
index ced362533e3c770f6dc8f4cb3a3872aeb52e455d..bfacf0d5a225fd0dd4c9a52d42496f3e7049a030 100644 (file)
@@ -118,7 +118,8 @@ enum drm_mode_status {
        .hdisplay = (hd), .hsync_start = (hss), .hsync_end = (hse), \
        .htotal = (ht), .hskew = (hsk), .vdisplay = (vd), \
        .vsync_start = (vss), .vsync_end = (vse), .vtotal = (vt), \
-       .vscan = (vs), .flags = (f), .vrefresh = 0
+       .vscan = (vs), .flags = (f), .vrefresh = 0, \
+       .base.type = DRM_MODE_OBJECT_MODE
 
 #define CRTC_INTERLACE_HALVE_V 0x1 /* halve V values for interlacing */
 
index bdf0152cbbe95b2747f0736366f520eabb193ea9..f4621184a9b404f8f7a81dfb130258def67cbd58 100644 (file)
 #define DRM_FORMAT_NV16                fourcc_code('N', 'V', '1', '6') /* 2x1 subsampled Cr:Cb plane */
 #define DRM_FORMAT_NV61                fourcc_code('N', 'V', '6', '1') /* 2x1 subsampled Cb:Cr plane */
 
-/* 2 non contiguous plane YCbCr */
-#define DRM_FORMAT_NV12M       fourcc_code('N', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane */
+/* special NV12 tiled format */
 #define DRM_FORMAT_NV12MT      fourcc_code('T', 'M', '1', '2') /* 2x2 subsampled Cr:Cb plane 64x32 macroblocks */
 
 /*
 #define DRM_FORMAT_YUV444      fourcc_code('Y', 'U', '2', '4') /* non-subsampled Cb (1) and Cr (2) planes */
 #define DRM_FORMAT_YVU444      fourcc_code('Y', 'V', '2', '4') /* non-subsampled Cr (1) and Cb (2) planes */
 
-/* 3 non contiguous plane YCbCr */
-#define DRM_FORMAT_YUV420M     fourcc_code('Y', 'M', '1', '2') /* 2x2 subsampled Cb (1) and Cr (2) planes */
-
 #endif /* DRM_FOURCC_H */
index 5581980b14f606e593e9827e175980e5a50802f0..3d6301b6ec16d36b60cb4f69570170b8c804fb6d 100644 (file)
@@ -359,8 +359,9 @@ struct drm_mode_mode_cmd {
        struct drm_mode_modeinfo mode;
 };
 
-#define DRM_MODE_CURSOR_BO     (1<<0)
-#define DRM_MODE_CURSOR_MOVE   (1<<1)
+#define DRM_MODE_CURSOR_BO     0x01
+#define DRM_MODE_CURSOR_MOVE   0x02
+#define DRM_MODE_CURSOR_FLAGS  0x03
 
 /*
  * depending on the value in flags different members are used.
index fa217607c582e7feb5cf1ef301b1659f7b9db1ff..e53840d941d4ad3e80d8705fa6560289e2806367 100644 (file)
@@ -387,6 +387,7 @@ header-y += utsname.h
 header-y += uuid.h
 header-y += uvcvideo.h
 header-y += v4l2-common.h
+header-y += v4l2-controls.h
 header-y += v4l2-dv-timings.h
 header-y += v4l2-mediabus.h
 header-y += v4l2-subdev.h
index 06023393fba97cfc069ae119f66d84b1bdb0b256..4eb31752e2b77592e8a2fdbf3fde779d4851504d 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/platform_device.h>
 #include <linux/list.h>
+#include <linux/io.h>
 
 struct ssc_device {
        struct list_head        list;
index 4e72a9d48232d513b5b2fe44d973de8dfeb1e9e4..4a2ab7c85393df48fd8d93e085f3b7ead5de7be2 100644 (file)
@@ -601,7 +601,7 @@ static inline void blk_clear_rl_full(struct request_list *rl, bool sync)
  * it already be started by driver.
  */
 #define RQ_NOMERGE_FLAGS       \
-       (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA)
+       (REQ_NOMERGE | REQ_STARTED | REQ_SOFTBARRIER | REQ_FLUSH | REQ_FUA | REQ_DISCARD)
 #define rq_mergeable(rq)       \
        (!((rq)->cmd_flags & RQ_NOMERGE_FLAGS) && \
         (((rq)->cmd_flags & REQ_DISCARD) || \
@@ -894,6 +894,8 @@ extern void blk_queue_flush_queueable(struct request_queue *q, bool queueable);
 extern struct backing_dev_info *blk_get_backing_dev_info(struct block_device *bdev);
 
 extern int blk_rq_map_sg(struct request_queue *, struct request *, struct scatterlist *);
+extern int blk_bio_map_sg(struct request_queue *q, struct bio *bio,
+                         struct scatterlist *sglist);
 extern void blk_dump_rq_flags(struct request *, char *);
 extern long nr_blockdev_pages(void);
 
@@ -1139,6 +1141,16 @@ static inline int queue_limit_discard_alignment(struct queue_limits *lim, sector
                & (lim->discard_granularity - 1);
 }
 
+static inline int bdev_discard_alignment(struct block_device *bdev)
+{
+       struct request_queue *q = bdev_get_queue(bdev);
+
+       if (bdev != bdev->bd_contains)
+               return bdev->bd_part->discard_alignment;
+
+       return q->limits.discard_alignment;
+}
+
 static inline unsigned int queue_discard_zeroes_data(struct request_queue *q)
 {
        if (q->limits.max_discard_sectors && q->limits.discard_zeroes_data == 1)
index 2f4079175afb81f80f641e28da9b1145b5415bae..934bc34d5f993892f75c3b803d412b43e62dc072 100644 (file)
 #endif
 #endif
 
+#if __GNUC_MINOR__ >= 6
+/*
+ * Tell the optimizer that something else uses this function or variable.
+ */
+#define __visible __attribute__((externally_visible))
+#endif
+
 #if __GNUC_MINOR__ > 0
 #define __compiletime_object_size(obj) __builtin_object_size(obj, 0)
 #endif
index 923d093c9ceac685f199868a8b49fa58349aa554..f430e4162f41ea188fdb5168df28b4304b7c14c3 100644 (file)
@@ -278,6 +278,10 @@ void ftrace_likely_update(struct ftrace_branch_data *f, int val, int expect);
 # define __section(S) __attribute__ ((__section__(#S)))
 #endif
 
+#ifndef __visible
+#define __visible
+#endif
+
 /* Are two types/vars the same type (ignoring qualifiers)? */
 #ifndef __same_type
 # define __same_type(a, b) __builtin_types_compatible_p(typeof(a), typeof(b))
index 040b13b5c14a5bdc500f82855123e7940fda6f6f..279b1eaa8b7304bf1028b6f91acedf4f15317148 100644 (file)
@@ -194,6 +194,10 @@ static inline int cpuidle_play_dead(void) {return -ENODEV; }
 
 #ifdef CONFIG_ARCH_NEEDS_CPU_IDLE_COUPLED
 void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a);
+#else
+static inline void cpuidle_coupled_parallel_barrier(struct cpuidle_device *dev, atomic_t *a)
+{
+}
 #endif
 
 /******************************
index caa34e50537e895a7a4b5149148f03157e253129..59200795482eebccde8497372c82d1aca0cadd40 100644 (file)
@@ -206,6 +206,8 @@ struct dentry_operations {
 #define DCACHE_MANAGED_DENTRY \
        (DCACHE_MOUNTED|DCACHE_NEED_AUTOMOUNT|DCACHE_MANAGE_TRANSIT)
 
+#define DCACHE_DENTRY_KILLED   0x100000
+
 extern seqlock_t rename_lock;
 
 static inline int dname_external(struct dentry *dentry)
index f50d4058c5fbfa1c8c50e5773456a46dd03736f1..c12d452cb40df13b256db3d040fa4e898f7b9355 100644 (file)
@@ -62,6 +62,7 @@ typedef enum fe_caps {
        FE_CAN_8VSB                     = 0x200000,
        FE_CAN_16VSB                    = 0x400000,
        FE_HAS_EXTENDED_CAPS            = 0x800000,   /* We need more bitspace for newer APIs, indicate this. */
+       FE_CAN_MULTISTREAM              = 0x4000000,  /* frontend supports multistream filtering */
        FE_CAN_TURBO_FEC                = 0x8000000,  /* frontend supports "turbo fec modulation" */
        FE_CAN_2G_MODULATION            = 0x10000000, /* frontend supports "2nd generation modulation" (DVB-S2) */
        FE_NEEDS_BENDING                = 0x20000000, /* not supported anymore, don't use (frontend requires frequency bending) */
@@ -121,16 +122,27 @@ typedef enum fe_sec_mini_cmd {
 } fe_sec_mini_cmd_t;
 
 
+/**
+ * enum fe_status - enumerates the possible frontend status
+ * @FE_HAS_SIGNAL:     found something above the noise level
+ * @FE_HAS_CARRIER:    found a DVB signal
+ * @FE_HAS_VITERBI:    FEC is stable
+ * @FE_HAS_SYNC:       found sync bytes
+ * @FE_HAS_LOCK:       everything's working
+ * @FE_TIMEDOUT:       no lock within the last ~2 seconds
+ * @FE_REINIT:         frontend was reinitialized, application is recommended
+ *                     to reset DiSEqC, tone and parameters
+ */
+
 typedef enum fe_status {
-       FE_HAS_SIGNAL   = 0x01,   /* found something above the noise level */
-       FE_HAS_CARRIER  = 0x02,   /* found a DVB signal  */
-       FE_HAS_VITERBI  = 0x04,   /* FEC is stable  */
-       FE_HAS_SYNC     = 0x08,   /* found sync bytes  */
-       FE_HAS_LOCK     = 0x10,   /* everything's working... */
-       FE_TIMEDOUT     = 0x20,   /* no lock within the last ~2 seconds */
-       FE_REINIT       = 0x40    /* frontend was reinitialized,  */
-} fe_status_t;                   /* application is recommended to reset */
-                                 /* DiSEqC, tone and parameters */
+       FE_HAS_SIGNAL           = 0x01,
+       FE_HAS_CARRIER          = 0x02,
+       FE_HAS_VITERBI          = 0x04,
+       FE_HAS_SYNC             = 0x08,
+       FE_HAS_LOCK             = 0x10,
+       FE_TIMEDOUT             = 0x20,
+       FE_REINIT               = 0x40,
+} fe_status_t;
 
 typedef enum fe_spectral_inversion {
        INVERSION_OFF,
@@ -152,6 +164,7 @@ typedef enum fe_code_rate {
        FEC_AUTO,
        FEC_3_5,
        FEC_9_10,
+       FEC_2_5,
 } fe_code_rate_t;
 
 
@@ -169,6 +182,7 @@ typedef enum fe_modulation {
        APSK_16,
        APSK_32,
        DQPSK,
+       QAM_4_NR,
 } fe_modulation_t;
 
 typedef enum fe_transmit_mode {
@@ -179,6 +193,8 @@ typedef enum fe_transmit_mode {
        TRANSMISSION_MODE_1K,
        TRANSMISSION_MODE_16K,
        TRANSMISSION_MODE_32K,
+       TRANSMISSION_MODE_C1,
+       TRANSMISSION_MODE_C3780,
 } fe_transmit_mode_t;
 
 #if defined(__DVB_CORE__) || !defined (__KERNEL__)
@@ -202,6 +218,9 @@ typedef enum fe_guard_interval {
        GUARD_INTERVAL_1_128,
        GUARD_INTERVAL_19_128,
        GUARD_INTERVAL_19_256,
+       GUARD_INTERVAL_PN420,
+       GUARD_INTERVAL_PN595,
+       GUARD_INTERVAL_PN945,
 } fe_guard_interval_t;
 
 
@@ -213,6 +232,12 @@ typedef enum fe_hierarchy {
        HIERARCHY_AUTO
 } fe_hierarchy_t;
 
+enum fe_interleaving {
+       INTERLEAVING_NONE,
+       INTERLEAVING_AUTO,
+       INTERLEAVING_240,
+       INTERLEAVING_720,
+};
 
 #if defined(__DVB_CORE__) || !defined (__KERNEL__)
 struct dvb_qpsk_parameters {
@@ -314,9 +339,9 @@ struct dvb_frontend_event {
 
 #define DTV_ISDBT_LAYER_ENABLED        41
 
-#define DTV_ISDBS_TS_ID                42
-
-#define DTV_DVBT2_PLP_ID       43
+#define DTV_STREAM_ID          42
+#define DTV_ISDBS_TS_ID_LEGACY DTV_STREAM_ID
+#define DTV_DVBT2_PLP_ID_LEGACY        43
 
 #define DTV_ENUM_DELSYS                44
 
@@ -337,7 +362,10 @@ struct dvb_frontend_event {
 #define DTV_ATSCMH_SCCC_CODE_MODE_C    58
 #define DTV_ATSCMH_SCCC_CODE_MODE_D    59
 
-#define DTV_MAX_COMMAND                                DTV_ATSCMH_SCCC_CODE_MODE_D
+#define DTV_INTERLEAVING                       60
+#define DTV_LNA                                        61
+
+#define DTV_MAX_COMMAND                                DTV_LNA
 
 typedef enum fe_pilot {
        PILOT_ON,
@@ -366,7 +394,7 @@ typedef enum fe_delivery_system {
        SYS_ISDBC,
        SYS_ATSC,
        SYS_ATSCMH,
-       SYS_DMBTH,
+       SYS_DTMB,
        SYS_CMMB,
        SYS_DAB,
        SYS_DVBT2,
@@ -374,8 +402,9 @@ typedef enum fe_delivery_system {
        SYS_DVBC_ANNEX_C,
 } fe_delivery_system_t;
 
-
+/* backward compatibility */
 #define SYS_DVBC_ANNEX_AC      SYS_DVBC_ANNEX_A
+#define SYS_DMBTH SYS_DTMB /* DMB-TH is legacy name, use DTMB instead */
 
 /* ATSC-MH */
 
@@ -409,6 +438,8 @@ enum atscmh_rs_code_mode {
        ATSCMH_RSCODE_RES        = 3,
 };
 
+#define NO_STREAM_ID_FILTER    (~0U)
+#define LNA_AUTO                (~0U)
 
 struct dtv_cmds_h {
        char    *name;          /* A display name for debugging purposes */
index 43d9e8d462d47aab070930f56fa4ac78d47d6f08..20e5eac2ffd3f70688e35b7964fbdc0e172e8c4a 100644 (file)
@@ -24,6 +24,6 @@
 #define _DVBVERSION_H_
 
 #define DVB_API_VERSION 5
-#define DVB_API_VERSION_MINOR 6
+#define DVB_API_VERSION_MINOR 8
 
 #endif /*_DVBVERSION_H_*/
index 1bc74afe7a35c7ea248510874910525d0206c9c3..49ed17fdf0556436cd626e52e0a9cd9809bc610a 100644 (file)
@@ -22,6 +22,7 @@ struct i2c_pnx_mif {
        struct timer_list       timer;          /* Timeout */
        u8 *                    buf;            /* Data buffer */
        int                     len;            /* Length of data buffer */
+       int                     order;          /* RX Bytes to order via TX */
 };
 
 struct i2c_pnx_algo_data {
index 7e83370e6fd2b134691e7fa348529e70d0a1ae56..f3b99e1c1042ac4073b681ee30ff7ea1f0f9a3a3 100644 (file)
@@ -256,72 +256,78 @@ static inline void iommu_set_fault_handler(struct iommu_domain *domain,
 {
 }
 
-int iommu_attach_group(struct iommu_domain *domain, struct iommu_group *group)
+static inline int iommu_attach_group(struct iommu_domain *domain,
+                                    struct iommu_group *group)
 {
        return -ENODEV;
 }
 
-void iommu_detach_group(struct iommu_domain *domain, struct iommu_group *group)
+static inline void iommu_detach_group(struct iommu_domain *domain,
+                                     struct iommu_group *group)
 {
 }
 
-struct iommu_group *iommu_group_alloc(void)
+static inline struct iommu_group *iommu_group_alloc(void)
 {
        return ERR_PTR(-ENODEV);
 }
 
-void *iommu_group_get_iommudata(struct iommu_group *group)
+static inline void *iommu_group_get_iommudata(struct iommu_group *group)
 {
        return NULL;
 }
 
-void iommu_group_set_iommudata(struct iommu_group *group, void *iommu_data,
-                              void (*release)(void *iommu_data))
+static inline void iommu_group_set_iommudata(struct iommu_group *group,
+                                            void *iommu_data,
+                                            void (*release)(void *iommu_data))
 {
 }
 
-int iommu_group_set_name(struct iommu_group *group, const char *name)
+static inline int iommu_group_set_name(struct iommu_group *group,
+                                      const char *name)
 {
        return -ENODEV;
 }
 
-int iommu_group_add_device(struct iommu_group *group, struct device *dev)
+static inline int iommu_group_add_device(struct iommu_group *group,
+                                        struct device *dev)
 {
        return -ENODEV;
 }
 
-void iommu_group_remove_device(struct device *dev)
+static inline void iommu_group_remove_device(struct device *dev)
 {
 }
 
-int iommu_group_for_each_dev(struct iommu_group *group, void *data,
-                            int (*fn)(struct device *, void *))
+static inline int iommu_group_for_each_dev(struct iommu_group *group,
+                                          void *data,
+                                          int (*fn)(struct device *, void *))
 {
        return -ENODEV;
 }
 
-struct iommu_group *iommu_group_get(struct device *dev)
+static inline struct iommu_group *iommu_group_get(struct device *dev)
 {
        return NULL;
 }
 
-void iommu_group_put(struct iommu_group *group)
+static inline void iommu_group_put(struct iommu_group *group)
 {
 }
 
-int iommu_group_register_notifier(struct iommu_group *group,
-                                 struct notifier_block *nb)
+static inline int iommu_group_register_notifier(struct iommu_group *group,
+                                               struct notifier_block *nb)
 {
        return -ENODEV;
 }
 
-int iommu_group_unregister_notifier(struct iommu_group *group,
-                                   struct notifier_block *nb)
+static inline int iommu_group_unregister_notifier(struct iommu_group *group,
+                                                 struct notifier_block *nb)
 {
        return 0;
 }
 
-int iommu_group_id(struct iommu_group *group)
+static inline int iommu_group_id(struct iommu_group *group)
 {
        return -ENODEV;
 }
index 604382143bcfccd6772260ed56e16589800af83c..2451f1f7a1d969f29bb2a3137c846566bfaf614a 100644 (file)
        __x - (__x % (y));                              \
 }                                                      \
 )
+
+/*
+ * Divide positive or negative dividend by positive divisor and round
+ * to closest integer. Result is undefined for negative divisors.
+ */
 #define DIV_ROUND_CLOSEST(x, divisor)(                 \
 {                                                      \
-       typeof(divisor) __divisor = divisor;            \
-       (((x) + ((__divisor) / 2)) / (__divisor));      \
+       typeof(x) __x = x;                              \
+       typeof(divisor) __d = divisor;                  \
+       (((typeof(x))-1) > 0 || (__x) > 0) ?            \
+               (((__x) + ((__d) / 2)) / (__d)) :       \
+               (((__x) - ((__d) / 2)) / (__d));        \
 }                                                      \
 )
 
index fc615a97e2d363df686f6111988cf686d8e03dfa..1e57449395b16db43ecfb638b71acc533e9ec73b 100644 (file)
@@ -224,7 +224,7 @@ static inline int kobject_uevent_env(struct kobject *kobj,
 
 static inline __printf(2, 3)
 int add_uevent_var(struct kobj_uevent_env *env, const char *format, ...)
-{ return 0; }
+{ return -ENOMEM; }
 
 static inline int kobject_action_type(const char *buf, size_t count,
                                      enum kobject_action *type)
index 603bec2913b00ca40086149828f3fcddab32a435..06177ba10a1617461dbe6803efc22ba6dfb43304 100644 (file)
@@ -58,13 +58,6 @@ union ktime {
 
 typedef union ktime ktime_t;           /* Kill this */
 
-#define KTIME_MAX                      ((s64)~((u64)1 << 63))
-#if (BITS_PER_LONG == 64)
-# define KTIME_SEC_MAX                 (KTIME_MAX / NSEC_PER_SEC)
-#else
-# define KTIME_SEC_MAX                 LONG_MAX
-#endif
-
 /*
  * ktime_t definitions when using the 64-bit scalar representation:
  */
index d0752eca9b4495011f6f82b20ba4e487b06ad6da..9d96d5d4dfed30f19c5ddeb04bacacd44f08bd45 100644 (file)
@@ -183,7 +183,7 @@ extern int  mISDN_initbchannel(struct bchannel *, unsigned short,
                                   unsigned short);
 extern int     mISDN_freedchannel(struct dchannel *);
 extern void    mISDN_clear_bchannel(struct bchannel *);
-extern int     mISDN_freebchannel(struct bchannel *);
+extern void    mISDN_freebchannel(struct bchannel *);
 extern int     mISDN_ctrl_bchannel(struct bchannel *, struct mISDN_ctrl_req *);
 extern void    queue_ch_frame(struct mISDNchannel *, u_int,
                        int, struct sk_buff *);
index 1ac7f6e405f9e2fe3556cb02135393b9b818af24..ff9a9f8e0ed9deb1573c087475511b269b7e17e2 100644 (file)
@@ -19,7 +19,7 @@
 #include <linux/compiler.h>
 #include <linux/mutex.h>
 
-#define MIN_MEMORY_BLOCK_SIZE     (1 << SECTION_SIZE_BITS)
+#define MIN_MEMORY_BLOCK_SIZE     (1UL << SECTION_SIZE_BITS)
 
 struct memory_block {
        unsigned long start_section_nr;
index 3a8435a8058f1cec9357b3f980efb0eae18f5569..cebe97ee98b86e1d6f6ef478ddf84693d8486d6b 100644 (file)
@@ -16,6 +16,8 @@
 
 #include <linux/platform_device.h>
 
+struct irq_domain;
+
 /*
  * This struct describes the MFD part ("cell").
  * After registration the copy of this structure will become the platform data
@@ -98,7 +100,7 @@ static inline const struct mfd_cell *mfd_get_cell(struct platform_device *pdev)
 extern int mfd_add_devices(struct device *parent, int id,
                           struct mfd_cell *cells, int n_devs,
                           struct resource *mem_base,
-                          int irq_base);
+                          int irq_base, struct irq_domain *irq_domain);
 
 extern void mfd_remove_devices(struct device *parent);
 
index 12c06870829af2add4caed14a9ea57f069b7479f..7cd83d826ed82285099c55cc7008dc558feddcb2 100644 (file)
@@ -22,6 +22,9 @@
 #include <linux/regulator/driver.h>
 #include <linux/regulator/machine.h>
 
+/* TPS chip id list */
+#define TPS65217                       0xF0
+
 /* I2C ID for TPS65217 part */
 #define TPS65217_I2C_ID                        0x24
 
@@ -248,13 +251,11 @@ struct tps_info {
 struct tps65217 {
        struct device *dev;
        struct tps65217_board *pdata;
+       unsigned int id;
        struct regulator_desc desc[TPS65217_NUM_REGULATOR];
        struct regulator_dev *rdev[TPS65217_NUM_REGULATOR];
        struct tps_info *info[TPS65217_NUM_REGULATOR];
        struct regmap *regmap;
-
-       /* Client devices */
-       struct platform_device *regulator_pdev[TPS65217_NUM_REGULATOR];
 };
 
 static inline struct tps65217 *dev_to_tps65217(struct device *dev)
@@ -262,6 +263,11 @@ static inline struct tps65217 *dev_to_tps65217(struct device *dev)
        return dev_get_drvdata(dev);
 }
 
+static inline int tps65217_chip_id(struct tps65217 *tps65217)
+{
+       return tps65217->id;
+}
+
 int tps65217_reg_read(struct tps65217 *tps, unsigned int reg,
                                        unsigned int *val);
 int tps65217_reg_write(struct tps65217 *tps, unsigned int reg,
index 61f0905bdc480b9078dc31e5d434158f4301df50..de201203bc7c833a09651f75678b833cfac0b880 100644 (file)
@@ -1,3 +1,15 @@
+/*
+ * include/linux/micrel_phy.h
+ *
+ * Micrel PHY IDs
+ *
+ * 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 _MICREL_PHY_H
 #define _MICREL_PHY_H
 
 
 #define PHY_ID_KSZ9021         0x00221610
 #define PHY_ID_KS8737          0x00221720
-#define PHY_ID_KS8041          0x00221510
-#define PHY_ID_KS8051          0x00221550
+#define PHY_ID_KSZ8021         0x00221555
+#define PHY_ID_KSZ8041         0x00221510
+#define PHY_ID_KSZ8051         0x00221550
 /* both for ks8001 Rev. A/B, and for ks8721 Rev 3. */
-#define PHY_ID_KS8001          0x0022161A
+#define PHY_ID_KSZ8001         0x0022161A
 
 /* struct phy_device dev_flags definitions */
 #define MICREL_PHY_50MHZ_CLK   0x00000001
index bd6c9fcdf2dd30c29b582a38e5f5c3f1eb320b62..6e1b0f973a03511b398154a5d42f3a9174b9268a 100644 (file)
@@ -796,6 +796,19 @@ enum mlx4_net_trans_rule_id {
        MLX4_NET_TRANS_RULE_NUM, /* should be last */
 };
 
+extern const u16 __sw_id_hw[];
+
+static inline int map_hw_to_sw_id(u16 header_id)
+{
+
+       int i;
+       for (i = 0; i < MLX4_NET_TRANS_RULE_NUM; i++) {
+               if (header_id == __sw_id_hw[i])
+                       return i;
+       }
+       return -EINVAL;
+}
+
 enum mlx4_net_trans_promisc_mode {
        MLX4_FS_PROMISC_NONE = 0,
        MLX4_FS_PROMISC_UPLINK,
index 111aca5e97f3d1801ace7ed7c009af4165a3869a..4b27f9f503e4a25a18f664ea7bd84c9b385d11be 100644 (file)
@@ -239,6 +239,7 @@ struct mmc_card {
 #define MMC_QUIRK_BLK_NO_CMD23 (1<<7)          /* Avoid CMD23 for regular multiblock */
 #define MMC_QUIRK_BROKEN_BYTE_MODE_512 (1<<8)  /* Avoid sending 512 bytes in */
 #define MMC_QUIRK_LONG_READ_TIME (1<<9)                /* Data read time > CSD says */
+#define MMC_QUIRK_SEC_ERASE_TRIM_BROKEN (1<<10)        /* Skip secure for erase/trim */
                                                /* byte mode */
        unsigned int    poweroff_notify_state;  /* eMMC4.5 notify feature */
 #define MMC_NO_POWER_NOTIFICATION      0
index 51bf8ada6dc0166b103c4d11067d92fbb2496d78..49258e0ed1c679e4dfacc488b8e94aa49e7d815e 100644 (file)
@@ -15,6 +15,8 @@
 #define MV643XX_ETH_SIZE_REG_4         0x2224
 #define MV643XX_ETH_BASE_ADDR_ENABLE_REG       0x2290
 
+#define MV643XX_TX_CSUM_DEFAULT_LIMIT  0
+
 struct mv643xx_eth_shared_platform_data {
        struct mbus_dram_target_info    *dram;
        struct platform_device  *shared_smi;
index 1f8fc7f9bcd8b8eb0d07588ba671b9327e53fe90..4b03f56e280eb9e59f236806ce24ce36e435c9c7 100644 (file)
@@ -265,11 +265,6 @@ static inline const struct nfs_rpc_ops *NFS_PROTO(const struct inode *inode)
        return NFS_SERVER(inode)->nfs_client->rpc_ops;
 }
 
-static inline __be32 *NFS_COOKIEVERF(const struct inode *inode)
-{
-       return NFS_I(inode)->cookieverf;
-}
-
 static inline unsigned NFS_MINATTRTIMEO(const struct inode *inode)
 {
        struct nfs_server *nfss = NFS_SERVER(inode);
index ac7c8ae254f251933e48f04d5c877eaaa3ec6e09..be9cf3c7e79ec0afcc0e024f6b95da5ab2bbd97e 100644 (file)
@@ -652,7 +652,7 @@ struct nfs_getaclargs {
 };
 
 /* getxattr ACL interface flags */
-#define NFS4_ACL_LEN_REQUEST   0x0001  /* zero length getxattr buffer */
+#define NFS4_ACL_TRUNC         0x0001  /* ACL was truncated */
 struct nfs_getaclres {
        size_t                          acl_len;
        size_t                          acl_data_offset;
index 9490a00529f49aa7f50a8e94e7fd7961b2002319..c25cccaa555a420b5cc6fd26d5e83a89937470a6 100644 (file)
@@ -35,8 +35,10 @@ struct nvme_bar {
        __u64                   acq;    /* Admin CQ Base Address */
 };
 
+#define NVME_CAP_MQES(cap)     ((cap) & 0xffff)
 #define NVME_CAP_TIMEOUT(cap)  (((cap) >> 24) & 0xff)
 #define NVME_CAP_STRIDE(cap)   (((cap) >> 32) & 0xf)
+#define NVME_CAP_MPSMIN(cap)   (((cap) >> 48) & 0xf)
 
 enum {
        NVME_CC_ENABLE          = 1 << 0,
index c73a34c3434d75150cc4f6440e3ba3a5a8ffc47f..c090cf9249bb68b6d1bcf1dec4d8e70f63e03137 100644 (file)
@@ -28,6 +28,7 @@
 #define OMAP3_ISP_USER_H
 
 #include <linux/types.h>
+#include <linux/videodev2.h>
 
 /*
  * Private IOCTLs
@@ -427,7 +428,7 @@ struct omap3isp_ccdc_update_config {
 #define OMAP3ISP_PREV_COLOR_CONV       (1 << 8)
 #define OMAP3ISP_PREV_YC_LIMIT         (1 << 9)
 #define OMAP3ISP_PREV_DEFECT_COR       (1 << 10)
-#define OMAP3ISP_PREV_GAMMABYPASS      (1 << 11)
+/* Bit 11 was OMAP3ISP_PREV_GAMMABYPASS, now merged with OMAP3ISP_PREV_GAMMA */
 #define OMAP3ISP_PREV_DRK_FRM_CAPTURE  (1 << 12)
 #define OMAP3ISP_PREV_DRK_FRM_SUBTRACT (1 << 13)
 #define OMAP3ISP_PREV_LENS_SHADING     (1 << 14)
@@ -436,6 +437,7 @@ struct omap3isp_ccdc_update_config {
 
 #define OMAP3ISP_PREV_NF_TBL_SIZE      64
 #define OMAP3ISP_PREV_CFA_TBL_SIZE     576
+#define OMAP3ISP_PREV_CFA_BLK_SIZE     (OMAP3ISP_PREV_CFA_TBL_SIZE / 4)
 #define OMAP3ISP_PREV_GAMMA_TBL_SIZE   1024
 #define OMAP3ISP_PREV_YENH_TBL_SIZE    128
 
@@ -477,7 +479,7 @@ struct omap3isp_prev_cfa {
        enum omap3isp_cfa_fmt format;
        __u8 gradthrs_vert;
        __u8 gradthrs_horz;
-       __u32 table[OMAP3ISP_PREV_CFA_TBL_SIZE];
+       __u32 table[4][OMAP3ISP_PREV_CFA_BLK_SIZE];
 };
 
 /**
index fc35260773489d55724f87d3493f5d5b23ab1f57..6b4565c440c8795eecf21044e9a8dc76b630687d 100644 (file)
 #define PCI_DEVICE_ID_TIGON3_5704S     0x16a8
 #define PCI_DEVICE_ID_NX2_57800_VF     0x16a9
 #define PCI_DEVICE_ID_NX2_5706S                0x16aa
-#define PCI_DEVICE_ID_NX2_57840_MF     0x16ab
+#define PCI_DEVICE_ID_NX2_57840_MF     0x16a4
 #define PCI_DEVICE_ID_NX2_5708S                0x16ac
 #define PCI_DEVICE_ID_NX2_57840_VF     0x16ad
 #define PCI_DEVICE_ID_NX2_57810_MF     0x16ae
index 7602ccb3f40ec672001be2eae9be3395604493f2..bdb41612bfec621e1aaba5e2468c5b01c6131770 100644 (file)
@@ -274,6 +274,8 @@ struct perf_event_attr {
        __u64   branch_sample_type; /* enum branch_sample_type */
 };
 
+#define perf_flags(attr)       (*(&(attr)->read_format + 1))
+
 /*
  * Ioctls that can be done on a perf event fd:
  */
@@ -926,7 +928,7 @@ struct perf_event {
        struct hw_perf_event            hw;
 
        struct perf_event_context       *ctx;
-       struct file                     *filp;
+       atomic_long_t                   refcount;
 
        /*
         * These accumulate total time (in nanoseconds) that children
@@ -1296,6 +1298,7 @@ extern int perf_swevent_get_recursion_context(void);
 extern void perf_swevent_put_recursion_context(int rctx);
 extern void perf_event_enable(struct perf_event *event);
 extern void perf_event_disable(struct perf_event *event);
+extern int __perf_event_disable(void *info);
 extern void perf_event_task_tick(void);
 #else
 static inline void
@@ -1334,6 +1337,7 @@ static inline int  perf_swevent_get_recursion_context(void)               { return -1; }
 static inline void perf_swevent_put_recursion_context(int rctx)                { }
 static inline void perf_event_enable(struct perf_event *event)         { }
 static inline void perf_event_disable(struct perf_event *event)                { }
+static inline int __perf_event_disable(void *info)                     { return -1; }
 static inline void perf_event_task_tick(void)                          { }
 #endif
 
index b8c86648a2f95dc6f83aab668fd9a7e07f277b4e..23bddac4bad8d08f3781d1e8a453aa41edb28632 100644 (file)
@@ -954,7 +954,6 @@ struct sched_domain {
        unsigned int smt_gain;
        int flags;                      /* See SD_* */
        int level;
-       int idle_buddy;                 /* cpu assigned to select_idle_sibling() */
 
        /* Runtime fields. */
        unsigned long last_balance;     /* init to jiffies. units in jiffies */
index 3dea6a9d568f416ccd1b704eec1d4bff9dea6d90..d143b8e01954ab14ac224d9894bf65e111ee97fb 100644 (file)
@@ -118,6 +118,7 @@ void reset_security_ops(void);
 extern unsigned long mmap_min_addr;
 extern unsigned long dac_mmap_min_addr;
 #else
+#define mmap_min_addr          0UL
 #define dac_mmap_min_addr      0UL
 #endif
 
index cff40aa7db625bbb9dafd6b5842d3dc70276c682..bf8c49ff7530c7ee8b85d4a8b3ccef5de86ff308 100644 (file)
@@ -114,6 +114,7 @@ struct rpc_xprt_ops {
        void            (*set_buffer_size)(struct rpc_xprt *xprt, size_t sndsize, size_t rcvsize);
        int             (*reserve_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
        void            (*release_xprt)(struct rpc_xprt *xprt, struct rpc_task *task);
+       void            (*alloc_slot)(struct rpc_xprt *xprt, struct rpc_task *task);
        void            (*rpcbind)(struct rpc_task *task);
        void            (*set_port)(struct rpc_xprt *xprt, unsigned short port);
        void            (*connect)(struct rpc_task *task);
@@ -281,6 +282,8 @@ void                        xprt_connect(struct rpc_task *task);
 void                   xprt_reserve(struct rpc_task *task);
 int                    xprt_reserve_xprt(struct rpc_xprt *xprt, struct rpc_task *task);
 int                    xprt_reserve_xprt_cong(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
+void                   xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task);
 int                    xprt_prepare_transmit(struct rpc_task *task);
 void                   xprt_transmit(struct rpc_task *task);
 void                   xprt_end_transmit(struct rpc_task *task);
index c81c5e40fcb512dda61255ac7399fb818bcb0cec..b51e664c83e7237e17e02f0b5752ce586f87dbd4 100644 (file)
@@ -107,11 +107,36 @@ static inline struct timespec timespec_sub(struct timespec lhs,
        return ts_delta;
 }
 
+#define KTIME_MAX                      ((s64)~((u64)1 << 63))
+#if (BITS_PER_LONG == 64)
+# define KTIME_SEC_MAX                 (KTIME_MAX / NSEC_PER_SEC)
+#else
+# define KTIME_SEC_MAX                 LONG_MAX
+#endif
+
 /*
  * Returns true if the timespec is norm, false if denorm:
  */
-#define timespec_valid(ts) \
-       (((ts)->tv_sec >= 0) && (((unsigned long) (ts)->tv_nsec) < NSEC_PER_SEC))
+static inline bool timespec_valid(const struct timespec *ts)
+{
+       /* Dates before 1970 are bogus */
+       if (ts->tv_sec < 0)
+               return false;
+       /* Can't have more nanoseconds then a second */
+       if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
+               return false;
+       return true;
+}
+
+static inline bool timespec_valid_strict(const struct timespec *ts)
+{
+       if (!timespec_valid(ts))
+               return false;
+       /* Disallow values that could overflow ktime_t */
+       if ((unsigned long long)ts->tv_sec >= KTIME_SEC_MAX)
+               return false;
+       return true;
+}
 
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
index 0fa8b64c3cdbd1614dfe6e4ea12c2bdb6ceabd04..4f0667e010dd39333ef672af24969c5c6683819a 100644 (file)
 /* Backward compatibility target definitions --- to be removed. */
 #define V4L2_SEL_TGT_CROP_ACTIVE       V4L2_SEL_TGT_CROP
 #define V4L2_SEL_TGT_COMPOSE_ACTIVE    V4L2_SEL_TGT_COMPOSE
-#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL \
-       V4L2_SEL_TGT_CROP
-#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL \
-       V4L2_SEL_TGT_COMPOSE
+#define V4L2_SUBDEV_SEL_TGT_CROP_ACTUAL        V4L2_SEL_TGT_CROP
+#define V4L2_SUBDEV_SEL_TGT_COMPOSE_ACTUAL V4L2_SEL_TGT_COMPOSE
+#define V4L2_SUBDEV_SEL_TGT_CROP_BOUNDS        V4L2_SEL_TGT_CROP_BOUNDS
+#define V4L2_SUBDEV_SEL_TGT_COMPOSE_BOUNDS V4L2_SEL_TGT_COMPOSE_BOUNDS
 
 /* Selection flags */
 #define V4L2_SEL_FLAG_GE               (1 << 0)
diff --git a/include/linux/v4l2-controls.h b/include/linux/v4l2-controls.h
new file mode 100644 (file)
index 0000000..e1b3680
--- /dev/null
@@ -0,0 +1,762 @@
+/*
+ *  Video for Linux Two controls header file
+ *
+ *  Copyright (C) 1999-2012 the contributors
+ *
+ *  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.
+ *
+ *  Alternatively you can redistribute this file under the terms of the
+ *  BSD license as stated below:
+ *
+ *  Redistribution and use in source and binary forms, with or without
+ *  modification, are permitted provided that the following conditions
+ *  are met:
+ *  1. Redistributions of source code must retain the above copyright
+ *     notice, this list of conditions and the following disclaimer.
+ *  2. Redistributions in binary form must reproduce the above copyright
+ *     notice, this list of conditions and the following disclaimer in
+ *     the documentation and/or other materials provided with the
+ *     distribution.
+ *  3. The names of its contributors may not be used to endorse or promote
+ *     products derived from this software without specific prior written
+ *     permission.
+ *
+ *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ *  TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ *  PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ *  LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ *  NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ *  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ *  The contents of this header was split off from videodev2.h. All control
+ *  definitions should be added to this header, which is included by
+ *  videodev2.h.
+ */
+
+#ifndef __LINUX_V4L2_CONTROLS_H
+#define __LINUX_V4L2_CONTROLS_H
+
+/* Control classes */
+#define V4L2_CTRL_CLASS_USER           0x00980000      /* Old-style 'user' controls */
+#define V4L2_CTRL_CLASS_MPEG           0x00990000      /* MPEG-compression controls */
+#define V4L2_CTRL_CLASS_CAMERA         0x009a0000      /* Camera class controls */
+#define V4L2_CTRL_CLASS_FM_TX          0x009b0000      /* FM Modulator control class */
+#define V4L2_CTRL_CLASS_FLASH          0x009c0000      /* Camera flash controls */
+#define V4L2_CTRL_CLASS_JPEG           0x009d0000      /* JPEG-compression controls */
+#define V4L2_CTRL_CLASS_IMAGE_SOURCE   0x009e0000      /* Image source controls */
+#define V4L2_CTRL_CLASS_IMAGE_PROC     0x009f0000      /* Image processing controls */
+#define V4L2_CTRL_CLASS_DV             0x00a00000      /* Digital Video controls */
+
+/* User-class control IDs */
+
+#define V4L2_CID_BASE                  (V4L2_CTRL_CLASS_USER | 0x900)
+#define V4L2_CID_USER_BASE             V4L2_CID_BASE
+#define V4L2_CID_USER_CLASS            (V4L2_CTRL_CLASS_USER | 1)
+#define V4L2_CID_BRIGHTNESS            (V4L2_CID_BASE+0)
+#define V4L2_CID_CONTRAST              (V4L2_CID_BASE+1)
+#define V4L2_CID_SATURATION            (V4L2_CID_BASE+2)
+#define V4L2_CID_HUE                   (V4L2_CID_BASE+3)
+#define V4L2_CID_AUDIO_VOLUME          (V4L2_CID_BASE+5)
+#define V4L2_CID_AUDIO_BALANCE         (V4L2_CID_BASE+6)
+#define V4L2_CID_AUDIO_BASS            (V4L2_CID_BASE+7)
+#define V4L2_CID_AUDIO_TREBLE          (V4L2_CID_BASE+8)
+#define V4L2_CID_AUDIO_MUTE            (V4L2_CID_BASE+9)
+#define V4L2_CID_AUDIO_LOUDNESS                (V4L2_CID_BASE+10)
+#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11) /* Deprecated */
+#define V4L2_CID_AUTO_WHITE_BALANCE    (V4L2_CID_BASE+12)
+#define V4L2_CID_DO_WHITE_BALANCE      (V4L2_CID_BASE+13)
+#define V4L2_CID_RED_BALANCE           (V4L2_CID_BASE+14)
+#define V4L2_CID_BLUE_BALANCE          (V4L2_CID_BASE+15)
+#define V4L2_CID_GAMMA                 (V4L2_CID_BASE+16)
+#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* Deprecated */
+#define V4L2_CID_EXPOSURE              (V4L2_CID_BASE+17)
+#define V4L2_CID_AUTOGAIN              (V4L2_CID_BASE+18)
+#define V4L2_CID_GAIN                  (V4L2_CID_BASE+19)
+#define V4L2_CID_HFLIP                 (V4L2_CID_BASE+20)
+#define V4L2_CID_VFLIP                 (V4L2_CID_BASE+21)
+
+/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
+#define V4L2_CID_HCENTER               (V4L2_CID_BASE+22)
+#define V4L2_CID_VCENTER               (V4L2_CID_BASE+23)
+
+#define V4L2_CID_POWER_LINE_FREQUENCY  (V4L2_CID_BASE+24)
+enum v4l2_power_line_frequency {
+       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
+       V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
+       V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
+       V4L2_CID_POWER_LINE_FREQUENCY_AUTO      = 3,
+};
+#define V4L2_CID_HUE_AUTO                      (V4L2_CID_BASE+25)
+#define V4L2_CID_WHITE_BALANCE_TEMPERATURE     (V4L2_CID_BASE+26)
+#define V4L2_CID_SHARPNESS                     (V4L2_CID_BASE+27)
+#define V4L2_CID_BACKLIGHT_COMPENSATION        (V4L2_CID_BASE+28)
+#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
+#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
+#define V4L2_CID_COLORFX                       (V4L2_CID_BASE+31)
+enum v4l2_colorfx {
+       V4L2_COLORFX_NONE                       = 0,
+       V4L2_COLORFX_BW                         = 1,
+       V4L2_COLORFX_SEPIA                      = 2,
+       V4L2_COLORFX_NEGATIVE                   = 3,
+       V4L2_COLORFX_EMBOSS                     = 4,
+       V4L2_COLORFX_SKETCH                     = 5,
+       V4L2_COLORFX_SKY_BLUE                   = 6,
+       V4L2_COLORFX_GRASS_GREEN                = 7,
+       V4L2_COLORFX_SKIN_WHITEN                = 8,
+       V4L2_COLORFX_VIVID                      = 9,
+       V4L2_COLORFX_AQUA                       = 10,
+       V4L2_COLORFX_ART_FREEZE                 = 11,
+       V4L2_COLORFX_SILHOUETTE                 = 12,
+       V4L2_COLORFX_SOLARIZATION               = 13,
+       V4L2_COLORFX_ANTIQUE                    = 14,
+       V4L2_COLORFX_SET_CBCR                   = 15,
+};
+#define V4L2_CID_AUTOBRIGHTNESS                        (V4L2_CID_BASE+32)
+#define V4L2_CID_BAND_STOP_FILTER              (V4L2_CID_BASE+33)
+
+#define V4L2_CID_ROTATE                                (V4L2_CID_BASE+34)
+#define V4L2_CID_BG_COLOR                      (V4L2_CID_BASE+35)
+
+#define V4L2_CID_CHROMA_GAIN                    (V4L2_CID_BASE+36)
+
+#define V4L2_CID_ILLUMINATORS_1                        (V4L2_CID_BASE+37)
+#define V4L2_CID_ILLUMINATORS_2                        (V4L2_CID_BASE+38)
+
+#define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE       (V4L2_CID_BASE+39)
+#define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT                (V4L2_CID_BASE+40)
+
+#define V4L2_CID_ALPHA_COMPONENT               (V4L2_CID_BASE+41)
+#define V4L2_CID_COLORFX_CBCR                  (V4L2_CID_BASE+42)
+
+/* last CID + 1 */
+#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+43)
+
+
+/* MPEG-class control IDs */
+
+#define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
+#define V4L2_CID_MPEG_CLASS                    (V4L2_CTRL_CLASS_MPEG | 1)
+
+/*  MPEG streams, specific to multiplexed streams */
+#define V4L2_CID_MPEG_STREAM_TYPE              (V4L2_CID_MPEG_BASE+0)
+enum v4l2_mpeg_stream_type {
+       V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
+       V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
+};
+#define V4L2_CID_MPEG_STREAM_PID_PMT           (V4L2_CID_MPEG_BASE+1)
+#define V4L2_CID_MPEG_STREAM_PID_AUDIO                 (V4L2_CID_MPEG_BASE+2)
+#define V4L2_CID_MPEG_STREAM_PID_VIDEO                 (V4L2_CID_MPEG_BASE+3)
+#define V4L2_CID_MPEG_STREAM_PID_PCR           (V4L2_CID_MPEG_BASE+4)
+#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO      (V4L2_CID_MPEG_BASE+5)
+#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO      (V4L2_CID_MPEG_BASE+6)
+#define V4L2_CID_MPEG_STREAM_VBI_FMT           (V4L2_CID_MPEG_BASE+7)
+enum v4l2_mpeg_stream_vbi_fmt {
+       V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
+       V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
+};
+
+/*  MPEG audio controls specific to multiplexed streams  */
+#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ      (V4L2_CID_MPEG_BASE+100)
+enum v4l2_mpeg_audio_sampling_freq {
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
+       V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_ENCODING           (V4L2_CID_MPEG_BASE+101)
+enum v4l2_mpeg_audio_encoding {
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
+       V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
+       V4L2_MPEG_AUDIO_ENCODING_AAC     = 3,
+       V4L2_MPEG_AUDIO_ENCODING_AC3     = 4,
+};
+#define V4L2_CID_MPEG_AUDIO_L1_BITRATE                 (V4L2_CID_MPEG_BASE+102)
+enum v4l2_mpeg_audio_l1_bitrate {
+       V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
+       V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
+       V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
+       V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
+       V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
+       V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
+       V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
+       V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
+       V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
+       V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
+       V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
+       V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
+       V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L2_BITRATE                 (V4L2_CID_MPEG_BASE+103)
+enum v4l2_mpeg_audio_l2_bitrate {
+       V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
+       V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
+       V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
+       V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
+       V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
+       V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
+       V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
+       V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
+       V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
+       V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
+       V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
+       V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
+       V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_L3_BITRATE                 (V4L2_CID_MPEG_BASE+104)
+enum v4l2_mpeg_audio_l3_bitrate {
+       V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
+       V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
+       V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
+       V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
+       V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
+       V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
+       V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
+       V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
+       V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
+       V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
+       V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
+       V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
+       V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE               (V4L2_CID_MPEG_BASE+105)
+enum v4l2_mpeg_audio_mode {
+       V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
+       V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
+       V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
+       V4L2_MPEG_AUDIO_MODE_MONO         = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION     (V4L2_CID_MPEG_BASE+106)
+enum v4l2_mpeg_audio_mode_extension {
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
+       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
+};
+#define V4L2_CID_MPEG_AUDIO_EMPHASIS           (V4L2_CID_MPEG_BASE+107)
+enum v4l2_mpeg_audio_emphasis {
+       V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
+       V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
+       V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
+};
+#define V4L2_CID_MPEG_AUDIO_CRC                (V4L2_CID_MPEG_BASE+108)
+enum v4l2_mpeg_audio_crc {
+       V4L2_MPEG_AUDIO_CRC_NONE  = 0,
+       V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
+};
+#define V4L2_CID_MPEG_AUDIO_MUTE               (V4L2_CID_MPEG_BASE+109)
+#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE                (V4L2_CID_MPEG_BASE+110)
+#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE                (V4L2_CID_MPEG_BASE+111)
+enum v4l2_mpeg_audio_ac3_bitrate {
+       V4L2_MPEG_AUDIO_AC3_BITRATE_32K  = 0,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_40K  = 1,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_48K  = 2,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_56K  = 3,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_64K  = 4,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_80K  = 5,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_96K  = 6,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17,
+       V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
+};
+#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK       (V4L2_CID_MPEG_BASE+112)
+enum v4l2_mpeg_audio_dec_playback {
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO           = 0,
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO         = 1,
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT           = 2,
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT          = 3,
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO           = 4,
+       V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5,
+};
+#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_MPEG_BASE+113)
+
+/*  MPEG video controls specific to multiplexed streams */
+#define V4L2_CID_MPEG_VIDEO_ENCODING           (V4L2_CID_MPEG_BASE+200)
+enum v4l2_mpeg_video_encoding {
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_2     = 1,
+       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2,
+};
+#define V4L2_CID_MPEG_VIDEO_ASPECT             (V4L2_CID_MPEG_BASE+201)
+enum v4l2_mpeg_video_aspect {
+       V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
+       V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
+       V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
+       V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
+};
+#define V4L2_CID_MPEG_VIDEO_B_FRAMES           (V4L2_CID_MPEG_BASE+202)
+#define V4L2_CID_MPEG_VIDEO_GOP_SIZE           (V4L2_CID_MPEG_BASE+203)
+#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE        (V4L2_CID_MPEG_BASE+204)
+#define V4L2_CID_MPEG_VIDEO_PULLDOWN           (V4L2_CID_MPEG_BASE+205)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE       (V4L2_CID_MPEG_BASE+206)
+enum v4l2_mpeg_video_bitrate_mode {
+       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
+       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_BITRATE            (V4L2_CID_MPEG_BASE+207)
+#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK       (V4L2_CID_MPEG_BASE+208)
+#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
+#define V4L2_CID_MPEG_VIDEO_MUTE               (V4L2_CID_MPEG_BASE+210)
+#define V4L2_CID_MPEG_VIDEO_MUTE_YUV           (V4L2_CID_MPEG_BASE+211)
+#define V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE            (V4L2_CID_MPEG_BASE+212)
+#define V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER       (V4L2_CID_MPEG_BASE+213)
+#define V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB            (V4L2_CID_MPEG_BASE+214)
+#define V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE                    (V4L2_CID_MPEG_BASE+215)
+#define V4L2_CID_MPEG_VIDEO_HEADER_MODE                                (V4L2_CID_MPEG_BASE+216)
+enum v4l2_mpeg_video_header_mode {
+       V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE                    = 0,
+       V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME       = 1,
+
+};
+#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC                        (V4L2_CID_MPEG_BASE+217)
+#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE               (V4L2_CID_MPEG_BASE+218)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES      (V4L2_CID_MPEG_BASE+219)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB         (V4L2_CID_MPEG_BASE+220)
+#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE           (V4L2_CID_MPEG_BASE+221)
+enum v4l2_mpeg_video_multi_slice_mode {
+       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE         = 0,
+       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB          = 1,
+       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES       = 2,
+};
+#define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
+#define V4L2_CID_MPEG_VIDEO_DEC_PTS                    (V4L2_CID_MPEG_BASE+223)
+#define V4L2_CID_MPEG_VIDEO_DEC_FRAME                  (V4L2_CID_MPEG_BASE+224)
+
+#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
+#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
+#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP            (V4L2_CID_MPEG_BASE+302)
+#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP                        (V4L2_CID_MPEG_BASE+303)
+#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP                        (V4L2_CID_MPEG_BASE+304)
+#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP            (V4L2_CID_MPEG_BASE+350)
+#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP            (V4L2_CID_MPEG_BASE+351)
+#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP            (V4L2_CID_MPEG_BASE+352)
+#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP                        (V4L2_CID_MPEG_BASE+353)
+#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP                        (V4L2_CID_MPEG_BASE+354)
+#define V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM         (V4L2_CID_MPEG_BASE+355)
+#define V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE              (V4L2_CID_MPEG_BASE+356)
+#define V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE          (V4L2_CID_MPEG_BASE+357)
+enum v4l2_mpeg_video_h264_entropy_mode {
+       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC = 0,
+       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC = 1,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_I_PERIOD              (V4L2_CID_MPEG_BASE+358)
+#define V4L2_CID_MPEG_VIDEO_H264_LEVEL                 (V4L2_CID_MPEG_BASE+359)
+enum v4l2_mpeg_video_h264_level {
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_0  = 0,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1B   = 1,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_1  = 2,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_2  = 3,
+       V4L2_MPEG_VIDEO_H264_LEVEL_1_3  = 4,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_0  = 5,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_1  = 6,
+       V4L2_MPEG_VIDEO_H264_LEVEL_2_2  = 7,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_0  = 8,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_1  = 9,
+       V4L2_MPEG_VIDEO_H264_LEVEL_3_2  = 10,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_0  = 11,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_1  = 12,
+       V4L2_MPEG_VIDEO_H264_LEVEL_4_2  = 13,
+       V4L2_MPEG_VIDEO_H264_LEVEL_5_0  = 14,
+       V4L2_MPEG_VIDEO_H264_LEVEL_5_1  = 15,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA     (V4L2_CID_MPEG_BASE+360)
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA      (V4L2_CID_MPEG_BASE+361)
+#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE      (V4L2_CID_MPEG_BASE+362)
+enum v4l2_mpeg_video_h264_loop_filter_mode {
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED                           = 0,
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED                          = 1,
+       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY        = 2,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_PROFILE               (V4L2_CID_MPEG_BASE+363)
+enum v4l2_mpeg_video_h264_profile {
+       V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE                   = 0,
+       V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE       = 1,
+       V4L2_MPEG_VIDEO_H264_PROFILE_MAIN                       = 2,
+       V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED                   = 3,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH                       = 4,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10                    = 5,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422                   = 6,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE        = 7,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA              = 8,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA             = 9,
+       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA             = 10,
+       V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA            = 11,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE          = 12,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH              = 13,
+       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA        = 14,
+       V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH                = 15,
+       V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH             = 16,
+};
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT    (V4L2_CID_MPEG_BASE+364)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH     (V4L2_CID_MPEG_BASE+365)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE                (V4L2_CID_MPEG_BASE+366)
+#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC           (V4L2_CID_MPEG_BASE+367)
+enum v4l2_mpeg_video_h264_vui_sar_idc {
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED    = 0,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1            = 1,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11          = 2,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11          = 3,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11          = 4,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33          = 5,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11          = 6,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11          = 7,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11          = 8,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33          = 9,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11          = 10,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11          = 11,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33          = 12,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99         = 13,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3            = 14,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2            = 15,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1            = 16,
+       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED       = 17,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP   (V4L2_CID_MPEG_BASE+400)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP   (V4L2_CID_MPEG_BASE+401)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP   (V4L2_CID_MPEG_BASE+402)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP       (V4L2_CID_MPEG_BASE+403)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP       (V4L2_CID_MPEG_BASE+404)
+#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL                (V4L2_CID_MPEG_BASE+405)
+enum v4l2_mpeg_video_mpeg4_level {
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0   = 0,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B  = 1,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_1   = 2,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_2   = 3,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3   = 4,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B  = 5,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_4   = 6,
+       V4L2_MPEG_VIDEO_MPEG4_LEVEL_5   = 7,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE      (V4L2_CID_MPEG_BASE+406)
+enum v4l2_mpeg_video_mpeg4_profile {
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE                            = 0,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE                   = 1,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE                              = 2,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE                   = 3,
+       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY        = 4,
+};
+#define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL         (V4L2_CID_MPEG_BASE+407)
+
+/*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
+#define V4L2_CID_MPEG_CX2341X_BASE                             (V4L2_CTRL_CLASS_MPEG | 0x1000)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE        (V4L2_CID_MPEG_CX2341X_BASE+0)
+enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
+       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
+       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER             (V4L2_CID_MPEG_CX2341X_BASE+1)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE   (V4L2_CID_MPEG_CX2341X_BASE+2)
+enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
+       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE         (V4L2_CID_MPEG_CX2341X_BASE+3)
+enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
+       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE       (V4L2_CID_MPEG_CX2341X_BASE+4)
+enum v4l2_mpeg_cx2341x_video_temporal_filter_mode {
+       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
+       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER            (V4L2_CID_MPEG_CX2341X_BASE+5)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE                 (V4L2_CID_MPEG_CX2341X_BASE+6)
+enum v4l2_mpeg_cx2341x_video_median_filter_type {
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
+       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
+};
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM  (V4L2_CID_MPEG_CX2341X_BASE+7)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP     (V4L2_CID_MPEG_CX2341X_BASE+8)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM        (V4L2_CID_MPEG_CX2341X_BASE+9)
+#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
+#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS        (V4L2_CID_MPEG_CX2341X_BASE+11)
+
+/*  MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */
+#define V4L2_CID_MPEG_MFC51_BASE                               (V4L2_CTRL_CLASS_MPEG | 0x1100)
+
+#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY           (V4L2_CID_MPEG_MFC51_BASE+0)
+#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE    (V4L2_CID_MPEG_MFC51_BASE+1)
+#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE                      (V4L2_CID_MPEG_MFC51_BASE+2)
+enum v4l2_mpeg_mfc51_video_frame_skip_mode {
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED          = 0,
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT       = 1,
+       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT         = 2,
+};
+#define V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE                     (V4L2_CID_MPEG_MFC51_BASE+3)
+enum v4l2_mpeg_mfc51_video_force_frame_type {
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED         = 0,
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME          = 1,
+       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED        = 2,
+};
+#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING                              (V4L2_CID_MPEG_MFC51_BASE+4)
+#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV                          (V4L2_CID_MPEG_MFC51_BASE+5)
+#define V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT                  (V4L2_CID_MPEG_MFC51_BASE+6)
+#define V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF                    (V4L2_CID_MPEG_MFC51_BASE+7)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY            (V4L2_CID_MPEG_MFC51_BASE+50)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK                        (V4L2_CID_MPEG_MFC51_BASE+51)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH              (V4L2_CID_MPEG_MFC51_BASE+52)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC              (V4L2_CID_MPEG_MFC51_BASE+53)
+#define V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P               (V4L2_CID_MPEG_MFC51_BASE+54)
+
+
+/*  Camera class control IDs */
+
+#define V4L2_CID_CAMERA_CLASS_BASE     (V4L2_CTRL_CLASS_CAMERA | 0x900)
+#define V4L2_CID_CAMERA_CLASS          (V4L2_CTRL_CLASS_CAMERA | 1)
+
+#define V4L2_CID_EXPOSURE_AUTO                 (V4L2_CID_CAMERA_CLASS_BASE+1)
+enum  v4l2_exposure_auto_type {
+       V4L2_EXPOSURE_AUTO = 0,
+       V4L2_EXPOSURE_MANUAL = 1,
+       V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
+       V4L2_EXPOSURE_APERTURE_PRIORITY = 3
+};
+#define V4L2_CID_EXPOSURE_ABSOLUTE             (V4L2_CID_CAMERA_CLASS_BASE+2)
+#define V4L2_CID_EXPOSURE_AUTO_PRIORITY                (V4L2_CID_CAMERA_CLASS_BASE+3)
+
+#define V4L2_CID_PAN_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+4)
+#define V4L2_CID_TILT_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+5)
+#define V4L2_CID_PAN_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+6)
+#define V4L2_CID_TILT_RESET                    (V4L2_CID_CAMERA_CLASS_BASE+7)
+
+#define V4L2_CID_PAN_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+8)
+#define V4L2_CID_TILT_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+9)
+
+#define V4L2_CID_FOCUS_ABSOLUTE                        (V4L2_CID_CAMERA_CLASS_BASE+10)
+#define V4L2_CID_FOCUS_RELATIVE                        (V4L2_CID_CAMERA_CLASS_BASE+11)
+#define V4L2_CID_FOCUS_AUTO                    (V4L2_CID_CAMERA_CLASS_BASE+12)
+
+#define V4L2_CID_ZOOM_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+13)
+#define V4L2_CID_ZOOM_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+14)
+#define V4L2_CID_ZOOM_CONTINUOUS               (V4L2_CID_CAMERA_CLASS_BASE+15)
+
+#define V4L2_CID_PRIVACY                       (V4L2_CID_CAMERA_CLASS_BASE+16)
+
+#define V4L2_CID_IRIS_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+17)
+#define V4L2_CID_IRIS_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+18)
+
+#define V4L2_CID_AUTO_EXPOSURE_BIAS            (V4L2_CID_CAMERA_CLASS_BASE+19)
+
+#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE   (V4L2_CID_CAMERA_CLASS_BASE+20)
+enum v4l2_auto_n_preset_white_balance {
+       V4L2_WHITE_BALANCE_MANUAL               = 0,
+       V4L2_WHITE_BALANCE_AUTO                 = 1,
+       V4L2_WHITE_BALANCE_INCANDESCENT         = 2,
+       V4L2_WHITE_BALANCE_FLUORESCENT          = 3,
+       V4L2_WHITE_BALANCE_FLUORESCENT_H        = 4,
+       V4L2_WHITE_BALANCE_HORIZON              = 5,
+       V4L2_WHITE_BALANCE_DAYLIGHT             = 6,
+       V4L2_WHITE_BALANCE_FLASH                = 7,
+       V4L2_WHITE_BALANCE_CLOUDY               = 8,
+       V4L2_WHITE_BALANCE_SHADE                = 9,
+};
+
+#define V4L2_CID_WIDE_DYNAMIC_RANGE            (V4L2_CID_CAMERA_CLASS_BASE+21)
+#define V4L2_CID_IMAGE_STABILIZATION           (V4L2_CID_CAMERA_CLASS_BASE+22)
+
+#define V4L2_CID_ISO_SENSITIVITY               (V4L2_CID_CAMERA_CLASS_BASE+23)
+#define V4L2_CID_ISO_SENSITIVITY_AUTO          (V4L2_CID_CAMERA_CLASS_BASE+24)
+enum v4l2_iso_sensitivity_auto_type {
+       V4L2_ISO_SENSITIVITY_MANUAL             = 0,
+       V4L2_ISO_SENSITIVITY_AUTO               = 1,
+};
+
+#define V4L2_CID_EXPOSURE_METERING             (V4L2_CID_CAMERA_CLASS_BASE+25)
+enum v4l2_exposure_metering {
+       V4L2_EXPOSURE_METERING_AVERAGE          = 0,
+       V4L2_EXPOSURE_METERING_CENTER_WEIGHTED  = 1,
+       V4L2_EXPOSURE_METERING_SPOT             = 2,
+};
+
+#define V4L2_CID_SCENE_MODE                    (V4L2_CID_CAMERA_CLASS_BASE+26)
+enum v4l2_scene_mode {
+       V4L2_SCENE_MODE_NONE                    = 0,
+       V4L2_SCENE_MODE_BACKLIGHT               = 1,
+       V4L2_SCENE_MODE_BEACH_SNOW              = 2,
+       V4L2_SCENE_MODE_CANDLE_LIGHT            = 3,
+       V4L2_SCENE_MODE_DAWN_DUSK               = 4,
+       V4L2_SCENE_MODE_FALL_COLORS             = 5,
+       V4L2_SCENE_MODE_FIREWORKS               = 6,
+       V4L2_SCENE_MODE_LANDSCAPE               = 7,
+       V4L2_SCENE_MODE_NIGHT                   = 8,
+       V4L2_SCENE_MODE_PARTY_INDOOR            = 9,
+       V4L2_SCENE_MODE_PORTRAIT                = 10,
+       V4L2_SCENE_MODE_SPORTS                  = 11,
+       V4L2_SCENE_MODE_SUNSET                  = 12,
+       V4L2_SCENE_MODE_TEXT                    = 13,
+};
+
+#define V4L2_CID_3A_LOCK                       (V4L2_CID_CAMERA_CLASS_BASE+27)
+#define V4L2_LOCK_EXPOSURE                     (1 << 0)
+#define V4L2_LOCK_WHITE_BALANCE                        (1 << 1)
+#define V4L2_LOCK_FOCUS                                (1 << 2)
+
+#define V4L2_CID_AUTO_FOCUS_START              (V4L2_CID_CAMERA_CLASS_BASE+28)
+#define V4L2_CID_AUTO_FOCUS_STOP               (V4L2_CID_CAMERA_CLASS_BASE+29)
+#define V4L2_CID_AUTO_FOCUS_STATUS             (V4L2_CID_CAMERA_CLASS_BASE+30)
+#define V4L2_AUTO_FOCUS_STATUS_IDLE            (0 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_BUSY            (1 << 0)
+#define V4L2_AUTO_FOCUS_STATUS_REACHED         (1 << 1)
+#define V4L2_AUTO_FOCUS_STATUS_FAILED          (1 << 2)
+
+#define V4L2_CID_AUTO_FOCUS_RANGE              (V4L2_CID_CAMERA_CLASS_BASE+31)
+enum v4l2_auto_focus_range {
+       V4L2_AUTO_FOCUS_RANGE_AUTO              = 0,
+       V4L2_AUTO_FOCUS_RANGE_NORMAL            = 1,
+       V4L2_AUTO_FOCUS_RANGE_MACRO             = 2,
+       V4L2_AUTO_FOCUS_RANGE_INFINITY          = 3,
+};
+
+
+/* FM Modulator class control IDs */
+
+#define V4L2_CID_FM_TX_CLASS_BASE              (V4L2_CTRL_CLASS_FM_TX | 0x900)
+#define V4L2_CID_FM_TX_CLASS                   (V4L2_CTRL_CLASS_FM_TX | 1)
+
+#define V4L2_CID_RDS_TX_DEVIATION              (V4L2_CID_FM_TX_CLASS_BASE + 1)
+#define V4L2_CID_RDS_TX_PI                     (V4L2_CID_FM_TX_CLASS_BASE + 2)
+#define V4L2_CID_RDS_TX_PTY                    (V4L2_CID_FM_TX_CLASS_BASE + 3)
+#define V4L2_CID_RDS_TX_PS_NAME                        (V4L2_CID_FM_TX_CLASS_BASE + 5)
+#define V4L2_CID_RDS_TX_RADIO_TEXT             (V4L2_CID_FM_TX_CLASS_BASE + 6)
+
+#define V4L2_CID_AUDIO_LIMITER_ENABLED         (V4L2_CID_FM_TX_CLASS_BASE + 64)
+#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME    (V4L2_CID_FM_TX_CLASS_BASE + 65)
+#define V4L2_CID_AUDIO_LIMITER_DEVIATION       (V4L2_CID_FM_TX_CLASS_BASE + 66)
+
+#define V4L2_CID_AUDIO_COMPRESSION_ENABLED     (V4L2_CID_FM_TX_CLASS_BASE + 80)
+#define V4L2_CID_AUDIO_COMPRESSION_GAIN                (V4L2_CID_FM_TX_CLASS_BASE + 81)
+#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD   (V4L2_CID_FM_TX_CLASS_BASE + 82)
+#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83)
+#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME        (V4L2_CID_FM_TX_CLASS_BASE + 84)
+
+#define V4L2_CID_PILOT_TONE_ENABLED            (V4L2_CID_FM_TX_CLASS_BASE + 96)
+#define V4L2_CID_PILOT_TONE_DEVIATION          (V4L2_CID_FM_TX_CLASS_BASE + 97)
+#define V4L2_CID_PILOT_TONE_FREQUENCY          (V4L2_CID_FM_TX_CLASS_BASE + 98)
+
+#define V4L2_CID_TUNE_PREEMPHASIS              (V4L2_CID_FM_TX_CLASS_BASE + 112)
+enum v4l2_preemphasis {
+       V4L2_PREEMPHASIS_DISABLED       = 0,
+       V4L2_PREEMPHASIS_50_uS          = 1,
+       V4L2_PREEMPHASIS_75_uS          = 2,
+};
+#define V4L2_CID_TUNE_POWER_LEVEL              (V4L2_CID_FM_TX_CLASS_BASE + 113)
+#define V4L2_CID_TUNE_ANTENNA_CAPACITOR                (V4L2_CID_FM_TX_CLASS_BASE + 114)
+
+
+/* Flash and privacy (indicator) light controls */
+
+#define V4L2_CID_FLASH_CLASS_BASE              (V4L2_CTRL_CLASS_FLASH | 0x900)
+#define V4L2_CID_FLASH_CLASS                   (V4L2_CTRL_CLASS_FLASH | 1)
+
+#define V4L2_CID_FLASH_LED_MODE                        (V4L2_CID_FLASH_CLASS_BASE + 1)
+enum v4l2_flash_led_mode {
+       V4L2_FLASH_LED_MODE_NONE,
+       V4L2_FLASH_LED_MODE_FLASH,
+       V4L2_FLASH_LED_MODE_TORCH,
+};
+
+#define V4L2_CID_FLASH_STROBE_SOURCE           (V4L2_CID_FLASH_CLASS_BASE + 2)
+enum v4l2_flash_strobe_source {
+       V4L2_FLASH_STROBE_SOURCE_SOFTWARE,
+       V4L2_FLASH_STROBE_SOURCE_EXTERNAL,
+};
+
+#define V4L2_CID_FLASH_STROBE                  (V4L2_CID_FLASH_CLASS_BASE + 3)
+#define V4L2_CID_FLASH_STROBE_STOP             (V4L2_CID_FLASH_CLASS_BASE + 4)
+#define V4L2_CID_FLASH_STROBE_STATUS           (V4L2_CID_FLASH_CLASS_BASE + 5)
+
+#define V4L2_CID_FLASH_TIMEOUT                 (V4L2_CID_FLASH_CLASS_BASE + 6)
+#define V4L2_CID_FLASH_INTENSITY               (V4L2_CID_FLASH_CLASS_BASE + 7)
+#define V4L2_CID_FLASH_TORCH_INTENSITY         (V4L2_CID_FLASH_CLASS_BASE + 8)
+#define V4L2_CID_FLASH_INDICATOR_INTENSITY     (V4L2_CID_FLASH_CLASS_BASE + 9)
+
+#define V4L2_CID_FLASH_FAULT                   (V4L2_CID_FLASH_CLASS_BASE + 10)
+#define V4L2_FLASH_FAULT_OVER_VOLTAGE          (1 << 0)
+#define V4L2_FLASH_FAULT_TIMEOUT               (1 << 1)
+#define V4L2_FLASH_FAULT_OVER_TEMPERATURE      (1 << 2)
+#define V4L2_FLASH_FAULT_SHORT_CIRCUIT         (1 << 3)
+#define V4L2_FLASH_FAULT_OVER_CURRENT          (1 << 4)
+#define V4L2_FLASH_FAULT_INDICATOR             (1 << 5)
+
+#define V4L2_CID_FLASH_CHARGE                  (V4L2_CID_FLASH_CLASS_BASE + 11)
+#define V4L2_CID_FLASH_READY                   (V4L2_CID_FLASH_CLASS_BASE + 12)
+
+
+/* JPEG-class control IDs */
+
+#define V4L2_CID_JPEG_CLASS_BASE               (V4L2_CTRL_CLASS_JPEG | 0x900)
+#define V4L2_CID_JPEG_CLASS                    (V4L2_CTRL_CLASS_JPEG | 1)
+
+#define        V4L2_CID_JPEG_CHROMA_SUBSAMPLING        (V4L2_CID_JPEG_CLASS_BASE + 1)
+enum v4l2_jpeg_chroma_subsampling {
+       V4L2_JPEG_CHROMA_SUBSAMPLING_444        = 0,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_422        = 1,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_420        = 2,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_411        = 3,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_410        = 4,
+       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY       = 5,
+};
+#define        V4L2_CID_JPEG_RESTART_INTERVAL          (V4L2_CID_JPEG_CLASS_BASE + 2)
+#define        V4L2_CID_JPEG_COMPRESSION_QUALITY       (V4L2_CID_JPEG_CLASS_BASE + 3)
+
+#define        V4L2_CID_JPEG_ACTIVE_MARKER             (V4L2_CID_JPEG_CLASS_BASE + 4)
+#define        V4L2_JPEG_ACTIVE_MARKER_APP0            (1 << 0)
+#define        V4L2_JPEG_ACTIVE_MARKER_APP1            (1 << 1)
+#define        V4L2_JPEG_ACTIVE_MARKER_COM             (1 << 16)
+#define        V4L2_JPEG_ACTIVE_MARKER_DQT             (1 << 17)
+#define        V4L2_JPEG_ACTIVE_MARKER_DHT             (1 << 18)
+
+/* Image source controls */
+#define V4L2_CID_IMAGE_SOURCE_CLASS_BASE       (V4L2_CTRL_CLASS_IMAGE_SOURCE | 0x900)
+#define V4L2_CID_IMAGE_SOURCE_CLASS            (V4L2_CTRL_CLASS_IMAGE_SOURCE | 1)
+
+#define V4L2_CID_VBLANK                                (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 1)
+#define V4L2_CID_HBLANK                                (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 2)
+#define V4L2_CID_ANALOGUE_GAIN                 (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 3)
+
+
+/* Image processing controls */
+
+#define V4L2_CID_IMAGE_PROC_CLASS_BASE         (V4L2_CTRL_CLASS_IMAGE_PROC | 0x900)
+#define V4L2_CID_IMAGE_PROC_CLASS              (V4L2_CTRL_CLASS_IMAGE_PROC | 1)
+
+#define V4L2_CID_LINK_FREQ                     (V4L2_CID_IMAGE_PROC_CLASS_BASE + 1)
+#define V4L2_CID_PIXEL_RATE                    (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2)
+#define V4L2_CID_TEST_PATTERN                  (V4L2_CID_IMAGE_PROC_CLASS_BASE + 3)
+
+#endif
index 5ea7f753a3488757ab7f2a06132fd7a8b2ce46e8..7d64e0e1a18b2543b7bc35ad20e202e6b1282d60 100644 (file)
@@ -92,6 +92,11 @@ enum v4l2_mbus_pixelcode {
 
        /* JPEG compressed formats - next is 0x4002 */
        V4L2_MBUS_FMT_JPEG_1X8 = 0x4001,
+
+       /* Vendor specific formats - next is 0x5002 */
+
+       /* S5C73M3 sensor specific interleaved UYVY and JPEG */
+       V4L2_MBUS_FMT_S5C_UYVY_JPEG_1X8 = 0x5001,
 };
 
 /**
index 8c57ee9872bb429ea6e27cbe839326e9281ecd1f..a33c4daadce31dbe2cc1011053fd8cab2f28ead6 100644 (file)
@@ -148,6 +148,14 @@ struct v4l2_subdev_selection {
        __u32 reserved[8];
 };
 
+struct v4l2_subdev_edid {
+       __u32 pad;
+       __u32 start_block;
+       __u32 blocks;
+       __u32 reserved[5];
+       __u8 __user *edid;
+};
+
 #define VIDIOC_SUBDEV_G_FMT    _IOWR('V',  4, struct v4l2_subdev_format)
 #define VIDIOC_SUBDEV_S_FMT    _IOWR('V',  5, struct v4l2_subdev_format)
 #define VIDIOC_SUBDEV_G_FRAME_INTERVAL \
@@ -166,5 +174,7 @@ struct v4l2_subdev_selection {
        _IOWR('V', 61, struct v4l2_subdev_selection)
 #define VIDIOC_SUBDEV_S_SELECTION \
        _IOWR('V', 62, struct v4l2_subdev_selection)
+#define VIDIOC_SUBDEV_G_EDID   _IOWR('V', 40, struct v4l2_subdev_edid)
+#define VIDIOC_SUBDEV_S_EDID   _IOWR('V', 41, struct v4l2_subdev_edid)
 
 #endif
index 7a147c8299ab36c5c289a8396664fa3be6fd377e..80977d6ec9bcd96bcc2498cbbeea035ab4d57508 100644 (file)
@@ -1,7 +1,7 @@
 /*
  *  Video for Linux Two header file
  *
- *  Copyright (C) 1999-2007 the contributors
+ *  Copyright (C) 1999-2012 the contributors
  *
  *  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
@@ -65,6 +65,7 @@
 #include <linux/ioctl.h>
 #include <linux/types.h>
 #include <linux/v4l2-common.h>
+#include <linux/v4l2-controls.h>
 
 /*
  * Common stuff for both V4L1 and V4L2
@@ -161,6 +162,7 @@ enum v4l2_buf_type {
 #endif
        V4L2_BUF_TYPE_VIDEO_CAPTURE_MPLANE = 9,
        V4L2_BUF_TYPE_VIDEO_OUTPUT_MPLANE  = 10,
+       /* Deprecated, do not use */
        V4L2_BUF_TYPE_PRIVATE              = 0x80,
 };
 
@@ -368,6 +370,7 @@ struct v4l2_pix_format {
 
 /* three non contiguous planes - Y, Cb, Cr */
 #define V4L2_PIX_FMT_YUV420M v4l2_fourcc('Y', 'M', '1', '2') /* 12  YUV420 planar */
+#define V4L2_PIX_FMT_YVU420M v4l2_fourcc('Y', 'M', '2', '1') /* 12  YVU420 planar */
 
 /* Bayer formats - see http://www.siliconimaging.com/RGB%20Bayer.htm */
 #define V4L2_PIX_FMT_SBGGR8  v4l2_fourcc('B', 'A', '8', '1') /*  8  BGBG.. GRGR.. */
@@ -434,6 +437,7 @@ struct v4l2_pix_format {
 #define V4L2_PIX_FMT_KONICA420  v4l2_fourcc('K', 'O', 'N', 'I') /* YUV420 planar in blocks of 256 pixels */
 #define V4L2_PIX_FMT_JPGL      v4l2_fourcc('J', 'P', 'G', 'L') /* JPEG-Lite */
 #define V4L2_PIX_FMT_SE401      v4l2_fourcc('S', '4', '0', '1') /* se401 janggu compressed rgb */
+#define V4L2_PIX_FMT_S5C_UYVY_JPG v4l2_fourcc('S', '5', 'C', 'I') /* S5C73M3 interleaved UYVY/JPEG */
 
 /*
  *     F O R M A T   E N U M E R A T I O N
@@ -1188,7 +1192,8 @@ struct v4l2_input {
 
 /* capabilities flags */
 #define V4L2_IN_CAP_PRESETS            0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_IN_CAP_CUSTOM_TIMINGS     0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_IN_CAP_DV_TIMINGS         0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_IN_CAP_CUSTOM_TIMINGS     V4L2_IN_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_IN_CAP_STD                        0x00000004 /* Supports S_STD */
 
 /*
@@ -1211,7 +1216,8 @@ struct v4l2_output {
 
 /* capabilities flags */
 #define V4L2_OUT_CAP_PRESETS           0x00000001 /* Supports S_DV_PRESET */
-#define V4L2_OUT_CAP_CUSTOM_TIMINGS    0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_OUT_CAP_DV_TIMINGS                0x00000002 /* Supports S_DV_TIMINGS */
+#define V4L2_OUT_CAP_CUSTOM_TIMINGS    V4L2_OUT_CAP_DV_TIMINGS /* For compatibility */
 #define V4L2_OUT_CAP_STD               0x00000004 /* Supports S_STD */
 
 /*
@@ -1241,16 +1247,6 @@ struct v4l2_ext_controls {
        struct v4l2_ext_control *controls;
 };
 
-/*  Values for ctrl_class field */
-#define V4L2_CTRL_CLASS_USER 0x00980000        /* Old-style 'user' controls */
-#define V4L2_CTRL_CLASS_MPEG 0x00990000        /* MPEG-compression controls */
-#define V4L2_CTRL_CLASS_CAMERA 0x009a0000      /* Camera class controls */
-#define V4L2_CTRL_CLASS_FM_TX 0x009b0000       /* FM Modulator control class */
-#define V4L2_CTRL_CLASS_FLASH 0x009c0000       /* Camera flash controls */
-#define V4L2_CTRL_CLASS_JPEG 0x009d0000                /* JPEG-compression controls */
-#define V4L2_CTRL_CLASS_IMAGE_SOURCE 0x009e0000        /* Image source controls */
-#define V4L2_CTRL_CLASS_IMAGE_PROC 0x009f0000  /* Image processing controls */
-
 #define V4L2_CTRL_ID_MASK                (0x0fffffff)
 #define V4L2_CTRL_ID2CLASS(id)    ((id) & 0x0fff0000UL)
 #define V4L2_CTRL_DRIVER_PRIV(id) (((id) & 0xffff) >= 0x1000)
@@ -1306,692 +1302,31 @@ struct v4l2_querymenu {
 
 /*  User-class control IDs defined by V4L2 */
 #define V4L2_CID_MAX_CTRLS             1024
-#define V4L2_CID_BASE                  (V4L2_CTRL_CLASS_USER | 0x900)
-#define V4L2_CID_USER_BASE             V4L2_CID_BASE
 /*  IDs reserved for driver specific controls */
 #define V4L2_CID_PRIVATE_BASE          0x08000000
 
-#define V4L2_CID_USER_CLASS            (V4L2_CTRL_CLASS_USER | 1)
-#define V4L2_CID_BRIGHTNESS            (V4L2_CID_BASE+0)
-#define V4L2_CID_CONTRAST              (V4L2_CID_BASE+1)
-#define V4L2_CID_SATURATION            (V4L2_CID_BASE+2)
-#define V4L2_CID_HUE                   (V4L2_CID_BASE+3)
-#define V4L2_CID_AUDIO_VOLUME          (V4L2_CID_BASE+5)
-#define V4L2_CID_AUDIO_BALANCE         (V4L2_CID_BASE+6)
-#define V4L2_CID_AUDIO_BASS            (V4L2_CID_BASE+7)
-#define V4L2_CID_AUDIO_TREBLE          (V4L2_CID_BASE+8)
-#define V4L2_CID_AUDIO_MUTE            (V4L2_CID_BASE+9)
-#define V4L2_CID_AUDIO_LOUDNESS                (V4L2_CID_BASE+10)
-#define V4L2_CID_BLACK_LEVEL           (V4L2_CID_BASE+11) /* Deprecated */
-#define V4L2_CID_AUTO_WHITE_BALANCE    (V4L2_CID_BASE+12)
-#define V4L2_CID_DO_WHITE_BALANCE      (V4L2_CID_BASE+13)
-#define V4L2_CID_RED_BALANCE           (V4L2_CID_BASE+14)
-#define V4L2_CID_BLUE_BALANCE          (V4L2_CID_BASE+15)
-#define V4L2_CID_GAMMA                 (V4L2_CID_BASE+16)
-#define V4L2_CID_WHITENESS             (V4L2_CID_GAMMA) /* Deprecated */
-#define V4L2_CID_EXPOSURE              (V4L2_CID_BASE+17)
-#define V4L2_CID_AUTOGAIN              (V4L2_CID_BASE+18)
-#define V4L2_CID_GAIN                  (V4L2_CID_BASE+19)
-#define V4L2_CID_HFLIP                 (V4L2_CID_BASE+20)
-#define V4L2_CID_VFLIP                 (V4L2_CID_BASE+21)
-
-/* Deprecated; use V4L2_CID_PAN_RESET and V4L2_CID_TILT_RESET */
-#define V4L2_CID_HCENTER               (V4L2_CID_BASE+22)
-#define V4L2_CID_VCENTER               (V4L2_CID_BASE+23)
-
-#define V4L2_CID_POWER_LINE_FREQUENCY  (V4L2_CID_BASE+24)
-enum v4l2_power_line_frequency {
-       V4L2_CID_POWER_LINE_FREQUENCY_DISABLED  = 0,
-       V4L2_CID_POWER_LINE_FREQUENCY_50HZ      = 1,
-       V4L2_CID_POWER_LINE_FREQUENCY_60HZ      = 2,
-       V4L2_CID_POWER_LINE_FREQUENCY_AUTO      = 3,
-};
-#define V4L2_CID_HUE_AUTO                      (V4L2_CID_BASE+25)
-#define V4L2_CID_WHITE_BALANCE_TEMPERATURE     (V4L2_CID_BASE+26)
-#define V4L2_CID_SHARPNESS                     (V4L2_CID_BASE+27)
-#define V4L2_CID_BACKLIGHT_COMPENSATION        (V4L2_CID_BASE+28)
-#define V4L2_CID_CHROMA_AGC                     (V4L2_CID_BASE+29)
-#define V4L2_CID_COLOR_KILLER                   (V4L2_CID_BASE+30)
-#define V4L2_CID_COLORFX                       (V4L2_CID_BASE+31)
-enum v4l2_colorfx {
-       V4L2_COLORFX_NONE                       = 0,
-       V4L2_COLORFX_BW                         = 1,
-       V4L2_COLORFX_SEPIA                      = 2,
-       V4L2_COLORFX_NEGATIVE                   = 3,
-       V4L2_COLORFX_EMBOSS                     = 4,
-       V4L2_COLORFX_SKETCH                     = 5,
-       V4L2_COLORFX_SKY_BLUE                   = 6,
-       V4L2_COLORFX_GRASS_GREEN                = 7,
-       V4L2_COLORFX_SKIN_WHITEN                = 8,
-       V4L2_COLORFX_VIVID                      = 9,
-       V4L2_COLORFX_AQUA                       = 10,
-       V4L2_COLORFX_ART_FREEZE                 = 11,
-       V4L2_COLORFX_SILHOUETTE                 = 12,
-       V4L2_COLORFX_SOLARIZATION               = 13,
-       V4L2_COLORFX_ANTIQUE                    = 14,
-       V4L2_COLORFX_SET_CBCR                   = 15,
-};
-#define V4L2_CID_AUTOBRIGHTNESS                        (V4L2_CID_BASE+32)
-#define V4L2_CID_BAND_STOP_FILTER              (V4L2_CID_BASE+33)
-
-#define V4L2_CID_ROTATE                                (V4L2_CID_BASE+34)
-#define V4L2_CID_BG_COLOR                      (V4L2_CID_BASE+35)
-
-#define V4L2_CID_CHROMA_GAIN                    (V4L2_CID_BASE+36)
-
-#define V4L2_CID_ILLUMINATORS_1                        (V4L2_CID_BASE+37)
-#define V4L2_CID_ILLUMINATORS_2                        (V4L2_CID_BASE+38)
-
-#define V4L2_CID_MIN_BUFFERS_FOR_CAPTURE       (V4L2_CID_BASE+39)
-#define V4L2_CID_MIN_BUFFERS_FOR_OUTPUT                (V4L2_CID_BASE+40)
-
-#define V4L2_CID_ALPHA_COMPONENT               (V4L2_CID_BASE+41)
-#define V4L2_CID_COLORFX_CBCR                  (V4L2_CID_BASE+42)
-
-/* last CID + 1 */
-#define V4L2_CID_LASTP1                         (V4L2_CID_BASE+43)
-
-/*  MPEG-class control IDs defined by V4L2 */
-#define V4L2_CID_MPEG_BASE                     (V4L2_CTRL_CLASS_MPEG | 0x900)
-#define V4L2_CID_MPEG_CLASS                    (V4L2_CTRL_CLASS_MPEG | 1)
-
-/*  MPEG streams, specific to multiplexed streams */
-#define V4L2_CID_MPEG_STREAM_TYPE              (V4L2_CID_MPEG_BASE+0)
-enum v4l2_mpeg_stream_type {
-       V4L2_MPEG_STREAM_TYPE_MPEG2_PS   = 0, /* MPEG-2 program stream */
-       V4L2_MPEG_STREAM_TYPE_MPEG2_TS   = 1, /* MPEG-2 transport stream */
-       V4L2_MPEG_STREAM_TYPE_MPEG1_SS   = 2, /* MPEG-1 system stream */
-       V4L2_MPEG_STREAM_TYPE_MPEG2_DVD  = 3, /* MPEG-2 DVD-compatible stream */
-       V4L2_MPEG_STREAM_TYPE_MPEG1_VCD  = 4, /* MPEG-1 VCD-compatible stream */
-       V4L2_MPEG_STREAM_TYPE_MPEG2_SVCD = 5, /* MPEG-2 SVCD-compatible stream */
-};
-#define V4L2_CID_MPEG_STREAM_PID_PMT           (V4L2_CID_MPEG_BASE+1)
-#define V4L2_CID_MPEG_STREAM_PID_AUDIO                 (V4L2_CID_MPEG_BASE+2)
-#define V4L2_CID_MPEG_STREAM_PID_VIDEO                 (V4L2_CID_MPEG_BASE+3)
-#define V4L2_CID_MPEG_STREAM_PID_PCR           (V4L2_CID_MPEG_BASE+4)
-#define V4L2_CID_MPEG_STREAM_PES_ID_AUDIO      (V4L2_CID_MPEG_BASE+5)
-#define V4L2_CID_MPEG_STREAM_PES_ID_VIDEO      (V4L2_CID_MPEG_BASE+6)
-#define V4L2_CID_MPEG_STREAM_VBI_FMT           (V4L2_CID_MPEG_BASE+7)
-enum v4l2_mpeg_stream_vbi_fmt {
-       V4L2_MPEG_STREAM_VBI_FMT_NONE = 0,  /* No VBI in the MPEG stream */
-       V4L2_MPEG_STREAM_VBI_FMT_IVTV = 1,  /* VBI in private packets, IVTV format */
-};
-
-/*  MPEG audio controls specific to multiplexed streams  */
-#define V4L2_CID_MPEG_AUDIO_SAMPLING_FREQ      (V4L2_CID_MPEG_BASE+100)
-enum v4l2_mpeg_audio_sampling_freq {
-       V4L2_MPEG_AUDIO_SAMPLING_FREQ_44100 = 0,
-       V4L2_MPEG_AUDIO_SAMPLING_FREQ_48000 = 1,
-       V4L2_MPEG_AUDIO_SAMPLING_FREQ_32000 = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_ENCODING           (V4L2_CID_MPEG_BASE+101)
-enum v4l2_mpeg_audio_encoding {
-       V4L2_MPEG_AUDIO_ENCODING_LAYER_1 = 0,
-       V4L2_MPEG_AUDIO_ENCODING_LAYER_2 = 1,
-       V4L2_MPEG_AUDIO_ENCODING_LAYER_3 = 2,
-       V4L2_MPEG_AUDIO_ENCODING_AAC     = 3,
-       V4L2_MPEG_AUDIO_ENCODING_AC3     = 4,
-};
-#define V4L2_CID_MPEG_AUDIO_L1_BITRATE                 (V4L2_CID_MPEG_BASE+102)
-enum v4l2_mpeg_audio_l1_bitrate {
-       V4L2_MPEG_AUDIO_L1_BITRATE_32K  = 0,
-       V4L2_MPEG_AUDIO_L1_BITRATE_64K  = 1,
-       V4L2_MPEG_AUDIO_L1_BITRATE_96K  = 2,
-       V4L2_MPEG_AUDIO_L1_BITRATE_128K = 3,
-       V4L2_MPEG_AUDIO_L1_BITRATE_160K = 4,
-       V4L2_MPEG_AUDIO_L1_BITRATE_192K = 5,
-       V4L2_MPEG_AUDIO_L1_BITRATE_224K = 6,
-       V4L2_MPEG_AUDIO_L1_BITRATE_256K = 7,
-       V4L2_MPEG_AUDIO_L1_BITRATE_288K = 8,
-       V4L2_MPEG_AUDIO_L1_BITRATE_320K = 9,
-       V4L2_MPEG_AUDIO_L1_BITRATE_352K = 10,
-       V4L2_MPEG_AUDIO_L1_BITRATE_384K = 11,
-       V4L2_MPEG_AUDIO_L1_BITRATE_416K = 12,
-       V4L2_MPEG_AUDIO_L1_BITRATE_448K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L2_BITRATE                 (V4L2_CID_MPEG_BASE+103)
-enum v4l2_mpeg_audio_l2_bitrate {
-       V4L2_MPEG_AUDIO_L2_BITRATE_32K  = 0,
-       V4L2_MPEG_AUDIO_L2_BITRATE_48K  = 1,
-       V4L2_MPEG_AUDIO_L2_BITRATE_56K  = 2,
-       V4L2_MPEG_AUDIO_L2_BITRATE_64K  = 3,
-       V4L2_MPEG_AUDIO_L2_BITRATE_80K  = 4,
-       V4L2_MPEG_AUDIO_L2_BITRATE_96K  = 5,
-       V4L2_MPEG_AUDIO_L2_BITRATE_112K = 6,
-       V4L2_MPEG_AUDIO_L2_BITRATE_128K = 7,
-       V4L2_MPEG_AUDIO_L2_BITRATE_160K = 8,
-       V4L2_MPEG_AUDIO_L2_BITRATE_192K = 9,
-       V4L2_MPEG_AUDIO_L2_BITRATE_224K = 10,
-       V4L2_MPEG_AUDIO_L2_BITRATE_256K = 11,
-       V4L2_MPEG_AUDIO_L2_BITRATE_320K = 12,
-       V4L2_MPEG_AUDIO_L2_BITRATE_384K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_L3_BITRATE                 (V4L2_CID_MPEG_BASE+104)
-enum v4l2_mpeg_audio_l3_bitrate {
-       V4L2_MPEG_AUDIO_L3_BITRATE_32K  = 0,
-       V4L2_MPEG_AUDIO_L3_BITRATE_40K  = 1,
-       V4L2_MPEG_AUDIO_L3_BITRATE_48K  = 2,
-       V4L2_MPEG_AUDIO_L3_BITRATE_56K  = 3,
-       V4L2_MPEG_AUDIO_L3_BITRATE_64K  = 4,
-       V4L2_MPEG_AUDIO_L3_BITRATE_80K  = 5,
-       V4L2_MPEG_AUDIO_L3_BITRATE_96K  = 6,
-       V4L2_MPEG_AUDIO_L3_BITRATE_112K = 7,
-       V4L2_MPEG_AUDIO_L3_BITRATE_128K = 8,
-       V4L2_MPEG_AUDIO_L3_BITRATE_160K = 9,
-       V4L2_MPEG_AUDIO_L3_BITRATE_192K = 10,
-       V4L2_MPEG_AUDIO_L3_BITRATE_224K = 11,
-       V4L2_MPEG_AUDIO_L3_BITRATE_256K = 12,
-       V4L2_MPEG_AUDIO_L3_BITRATE_320K = 13,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE               (V4L2_CID_MPEG_BASE+105)
-enum v4l2_mpeg_audio_mode {
-       V4L2_MPEG_AUDIO_MODE_STEREO       = 0,
-       V4L2_MPEG_AUDIO_MODE_JOINT_STEREO = 1,
-       V4L2_MPEG_AUDIO_MODE_DUAL         = 2,
-       V4L2_MPEG_AUDIO_MODE_MONO         = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_MODE_EXTENSION     (V4L2_CID_MPEG_BASE+106)
-enum v4l2_mpeg_audio_mode_extension {
-       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_4  = 0,
-       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_8  = 1,
-       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_12 = 2,
-       V4L2_MPEG_AUDIO_MODE_EXTENSION_BOUND_16 = 3,
-};
-#define V4L2_CID_MPEG_AUDIO_EMPHASIS           (V4L2_CID_MPEG_BASE+107)
-enum v4l2_mpeg_audio_emphasis {
-       V4L2_MPEG_AUDIO_EMPHASIS_NONE         = 0,
-       V4L2_MPEG_AUDIO_EMPHASIS_50_DIV_15_uS = 1,
-       V4L2_MPEG_AUDIO_EMPHASIS_CCITT_J17    = 2,
-};
-#define V4L2_CID_MPEG_AUDIO_CRC                (V4L2_CID_MPEG_BASE+108)
-enum v4l2_mpeg_audio_crc {
-       V4L2_MPEG_AUDIO_CRC_NONE  = 0,
-       V4L2_MPEG_AUDIO_CRC_CRC16 = 1,
-};
-#define V4L2_CID_MPEG_AUDIO_MUTE               (V4L2_CID_MPEG_BASE+109)
-#define V4L2_CID_MPEG_AUDIO_AAC_BITRATE                (V4L2_CID_MPEG_BASE+110)
-#define V4L2_CID_MPEG_AUDIO_AC3_BITRATE                (V4L2_CID_MPEG_BASE+111)
-enum v4l2_mpeg_audio_ac3_bitrate {
-       V4L2_MPEG_AUDIO_AC3_BITRATE_32K  = 0,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_40K  = 1,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_48K  = 2,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_56K  = 3,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_64K  = 4,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_80K  = 5,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_96K  = 6,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_112K = 7,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_128K = 8,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_160K = 9,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_192K = 10,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_224K = 11,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_256K = 12,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_320K = 13,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_384K = 14,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_448K = 15,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_512K = 16,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_576K = 17,
-       V4L2_MPEG_AUDIO_AC3_BITRATE_640K = 18,
-};
-#define V4L2_CID_MPEG_AUDIO_DEC_PLAYBACK       (V4L2_CID_MPEG_BASE+112)
-enum v4l2_mpeg_audio_dec_playback {
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_AUTO           = 0,
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_STEREO         = 1,
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_LEFT           = 2,
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_RIGHT          = 3,
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_MONO           = 4,
-       V4L2_MPEG_AUDIO_DEC_PLAYBACK_SWAPPED_STEREO = 5,
-};
-#define V4L2_CID_MPEG_AUDIO_DEC_MULTILINGUAL_PLAYBACK (V4L2_CID_MPEG_BASE+113)
-
-/*  MPEG video controls specific to multiplexed streams */
-#define V4L2_CID_MPEG_VIDEO_ENCODING           (V4L2_CID_MPEG_BASE+200)
-enum v4l2_mpeg_video_encoding {
-       V4L2_MPEG_VIDEO_ENCODING_MPEG_1     = 0,
-       V4L2_MPEG_VIDEO_ENCODING_MPEG_2     = 1,
-       V4L2_MPEG_VIDEO_ENCODING_MPEG_4_AVC = 2,
-};
-#define V4L2_CID_MPEG_VIDEO_ASPECT             (V4L2_CID_MPEG_BASE+201)
-enum v4l2_mpeg_video_aspect {
-       V4L2_MPEG_VIDEO_ASPECT_1x1     = 0,
-       V4L2_MPEG_VIDEO_ASPECT_4x3     = 1,
-       V4L2_MPEG_VIDEO_ASPECT_16x9    = 2,
-       V4L2_MPEG_VIDEO_ASPECT_221x100 = 3,
-};
-#define V4L2_CID_MPEG_VIDEO_B_FRAMES           (V4L2_CID_MPEG_BASE+202)
-#define V4L2_CID_MPEG_VIDEO_GOP_SIZE           (V4L2_CID_MPEG_BASE+203)
-#define V4L2_CID_MPEG_VIDEO_GOP_CLOSURE        (V4L2_CID_MPEG_BASE+204)
-#define V4L2_CID_MPEG_VIDEO_PULLDOWN           (V4L2_CID_MPEG_BASE+205)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_MODE       (V4L2_CID_MPEG_BASE+206)
-enum v4l2_mpeg_video_bitrate_mode {
-       V4L2_MPEG_VIDEO_BITRATE_MODE_VBR = 0,
-       V4L2_MPEG_VIDEO_BITRATE_MODE_CBR = 1,
-};
-#define V4L2_CID_MPEG_VIDEO_BITRATE            (V4L2_CID_MPEG_BASE+207)
-#define V4L2_CID_MPEG_VIDEO_BITRATE_PEAK       (V4L2_CID_MPEG_BASE+208)
-#define V4L2_CID_MPEG_VIDEO_TEMPORAL_DECIMATION (V4L2_CID_MPEG_BASE+209)
-#define V4L2_CID_MPEG_VIDEO_MUTE               (V4L2_CID_MPEG_BASE+210)
-#define V4L2_CID_MPEG_VIDEO_MUTE_YUV           (V4L2_CID_MPEG_BASE+211)
-#define V4L2_CID_MPEG_VIDEO_DECODER_SLICE_INTERFACE            (V4L2_CID_MPEG_BASE+212)
-#define V4L2_CID_MPEG_VIDEO_DECODER_MPEG4_DEBLOCK_FILTER       (V4L2_CID_MPEG_BASE+213)
-#define V4L2_CID_MPEG_VIDEO_CYCLIC_INTRA_REFRESH_MB            (V4L2_CID_MPEG_BASE+214)
-#define V4L2_CID_MPEG_VIDEO_FRAME_RC_ENABLE                    (V4L2_CID_MPEG_BASE+215)
-#define V4L2_CID_MPEG_VIDEO_HEADER_MODE                                (V4L2_CID_MPEG_BASE+216)
-enum v4l2_mpeg_video_header_mode {
-       V4L2_MPEG_VIDEO_HEADER_MODE_SEPARATE                    = 0,
-       V4L2_MPEG_VIDEO_HEADER_MODE_JOINED_WITH_1ST_FRAME       = 1,
-
-};
-#define V4L2_CID_MPEG_VIDEO_MAX_REF_PIC                        (V4L2_CID_MPEG_BASE+217)
-#define V4L2_CID_MPEG_VIDEO_MB_RC_ENABLE               (V4L2_CID_MPEG_BASE+218)
-#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_BYTES      (V4L2_CID_MPEG_BASE+219)
-#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MAX_MB         (V4L2_CID_MPEG_BASE+220)
-#define V4L2_CID_MPEG_VIDEO_MULTI_SLICE_MODE           (V4L2_CID_MPEG_BASE+221)
-enum v4l2_mpeg_video_multi_slice_mode {
-       V4L2_MPEG_VIDEO_MULTI_SLICE_MODE_SINGLE         = 0,
-       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_MB          = 1,
-       V4L2_MPEG_VIDEO_MULTI_SICE_MODE_MAX_BYTES       = 2,
-};
-#define V4L2_CID_MPEG_VIDEO_VBV_SIZE                   (V4L2_CID_MPEG_BASE+222)
-#define V4L2_CID_MPEG_VIDEO_DEC_PTS                    (V4L2_CID_MPEG_BASE+223)
-#define V4L2_CID_MPEG_VIDEO_DEC_FRAME                  (V4L2_CID_MPEG_BASE+224)
-
-#define V4L2_CID_MPEG_VIDEO_H263_I_FRAME_QP            (V4L2_CID_MPEG_BASE+300)
-#define V4L2_CID_MPEG_VIDEO_H263_P_FRAME_QP            (V4L2_CID_MPEG_BASE+301)
-#define V4L2_CID_MPEG_VIDEO_H263_B_FRAME_QP            (V4L2_CID_MPEG_BASE+302)
-#define V4L2_CID_MPEG_VIDEO_H263_MIN_QP                        (V4L2_CID_MPEG_BASE+303)
-#define V4L2_CID_MPEG_VIDEO_H263_MAX_QP                        (V4L2_CID_MPEG_BASE+304)
-#define V4L2_CID_MPEG_VIDEO_H264_I_FRAME_QP            (V4L2_CID_MPEG_BASE+350)
-#define V4L2_CID_MPEG_VIDEO_H264_P_FRAME_QP            (V4L2_CID_MPEG_BASE+351)
-#define V4L2_CID_MPEG_VIDEO_H264_B_FRAME_QP            (V4L2_CID_MPEG_BASE+352)
-#define V4L2_CID_MPEG_VIDEO_H264_MIN_QP                        (V4L2_CID_MPEG_BASE+353)
-#define V4L2_CID_MPEG_VIDEO_H264_MAX_QP                        (V4L2_CID_MPEG_BASE+354)
-#define V4L2_CID_MPEG_VIDEO_H264_8X8_TRANSFORM         (V4L2_CID_MPEG_BASE+355)
-#define V4L2_CID_MPEG_VIDEO_H264_CPB_SIZE              (V4L2_CID_MPEG_BASE+356)
-#define V4L2_CID_MPEG_VIDEO_H264_ENTROPY_MODE          (V4L2_CID_MPEG_BASE+357)
-enum v4l2_mpeg_video_h264_entropy_mode {
-       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CAVLC = 0,
-       V4L2_MPEG_VIDEO_H264_ENTROPY_MODE_CABAC = 1,
-};
-#define V4L2_CID_MPEG_VIDEO_H264_I_PERIOD              (V4L2_CID_MPEG_BASE+358)
-#define V4L2_CID_MPEG_VIDEO_H264_LEVEL                 (V4L2_CID_MPEG_BASE+359)
-enum v4l2_mpeg_video_h264_level {
-       V4L2_MPEG_VIDEO_H264_LEVEL_1_0  = 0,
-       V4L2_MPEG_VIDEO_H264_LEVEL_1B   = 1,
-       V4L2_MPEG_VIDEO_H264_LEVEL_1_1  = 2,
-       V4L2_MPEG_VIDEO_H264_LEVEL_1_2  = 3,
-       V4L2_MPEG_VIDEO_H264_LEVEL_1_3  = 4,
-       V4L2_MPEG_VIDEO_H264_LEVEL_2_0  = 5,
-       V4L2_MPEG_VIDEO_H264_LEVEL_2_1  = 6,
-       V4L2_MPEG_VIDEO_H264_LEVEL_2_2  = 7,
-       V4L2_MPEG_VIDEO_H264_LEVEL_3_0  = 8,
-       V4L2_MPEG_VIDEO_H264_LEVEL_3_1  = 9,
-       V4L2_MPEG_VIDEO_H264_LEVEL_3_2  = 10,
-       V4L2_MPEG_VIDEO_H264_LEVEL_4_0  = 11,
-       V4L2_MPEG_VIDEO_H264_LEVEL_4_1  = 12,
-       V4L2_MPEG_VIDEO_H264_LEVEL_4_2  = 13,
-       V4L2_MPEG_VIDEO_H264_LEVEL_5_0  = 14,
-       V4L2_MPEG_VIDEO_H264_LEVEL_5_1  = 15,
-};
-#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_ALPHA     (V4L2_CID_MPEG_BASE+360)
-#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_BETA      (V4L2_CID_MPEG_BASE+361)
-#define V4L2_CID_MPEG_VIDEO_H264_LOOP_FILTER_MODE      (V4L2_CID_MPEG_BASE+362)
-enum v4l2_mpeg_video_h264_loop_filter_mode {
-       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_ENABLED                           = 0,
-       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED                          = 1,
-       V4L2_MPEG_VIDEO_H264_LOOP_FILTER_MODE_DISABLED_AT_SLICE_BOUNDARY        = 2,
-};
-#define V4L2_CID_MPEG_VIDEO_H264_PROFILE               (V4L2_CID_MPEG_BASE+363)
-enum v4l2_mpeg_video_h264_profile {
-       V4L2_MPEG_VIDEO_H264_PROFILE_BASELINE                   = 0,
-       V4L2_MPEG_VIDEO_H264_PROFILE_CONSTRAINED_BASELINE       = 1,
-       V4L2_MPEG_VIDEO_H264_PROFILE_MAIN                       = 2,
-       V4L2_MPEG_VIDEO_H264_PROFILE_EXTENDED                   = 3,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH                       = 4,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10                    = 5,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422                   = 6,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_PREDICTIVE        = 7,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_10_INTRA              = 8,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_422_INTRA             = 9,
-       V4L2_MPEG_VIDEO_H264_PROFILE_HIGH_444_INTRA             = 10,
-       V4L2_MPEG_VIDEO_H264_PROFILE_CAVLC_444_INTRA            = 11,
-       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_BASELINE          = 12,
-       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH              = 13,
-       V4L2_MPEG_VIDEO_H264_PROFILE_SCALABLE_HIGH_INTRA        = 14,
-       V4L2_MPEG_VIDEO_H264_PROFILE_STEREO_HIGH                = 15,
-       V4L2_MPEG_VIDEO_H264_PROFILE_MULTIVIEW_HIGH             = 16,
-};
-#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_HEIGHT    (V4L2_CID_MPEG_BASE+364)
-#define V4L2_CID_MPEG_VIDEO_H264_VUI_EXT_SAR_WIDTH     (V4L2_CID_MPEG_BASE+365)
-#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_ENABLE                (V4L2_CID_MPEG_BASE+366)
-#define V4L2_CID_MPEG_VIDEO_H264_VUI_SAR_IDC           (V4L2_CID_MPEG_BASE+367)
-enum v4l2_mpeg_video_h264_vui_sar_idc {
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_UNSPECIFIED    = 0,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_1x1            = 1,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_12x11          = 2,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_10x11          = 3,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_16x11          = 4,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_40x33          = 5,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_24x11          = 6,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_20x11          = 7,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_32x11          = 8,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_80x33          = 9,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_18x11          = 10,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_15x11          = 11,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_64x33          = 12,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_160x99         = 13,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_4x3            = 14,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_3x2            = 15,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_2x1            = 16,
-       V4L2_MPEG_VIDEO_H264_VUI_SAR_IDC_EXTENDED       = 17,
-};
-#define V4L2_CID_MPEG_VIDEO_MPEG4_I_FRAME_QP   (V4L2_CID_MPEG_BASE+400)
-#define V4L2_CID_MPEG_VIDEO_MPEG4_P_FRAME_QP   (V4L2_CID_MPEG_BASE+401)
-#define V4L2_CID_MPEG_VIDEO_MPEG4_B_FRAME_QP   (V4L2_CID_MPEG_BASE+402)
-#define V4L2_CID_MPEG_VIDEO_MPEG4_MIN_QP       (V4L2_CID_MPEG_BASE+403)
-#define V4L2_CID_MPEG_VIDEO_MPEG4_MAX_QP       (V4L2_CID_MPEG_BASE+404)
-#define V4L2_CID_MPEG_VIDEO_MPEG4_LEVEL                (V4L2_CID_MPEG_BASE+405)
-enum v4l2_mpeg_video_mpeg4_level {
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0   = 0,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_0B  = 1,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_1   = 2,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_2   = 3,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3   = 4,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_3B  = 5,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_4   = 6,
-       V4L2_MPEG_VIDEO_MPEG4_LEVEL_5   = 7,
-};
-#define V4L2_CID_MPEG_VIDEO_MPEG4_PROFILE      (V4L2_CID_MPEG_BASE+406)
-enum v4l2_mpeg_video_mpeg4_profile {
-       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE                            = 0,
-       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_SIMPLE                   = 1,
-       V4L2_MPEG_VIDEO_MPEG4_PROFILE_CORE                              = 2,
-       V4L2_MPEG_VIDEO_MPEG4_PROFILE_SIMPLE_SCALABLE                   = 3,
-       V4L2_MPEG_VIDEO_MPEG4_PROFILE_ADVANCED_CODING_EFFICIENCY        = 4,
-};
-#define V4L2_CID_MPEG_VIDEO_MPEG4_QPEL         (V4L2_CID_MPEG_BASE+407)
-
-/*  MPEG-class control IDs specific to the CX2341x driver as defined by V4L2 */
-#define V4L2_CID_MPEG_CX2341X_BASE                             (V4L2_CTRL_CLASS_MPEG | 0x1000)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE        (V4L2_CID_MPEG_CX2341X_BASE+0)
-enum v4l2_mpeg_cx2341x_video_spatial_filter_mode {
-       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_MANUAL = 0,
-       V4L2_MPEG_CX2341X_VIDEO_SPATIAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_SPATIAL_FILTER             (V4L2_CID_MPEG_CX2341X_BASE+1)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE   (V4L2_CID_MPEG_CX2341X_BASE+2)
-enum v4l2_mpeg_cx2341x_video_luma_spatial_filter_type {
-       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_OFF                  = 0,
-       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_HOR               = 1,
-       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_1D_VERT              = 2,
-       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_HV_SEPARABLE      = 3,
-       V4L2_MPEG_CX2341X_VIDEO_LUMA_SPATIAL_FILTER_TYPE_2D_SYM_NON_SEPARABLE = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE         (V4L2_CID_MPEG_CX2341X_BASE+3)
-enum v4l2_mpeg_cx2341x_video_chroma_spatial_filter_type {
-       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_OFF    = 0,
-       V4L2_MPEG_CX2341X_VIDEO_CHROMA_SPATIAL_FILTER_TYPE_1D_HOR = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE       (V4L2_CID_MPEG_CX2341X_BASE+4)
-enum v4l2_mpeg_cx2341x_video_temporal_filter_mode {
-       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_MANUAL = 0,
-       V4L2_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER_MODE_AUTO   = 1,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_TEMPORAL_FILTER            (V4L2_CID_MPEG_CX2341X_BASE+5)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE                 (V4L2_CID_MPEG_CX2341X_BASE+6)
-enum v4l2_mpeg_cx2341x_video_median_filter_type {
-       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_OFF      = 0,
-       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR      = 1,
-       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_VERT     = 2,
-       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_HOR_VERT = 3,
-       V4L2_MPEG_CX2341X_VIDEO_MEDIAN_FILTER_TYPE_DIAG     = 4,
-};
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_BOTTOM  (V4L2_CID_MPEG_CX2341X_BASE+7)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_LUMA_MEDIAN_FILTER_TOP     (V4L2_CID_MPEG_CX2341X_BASE+8)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_BOTTOM        (V4L2_CID_MPEG_CX2341X_BASE+9)
-#define V4L2_CID_MPEG_CX2341X_VIDEO_CHROMA_MEDIAN_FILTER_TOP   (V4L2_CID_MPEG_CX2341X_BASE+10)
-#define V4L2_CID_MPEG_CX2341X_STREAM_INSERT_NAV_PACKETS        (V4L2_CID_MPEG_CX2341X_BASE+11)
-
-/*  MPEG-class control IDs specific to the Samsung MFC 5.1 driver as defined by V4L2 */
-#define V4L2_CID_MPEG_MFC51_BASE                               (V4L2_CTRL_CLASS_MPEG | 0x1100)
-
-#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY           (V4L2_CID_MPEG_MFC51_BASE+0)
-#define V4L2_CID_MPEG_MFC51_VIDEO_DECODER_H264_DISPLAY_DELAY_ENABLE    (V4L2_CID_MPEG_MFC51_BASE+1)
-#define V4L2_CID_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE                      (V4L2_CID_MPEG_MFC51_BASE+2)
-enum v4l2_mpeg_mfc51_video_frame_skip_mode {
-       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_DISABLED          = 0,
-       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_LEVEL_LIMIT       = 1,
-       V4L2_MPEG_MFC51_VIDEO_FRAME_SKIP_MODE_BUF_LIMIT         = 2,
-};
-#define V4L2_CID_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE                     (V4L2_CID_MPEG_MFC51_BASE+3)
-enum v4l2_mpeg_mfc51_video_force_frame_type {
-       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_DISABLED         = 0,
-       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_I_FRAME          = 1,
-       V4L2_MPEG_MFC51_VIDEO_FORCE_FRAME_TYPE_NOT_CODED        = 2,
-};
-#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING                              (V4L2_CID_MPEG_MFC51_BASE+4)
-#define V4L2_CID_MPEG_MFC51_VIDEO_PADDING_YUV                          (V4L2_CID_MPEG_MFC51_BASE+5)
-#define V4L2_CID_MPEG_MFC51_VIDEO_RC_FIXED_TARGET_BIT                  (V4L2_CID_MPEG_MFC51_BASE+6)
-#define V4L2_CID_MPEG_MFC51_VIDEO_RC_REACTION_COEFF                    (V4L2_CID_MPEG_MFC51_BASE+7)
-#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_ACTIVITY            (V4L2_CID_MPEG_MFC51_BASE+50)
-#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_DARK                        (V4L2_CID_MPEG_MFC51_BASE+51)
-#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_SMOOTH              (V4L2_CID_MPEG_MFC51_BASE+52)
-#define V4L2_CID_MPEG_MFC51_VIDEO_H264_ADAPTIVE_RC_STATIC              (V4L2_CID_MPEG_MFC51_BASE+53)
-#define V4L2_CID_MPEG_MFC51_VIDEO_H264_NUM_REF_PIC_FOR_P               (V4L2_CID_MPEG_MFC51_BASE+54)
-
-/*  Camera class control IDs */
-#define V4L2_CID_CAMERA_CLASS_BASE     (V4L2_CTRL_CLASS_CAMERA | 0x900)
-#define V4L2_CID_CAMERA_CLASS          (V4L2_CTRL_CLASS_CAMERA | 1)
-
-#define V4L2_CID_EXPOSURE_AUTO                 (V4L2_CID_CAMERA_CLASS_BASE+1)
-enum  v4l2_exposure_auto_type {
-       V4L2_EXPOSURE_AUTO = 0,
-       V4L2_EXPOSURE_MANUAL = 1,
-       V4L2_EXPOSURE_SHUTTER_PRIORITY = 2,
-       V4L2_EXPOSURE_APERTURE_PRIORITY = 3
-};
-#define V4L2_CID_EXPOSURE_ABSOLUTE             (V4L2_CID_CAMERA_CLASS_BASE+2)
-#define V4L2_CID_EXPOSURE_AUTO_PRIORITY                (V4L2_CID_CAMERA_CLASS_BASE+3)
-
-#define V4L2_CID_PAN_RELATIVE                  (V4L2_CID_CAMERA_CLASS_BASE+4)
-#define V4L2_CID_TILT_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+5)
-#define V4L2_CID_PAN_RESET                     (V4L2_CID_CAMERA_CLASS_BASE+6)
-#define V4L2_CID_TILT_RESET                    (V4L2_CID_CAMERA_CLASS_BASE+7)
-
-#define V4L2_CID_PAN_ABSOLUTE                  (V4L2_CID_CAMERA_CLASS_BASE+8)
-#define V4L2_CID_TILT_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+9)
-
-#define V4L2_CID_FOCUS_ABSOLUTE                        (V4L2_CID_CAMERA_CLASS_BASE+10)
-#define V4L2_CID_FOCUS_RELATIVE                        (V4L2_CID_CAMERA_CLASS_BASE+11)
-#define V4L2_CID_FOCUS_AUTO                    (V4L2_CID_CAMERA_CLASS_BASE+12)
-
-#define V4L2_CID_ZOOM_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+13)
-#define V4L2_CID_ZOOM_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+14)
-#define V4L2_CID_ZOOM_CONTINUOUS               (V4L2_CID_CAMERA_CLASS_BASE+15)
-
-#define V4L2_CID_PRIVACY                       (V4L2_CID_CAMERA_CLASS_BASE+16)
-
-#define V4L2_CID_IRIS_ABSOLUTE                 (V4L2_CID_CAMERA_CLASS_BASE+17)
-#define V4L2_CID_IRIS_RELATIVE                 (V4L2_CID_CAMERA_CLASS_BASE+18)
-
-#define V4L2_CID_AUTO_EXPOSURE_BIAS            (V4L2_CID_CAMERA_CLASS_BASE+19)
-
-#define V4L2_CID_AUTO_N_PRESET_WHITE_BALANCE   (V4L2_CID_CAMERA_CLASS_BASE+20)
-enum v4l2_auto_n_preset_white_balance {
-       V4L2_WHITE_BALANCE_MANUAL               = 0,
-       V4L2_WHITE_BALANCE_AUTO                 = 1,
-       V4L2_WHITE_BALANCE_INCANDESCENT         = 2,
-       V4L2_WHITE_BALANCE_FLUORESCENT          = 3,
-       V4L2_WHITE_BALANCE_FLUORESCENT_H        = 4,
-       V4L2_WHITE_BALANCE_HORIZON              = 5,
-       V4L2_WHITE_BALANCE_DAYLIGHT             = 6,
-       V4L2_WHITE_BALANCE_FLASH                = 7,
-       V4L2_WHITE_BALANCE_CLOUDY               = 8,
-       V4L2_WHITE_BALANCE_SHADE                = 9,
-};
-
-#define V4L2_CID_WIDE_DYNAMIC_RANGE            (V4L2_CID_CAMERA_CLASS_BASE+21)
-#define V4L2_CID_IMAGE_STABILIZATION           (V4L2_CID_CAMERA_CLASS_BASE+22)
-
-#define V4L2_CID_ISO_SENSITIVITY               (V4L2_CID_CAMERA_CLASS_BASE+23)
-#define V4L2_CID_ISO_SENSITIVITY_AUTO          (V4L2_CID_CAMERA_CLASS_BASE+24)
-enum v4l2_iso_sensitivity_auto_type {
-       V4L2_ISO_SENSITIVITY_MANUAL             = 0,
-       V4L2_ISO_SENSITIVITY_AUTO               = 1,
-};
-
-#define V4L2_CID_EXPOSURE_METERING             (V4L2_CID_CAMERA_CLASS_BASE+25)
-enum v4l2_exposure_metering {
-       V4L2_EXPOSURE_METERING_AVERAGE          = 0,
-       V4L2_EXPOSURE_METERING_CENTER_WEIGHTED  = 1,
-       V4L2_EXPOSURE_METERING_SPOT             = 2,
-};
-
-#define V4L2_CID_SCENE_MODE                    (V4L2_CID_CAMERA_CLASS_BASE+26)
-enum v4l2_scene_mode {
-       V4L2_SCENE_MODE_NONE                    = 0,
-       V4L2_SCENE_MODE_BACKLIGHT               = 1,
-       V4L2_SCENE_MODE_BEACH_SNOW              = 2,
-       V4L2_SCENE_MODE_CANDLE_LIGHT            = 3,
-       V4L2_SCENE_MODE_DAWN_DUSK               = 4,
-       V4L2_SCENE_MODE_FALL_COLORS             = 5,
-       V4L2_SCENE_MODE_FIREWORKS               = 6,
-       V4L2_SCENE_MODE_LANDSCAPE               = 7,
-       V4L2_SCENE_MODE_NIGHT                   = 8,
-       V4L2_SCENE_MODE_PARTY_INDOOR            = 9,
-       V4L2_SCENE_MODE_PORTRAIT                = 10,
-       V4L2_SCENE_MODE_SPORTS                  = 11,
-       V4L2_SCENE_MODE_SUNSET                  = 12,
-       V4L2_SCENE_MODE_TEXT                    = 13,
-};
-
-#define V4L2_CID_3A_LOCK                       (V4L2_CID_CAMERA_CLASS_BASE+27)
-#define V4L2_LOCK_EXPOSURE                     (1 << 0)
-#define V4L2_LOCK_WHITE_BALANCE                        (1 << 1)
-#define V4L2_LOCK_FOCUS                                (1 << 2)
-
-#define V4L2_CID_AUTO_FOCUS_START              (V4L2_CID_CAMERA_CLASS_BASE+28)
-#define V4L2_CID_AUTO_FOCUS_STOP               (V4L2_CID_CAMERA_CLASS_BASE+29)
-#define V4L2_CID_AUTO_FOCUS_STATUS             (V4L2_CID_CAMERA_CLASS_BASE+30)
-#define V4L2_AUTO_FOCUS_STATUS_IDLE            (0 << 0)
-#define V4L2_AUTO_FOCUS_STATUS_BUSY            (1 << 0)
-#define V4L2_AUTO_FOCUS_STATUS_REACHED         (1 << 1)
-#define V4L2_AUTO_FOCUS_STATUS_FAILED          (1 << 2)
-
-#define V4L2_CID_AUTO_FOCUS_RANGE              (V4L2_CID_CAMERA_CLASS_BASE+31)
-enum v4l2_auto_focus_range {
-       V4L2_AUTO_FOCUS_RANGE_AUTO              = 0,
-       V4L2_AUTO_FOCUS_RANGE_NORMAL            = 1,
-       V4L2_AUTO_FOCUS_RANGE_MACRO             = 2,
-       V4L2_AUTO_FOCUS_RANGE_INFINITY          = 3,
-};
-
-/* FM Modulator class control IDs */
-#define V4L2_CID_FM_TX_CLASS_BASE              (V4L2_CTRL_CLASS_FM_TX | 0x900)
-#define V4L2_CID_FM_TX_CLASS                   (V4L2_CTRL_CLASS_FM_TX | 1)
-
-#define V4L2_CID_RDS_TX_DEVIATION              (V4L2_CID_FM_TX_CLASS_BASE + 1)
-#define V4L2_CID_RDS_TX_PI                     (V4L2_CID_FM_TX_CLASS_BASE + 2)
-#define V4L2_CID_RDS_TX_PTY                    (V4L2_CID_FM_TX_CLASS_BASE + 3)
-#define V4L2_CID_RDS_TX_PS_NAME                        (V4L2_CID_FM_TX_CLASS_BASE + 5)
-#define V4L2_CID_RDS_TX_RADIO_TEXT             (V4L2_CID_FM_TX_CLASS_BASE + 6)
-
-#define V4L2_CID_AUDIO_LIMITER_ENABLED         (V4L2_CID_FM_TX_CLASS_BASE + 64)
-#define V4L2_CID_AUDIO_LIMITER_RELEASE_TIME    (V4L2_CID_FM_TX_CLASS_BASE + 65)
-#define V4L2_CID_AUDIO_LIMITER_DEVIATION       (V4L2_CID_FM_TX_CLASS_BASE + 66)
-
-#define V4L2_CID_AUDIO_COMPRESSION_ENABLED     (V4L2_CID_FM_TX_CLASS_BASE + 80)
-#define V4L2_CID_AUDIO_COMPRESSION_GAIN                (V4L2_CID_FM_TX_CLASS_BASE + 81)
-#define V4L2_CID_AUDIO_COMPRESSION_THRESHOLD   (V4L2_CID_FM_TX_CLASS_BASE + 82)
-#define V4L2_CID_AUDIO_COMPRESSION_ATTACK_TIME (V4L2_CID_FM_TX_CLASS_BASE + 83)
-#define V4L2_CID_AUDIO_COMPRESSION_RELEASE_TIME        (V4L2_CID_FM_TX_CLASS_BASE + 84)
-
-#define V4L2_CID_PILOT_TONE_ENABLED            (V4L2_CID_FM_TX_CLASS_BASE + 96)
-#define V4L2_CID_PILOT_TONE_DEVIATION          (V4L2_CID_FM_TX_CLASS_BASE + 97)
-#define V4L2_CID_PILOT_TONE_FREQUENCY          (V4L2_CID_FM_TX_CLASS_BASE + 98)
-
-#define V4L2_CID_TUNE_PREEMPHASIS              (V4L2_CID_FM_TX_CLASS_BASE + 112)
-enum v4l2_preemphasis {
-       V4L2_PREEMPHASIS_DISABLED       = 0,
-       V4L2_PREEMPHASIS_50_uS          = 1,
-       V4L2_PREEMPHASIS_75_uS          = 2,
-};
-#define V4L2_CID_TUNE_POWER_LEVEL              (V4L2_CID_FM_TX_CLASS_BASE + 113)
-#define V4L2_CID_TUNE_ANTENNA_CAPACITOR                (V4L2_CID_FM_TX_CLASS_BASE + 114)
-
-/* Flash and privacy (indicator) light controls */
-#define V4L2_CID_FLASH_CLASS_BASE              (V4L2_CTRL_CLASS_FLASH | 0x900)
-#define V4L2_CID_FLASH_CLASS                   (V4L2_CTRL_CLASS_FLASH | 1)
-
-#define V4L2_CID_FLASH_LED_MODE                        (V4L2_CID_FLASH_CLASS_BASE + 1)
-enum v4l2_flash_led_mode {
-       V4L2_FLASH_LED_MODE_NONE,
-       V4L2_FLASH_LED_MODE_FLASH,
-       V4L2_FLASH_LED_MODE_TORCH,
-};
-
-#define V4L2_CID_FLASH_STROBE_SOURCE           (V4L2_CID_FLASH_CLASS_BASE + 2)
-enum v4l2_flash_strobe_source {
-       V4L2_FLASH_STROBE_SOURCE_SOFTWARE,
-       V4L2_FLASH_STROBE_SOURCE_EXTERNAL,
-};
-
-#define V4L2_CID_FLASH_STROBE                  (V4L2_CID_FLASH_CLASS_BASE + 3)
-#define V4L2_CID_FLASH_STROBE_STOP             (V4L2_CID_FLASH_CLASS_BASE + 4)
-#define V4L2_CID_FLASH_STROBE_STATUS           (V4L2_CID_FLASH_CLASS_BASE + 5)
-
-#define V4L2_CID_FLASH_TIMEOUT                 (V4L2_CID_FLASH_CLASS_BASE + 6)
-#define V4L2_CID_FLASH_INTENSITY               (V4L2_CID_FLASH_CLASS_BASE + 7)
-#define V4L2_CID_FLASH_TORCH_INTENSITY         (V4L2_CID_FLASH_CLASS_BASE + 8)
-#define V4L2_CID_FLASH_INDICATOR_INTENSITY     (V4L2_CID_FLASH_CLASS_BASE + 9)
-
-#define V4L2_CID_FLASH_FAULT                   (V4L2_CID_FLASH_CLASS_BASE + 10)
-#define V4L2_FLASH_FAULT_OVER_VOLTAGE          (1 << 0)
-#define V4L2_FLASH_FAULT_TIMEOUT               (1 << 1)
-#define V4L2_FLASH_FAULT_OVER_TEMPERATURE      (1 << 2)
-#define V4L2_FLASH_FAULT_SHORT_CIRCUIT         (1 << 3)
-#define V4L2_FLASH_FAULT_OVER_CURRENT          (1 << 4)
-#define V4L2_FLASH_FAULT_INDICATOR             (1 << 5)
-
-#define V4L2_CID_FLASH_CHARGE                  (V4L2_CID_FLASH_CLASS_BASE + 11)
-#define V4L2_CID_FLASH_READY                   (V4L2_CID_FLASH_CLASS_BASE + 12)
-
-/*  JPEG-class control IDs defined by V4L2 */
-#define V4L2_CID_JPEG_CLASS_BASE               (V4L2_CTRL_CLASS_JPEG | 0x900)
-#define V4L2_CID_JPEG_CLASS                    (V4L2_CTRL_CLASS_JPEG | 1)
-
-#define        V4L2_CID_JPEG_CHROMA_SUBSAMPLING        (V4L2_CID_JPEG_CLASS_BASE + 1)
-enum v4l2_jpeg_chroma_subsampling {
-       V4L2_JPEG_CHROMA_SUBSAMPLING_444        = 0,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_422        = 1,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_420        = 2,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_411        = 3,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_410        = 4,
-       V4L2_JPEG_CHROMA_SUBSAMPLING_GRAY       = 5,
-};
-#define        V4L2_CID_JPEG_RESTART_INTERVAL          (V4L2_CID_JPEG_CLASS_BASE + 2)
-#define        V4L2_CID_JPEG_COMPRESSION_QUALITY       (V4L2_CID_JPEG_CLASS_BASE + 3)
-
-#define        V4L2_CID_JPEG_ACTIVE_MARKER             (V4L2_CID_JPEG_CLASS_BASE + 4)
-#define        V4L2_JPEG_ACTIVE_MARKER_APP0            (1 << 0)
-#define        V4L2_JPEG_ACTIVE_MARKER_APP1            (1 << 1)
-#define        V4L2_JPEG_ACTIVE_MARKER_COM             (1 << 16)
-#define        V4L2_JPEG_ACTIVE_MARKER_DQT             (1 << 17)
-#define        V4L2_JPEG_ACTIVE_MARKER_DHT             (1 << 18)
-
-/* Image source controls */
-#define V4L2_CID_IMAGE_SOURCE_CLASS_BASE       (V4L2_CTRL_CLASS_IMAGE_SOURCE | 0x900)
-#define V4L2_CID_IMAGE_SOURCE_CLASS            (V4L2_CTRL_CLASS_IMAGE_SOURCE | 1)
-
-#define V4L2_CID_VBLANK                                (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 1)
-#define V4L2_CID_HBLANK                                (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 2)
-#define V4L2_CID_ANALOGUE_GAIN                 (V4L2_CID_IMAGE_SOURCE_CLASS_BASE + 3)
-
-/* Image processing controls */
-#define V4L2_CID_IMAGE_PROC_CLASS_BASE         (V4L2_CTRL_CLASS_IMAGE_PROC | 0x900)
-#define V4L2_CID_IMAGE_PROC_CLASS              (V4L2_CTRL_CLASS_IMAGE_PROC | 1)
-
-#define V4L2_CID_LINK_FREQ                     (V4L2_CID_IMAGE_PROC_CLASS_BASE + 1)
-#define V4L2_CID_PIXEL_RATE                    (V4L2_CID_IMAGE_PROC_CLASS_BASE + 2)
+
+/*  DV-class control IDs defined by V4L2 */
+#define V4L2_CID_DV_CLASS_BASE                 (V4L2_CTRL_CLASS_DV | 0x900)
+#define V4L2_CID_DV_CLASS                      (V4L2_CTRL_CLASS_DV | 1)
+
+#define        V4L2_CID_DV_TX_HOTPLUG                  (V4L2_CID_DV_CLASS_BASE + 1)
+#define        V4L2_CID_DV_TX_RXSENSE                  (V4L2_CID_DV_CLASS_BASE + 2)
+#define        V4L2_CID_DV_TX_EDID_PRESENT             (V4L2_CID_DV_CLASS_BASE + 3)
+#define        V4L2_CID_DV_TX_MODE                     (V4L2_CID_DV_CLASS_BASE + 4)
+enum v4l2_dv_tx_mode {
+       V4L2_DV_TX_MODE_DVI_D   = 0,
+       V4L2_DV_TX_MODE_HDMI    = 1,
+};
+#define V4L2_CID_DV_TX_RGB_RANGE               (V4L2_CID_DV_CLASS_BASE + 5)
+enum v4l2_dv_rgb_range {
+       V4L2_DV_RGB_RANGE_AUTO    = 0,
+       V4L2_DV_RGB_RANGE_LIMITED = 1,
+       V4L2_DV_RGB_RANGE_FULL    = 2,
+};
+
+#define        V4L2_CID_DV_RX_POWER_PRESENT            (V4L2_CID_DV_CLASS_BASE + 100)
+#define V4L2_CID_DV_RX_RGB_RANGE               (V4L2_CID_DV_CLASS_BASE + 101)
 
 /*
  *     T U N I N G
index 22e61fdf75a2bd46a656e164e046a006acd43343..28e493b5b94c9ba6d946d728a0908c84e34294db 100644 (file)
@@ -84,6 +84,8 @@ struct xfrm_replay_state {
        __u32   bitmap;
 };
 
+#define XFRMA_REPLAY_ESN_MAX   4096
+
 struct xfrm_replay_state_esn {
        unsigned int    bmp_len;
        __u32           oseq;
diff --git a/include/media/ad9389b.h b/include/media/ad9389b.h
new file mode 100644 (file)
index 0000000..5ba9af8
--- /dev/null
@@ -0,0 +1,49 @@
+/*
+ * Analog Devices AD9389B/AD9889B video encoder driver header
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ */
+
+#ifndef AD9389B_H
+#define AD9389B_H
+
+enum ad9389b_tmds_pll_gear {
+       AD9389B_TMDS_PLL_GEAR_AUTOMATIC,
+       AD9389B_TMDS_PLL_GEAR_SEMI_AUTOMATIC,
+};
+
+/* Platform dependent definitions */
+struct ad9389b_platform_data {
+       enum ad9389b_tmds_pll_gear tmds_pll_gear ;
+       /* Differential Data/Clock Output Drive Strength (reg. 0xa2/0xa3) */
+       u8 diff_data_drive_strength;
+       u8 diff_clk_drive_strength;
+};
+
+/* notify events */
+#define AD9389B_MONITOR_DETECT 0
+#define AD9389B_EDID_DETECT 1
+
+struct ad9389b_monitor_detect {
+       int present;
+};
+
+struct ad9389b_edid_detect {
+       int present;
+       int segment;
+};
+
+#endif
diff --git a/include/media/adv7604.h b/include/media/adv7604.h
new file mode 100644 (file)
index 0000000..171b957
--- /dev/null
@@ -0,0 +1,153 @@
+/*
+ * adv7604 - Analog Devices ADV7604 video decoder driver
+ *
+ * Copyright 2012 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
+ *
+ * This program is free software; you may redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * 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.
+ *
+ */
+
+#ifndef _ADV7604_
+#define _ADV7604_
+
+/* Analog input muxing modes (AFE register 0x02, [2:0]) */
+enum adv7604_ain_sel {
+       ADV7604_AIN1_2_3_NC_SYNC_1_2 = 0,
+       ADV7604_AIN4_5_6_NC_SYNC_2_1 = 1,
+       ADV7604_AIN7_8_9_NC_SYNC_3_1 = 2,
+       ADV7604_AIN10_11_12_NC_SYNC_4_1 = 3,
+       ADV7604_AIN9_4_5_6_SYNC_2_1 = 4,
+};
+
+/* Bus rotation and reordering (IO register 0x04, [7:5]) */
+enum adv7604_op_ch_sel {
+       ADV7604_OP_CH_SEL_GBR = 0,
+       ADV7604_OP_CH_SEL_GRB = 1,
+       ADV7604_OP_CH_SEL_BGR = 2,
+       ADV7604_OP_CH_SEL_RGB = 3,
+       ADV7604_OP_CH_SEL_BRG = 4,
+       ADV7604_OP_CH_SEL_RBG = 5,
+};
+
+/* Primary mode (IO register 0x01, [3:0]) */
+enum adv7604_prim_mode {
+       ADV7604_PRIM_MODE_COMP = 1,
+       ADV7604_PRIM_MODE_RGB = 2,
+       ADV7604_PRIM_MODE_HDMI_COMP = 5,
+       ADV7604_PRIM_MODE_HDMI_GR = 6,
+};
+
+/* Input Color Space (IO register 0x02, [7:4]) */
+enum adv7604_inp_color_space {
+       ADV7604_INP_COLOR_SPACE_LIM_RGB = 0,
+       ADV7604_INP_COLOR_SPACE_FULL_RGB = 1,
+       ADV7604_INP_COLOR_SPACE_LIM_YCbCr_601 = 2,
+       ADV7604_INP_COLOR_SPACE_LIM_YCbCr_709 = 3,
+       ADV7604_INP_COLOR_SPACE_XVYCC_601 = 4,
+       ADV7604_INP_COLOR_SPACE_XVYCC_709 = 5,
+       ADV7604_INP_COLOR_SPACE_FULL_YCbCr_601 = 6,
+       ADV7604_INP_COLOR_SPACE_FULL_YCbCr_709 = 7,
+       ADV7604_INP_COLOR_SPACE_AUTO = 0xf,
+};
+
+/* Select output format (IO register 0x03, [7:0]) */
+enum adv7604_op_format_sel {
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_8 = 0x00,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_10 = 0x01,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE0 = 0x02,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE1 = 0x06,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_12_MODE2 = 0x0a,
+       ADV7604_OP_FORMAT_SEL_DDR_422_8 = 0x20,
+       ADV7604_OP_FORMAT_SEL_DDR_422_10 = 0x21,
+       ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE0 = 0x22,
+       ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE1 = 0x23,
+       ADV7604_OP_FORMAT_SEL_DDR_422_12_MODE2 = 0x24,
+       ADV7604_OP_FORMAT_SEL_SDR_444_24 = 0x40,
+       ADV7604_OP_FORMAT_SEL_SDR_444_30 = 0x41,
+       ADV7604_OP_FORMAT_SEL_SDR_444_36_MODE0 = 0x42,
+       ADV7604_OP_FORMAT_SEL_DDR_444_24 = 0x60,
+       ADV7604_OP_FORMAT_SEL_DDR_444_30 = 0x61,
+       ADV7604_OP_FORMAT_SEL_DDR_444_36 = 0x62,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_16 = 0x80,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_20 = 0x81,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE0 = 0x82,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE1 = 0x86,
+       ADV7604_OP_FORMAT_SEL_SDR_ITU656_24_MODE2 = 0x8a,
+};
+
+/* Platform dependent definition */
+struct adv7604_platform_data {
+       /* connector - HDMI or DVI? */
+       unsigned connector_hdmi:1;
+
+       /* DIS_PWRDNB: 1 if the PWRDNB pin is unused and unconnected */
+       unsigned disable_pwrdnb:1;
+
+       /* DIS_CABLE_DET_RST: 1 if the 5V pins are unused and unconnected */
+       unsigned disable_cable_det_rst:1;
+
+       /* Analog input muxing mode */
+       enum adv7604_ain_sel ain_sel;
+
+       /* Bus rotation and reordering */
+       enum adv7604_op_ch_sel op_ch_sel;
+
+       /* Primary mode */
+       enum adv7604_prim_mode prim_mode;
+
+       /* Select output format */
+       enum adv7604_op_format_sel op_format_sel;
+
+       /* IO register 0x02 */
+       unsigned alt_gamma:1;
+       unsigned op_656_range:1;
+       unsigned rgb_out:1;
+       unsigned alt_data_sat:1;
+
+       /* IO register 0x05 */
+       unsigned blank_data:1;
+       unsigned insert_av_codes:1;
+       unsigned replicate_av_codes:1;
+       unsigned invert_cbcr:1;
+
+       /* IO register 0x30 */
+       unsigned output_bus_lsb_to_msb:1;
+
+       /* Free run */
+       unsigned hdmi_free_run_mode;
+
+       /* i2c addresses: 0 == use default */
+       u8 i2c_avlink;
+       u8 i2c_cec;
+       u8 i2c_infoframe;
+       u8 i2c_esdp;
+       u8 i2c_dpp;
+       u8 i2c_afe;
+       u8 i2c_repeater;
+       u8 i2c_edid;
+       u8 i2c_hdmi;
+       u8 i2c_test;
+       u8 i2c_cp;
+       u8 i2c_vdp;
+};
+
+#define V4L2_CID_ADV_RX_ANALOG_SAMPLING_PHASE  (V4L2_CID_DV_CLASS_BASE + 0x1000)
+#define V4L2_CID_ADV_RX_FREE_RUN_COLOR_MANUAL  (V4L2_CID_DV_CLASS_BASE + 0x1001)
+#define V4L2_CID_ADV_RX_FREE_RUN_COLOR         (V4L2_CID_DV_CLASS_BASE + 0x1002)
+
+/* notify events */
+#define ADV7604_HOTPLUG                1
+#define ADV7604_FMT_CHANGE     2
+
+#endif
index 8bc1b3c0e6790501d1853e59841867f5709afed4..a7ca4884c46cc8a386a42a7d9f9eaae6c35dc8ba 100644 (file)
@@ -35,7 +35,7 @@ struct osd_config_info {
 struct vpbe_output {
        struct v4l2_output output;
        /*
-        * If output capabilities include dv_preset, list supported presets
+        * If output capabilities include dv_timings, list supported timings
         * below
         */
        char *subdev_name;
@@ -120,16 +120,16 @@ struct vpbe_device_ops {
        unsigned int (*get_output)(struct vpbe_device *vpbe_dev);
 
        /* Set DV preset at current output */
-       int (*s_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*s_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Get DV presets supported at the output */
-       int (*g_dv_preset)(struct vpbe_device *vpbe_dev,
-                          struct v4l2_dv_preset *dv_preset);
+       int (*g_dv_timings)(struct vpbe_device *vpbe_dev,
+                          struct v4l2_dv_timings *dv_timings);
 
        /* Enumerate the DV Presets supported at the output */
-       int (*enum_dv_presets)(struct vpbe_device *vpbe_dev,
-                              struct v4l2_dv_enum_preset *preset_info);
+       int (*enum_dv_timings)(struct vpbe_device *vpbe_dev,
+                              struct v4l2_enum_dv_timings *timings_info);
 
        /* Set std at the output */
        int (*s_std)(struct vpbe_device *vpbe_dev, v4l2_std_id *std_id);
index 727f55170e41cc7dd74accb196b4a75776ed0ce2..9b85396514be33390705fdc34c4bad826fd609e1 100644 (file)
@@ -32,11 +32,6 @@ enum vpbe_enc_timings_type {
        VPBE_ENC_TIMINGS_INVALID = 0x8,
 };
 
-union vpbe_timings {
-       v4l2_std_id std_id;
-       unsigned int dv_preset;
-};
-
 /*
  * struct vpbe_enc_mode_info
  * @name: ptr to name string of the standard, "NTSC", "PAL" etc
@@ -73,7 +68,8 @@ union vpbe_timings {
 struct vpbe_enc_mode_info {
        unsigned char *name;
        enum vpbe_enc_timings_type timings_type;
-       union vpbe_timings timings;
+       v4l2_std_id std_id;
+       struct v4l2_dv_timings dv_timings;
        unsigned int interlaced;
        unsigned int xres;
        unsigned int yres;
index 6b57334f402996341e584fcc0177054140663ba5..cc78c2eb16da25a689ece25ad1dfc931c6dcf211 100644 (file)
@@ -32,7 +32,7 @@ struct venc_platform_data {
        int (*setup_pinmux)(enum v4l2_mbus_pixelcode if_type,
                            int field);
        int (*setup_clock)(enum vpbe_enc_timings_type type,
-                          unsigned int mode);
+                          unsigned int pixclock);
        int (*setup_if_config)(enum v4l2_mbus_pixelcode pixcode);
        /* Number of LCD outputs supported */
        int num_lcd_outputs;
index d8f6ab1943e4e492679b1b4ae58ac1244496cc72..3882e0675ccfd45e718dbd8dc38bedd51af02120 100644 (file)
@@ -20,6 +20,7 @@
 #include <linux/i2c.h>
 
 #define VPIF_CAPTURE_MAX_CHANNELS      2
+#define VPIF_DISPLAY_MAX_CHANNELS      2
 
 enum vpif_if_type {
        VPIF_IF_BT656,
@@ -37,29 +38,38 @@ struct vpif_interface {
 struct vpif_subdev_info {
        const char *name;
        struct i2c_board_info board_info;
-       u32 input;
-       u32 output;
-       unsigned can_route:1;
-       struct vpif_interface vpif_if;
+};
+
+struct vpif_output {
+       struct v4l2_output output;
+       const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
+};
+
+struct vpif_display_chan_config {
+       const struct vpif_output *outputs;
+       int output_count;
+       bool clip_en;
 };
 
 struct vpif_display_config {
        int (*set_clock)(int, int);
        struct vpif_subdev_info *subdevinfo;
        int subdev_count;
-       const char **output;
-       int output_count;
+       struct vpif_display_chan_config chan_config[VPIF_DISPLAY_MAX_CHANNELS];
        const char *card_name;
-       bool ch2_clip_en;
-       bool ch3_clip_en;
 };
 
 struct vpif_input {
        struct v4l2_input input;
        const char *subdev_name;
+       u32 input_route;
+       u32 output_route;
 };
 
 struct vpif_capture_chan_config {
+       struct vpif_interface vpif_if;
        const struct vpif_input *inputs;
        int input_count;
 };
diff --git a/include/media/ir-rx51.h b/include/media/ir-rx51.h
new file mode 100644 (file)
index 0000000..104aa89
--- /dev/null
@@ -0,0 +1,10 @@
+#ifndef _LIRC_RX51_H
+#define _LIRC_RX51_H
+
+struct lirc_rx51_platform_data {
+       int pwm_timer;
+
+       int(*set_max_mpu_wakeup_lat)(struct device *dev, long t);
+};
+
+#endif
index 5e27f9be6b95c4923e40a99abe2b89a64c1ff16d..78fd39eac219b75041ef38fdc6b5a4729faa8ce2 100644 (file)
@@ -7,6 +7,9 @@ struct mt9v032_platform_data {
        unsigned int clk_pol:1;
 
        void (*set_clock)(struct v4l2_subdev *subdev, unsigned int rate);
+
+       const s64 *link_freqs;
+       s64 link_def_freq;
 };
 
 #endif
index 4d94be5226af75ba9da2064311b80b7987e93764..95842696857f26122b9a3233b19c251ec6038eb2 100644 (file)
@@ -41,12 +41,6 @@ enum isp_interface_type {
        ISP_INTERFACE_CSI2C_PHY1,
 };
 
-enum {
-       ISP_BRIDGE_DISABLE = 0,
-       ISP_BRIDGE_LITTLE_ENDIAN = 2,
-       ISP_BRIDGE_BIG_ENDIAN = 3,
-};
-
 enum {
        ISP_LANE_SHIFT_0 = 0,
        ISP_LANE_SHIFT_2 = 1,
@@ -67,17 +61,15 @@ enum {
  *             0 - Active high, 1 - Active low
  * @vs_pol: Vertical synchronization polarity
  *             0 - Active high, 1 - Active low
- * @bridge: CCDC Bridge input control
- *             ISP_BRIDGE_DISABLE - Disable
- *             ISP_BRIDGE_LITTLE_ENDIAN - Little endian
- *             ISP_BRIDGE_BIG_ENDIAN - Big endian
+ * @data_pol: Data polarity
+ *             0 - Normal, 1 - One's complement
  */
 struct isp_parallel_platform_data {
        unsigned int data_lane_shift:2;
        unsigned int clk_pol:1;
        unsigned int hs_pol:1;
        unsigned int vs_pol:1;
-       unsigned int bridge:2;
+       unsigned int data_pol:1;
 };
 
 enum {
diff --git a/include/media/s5k4ecgx.h b/include/media/s5k4ecgx.h
new file mode 100644 (file)
index 0000000..90c1be7
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ * S5K4ECGX image sensor header file
+ *
+ * Copyright (C) 2012, Linaro
+ * Copyright (C) 2012, Samsung Electronics Co., 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 S5K4ECGX_H
+#define S5K4ECGX_H
+
+/**
+ * struct s5k4ecgx_gpio - data structure describing a GPIO
+ * @gpio : GPIO number
+ * @level: indicates active state of the @gpio
+ */
+struct s5k4ecgx_gpio {
+       int gpio;
+       int level;
+};
+
+/**
+ * struct ss5k4ecgx_platform_data- s5k4ecgx driver platform data
+ * @gpio_reset:         GPIO driving RESET pin
+ * @gpio_stby :         GPIO driving STBY pin
+ */
+
+struct s5k4ecgx_platform_data {
+       struct s5k4ecgx_gpio gpio_reset;
+       struct s5k4ecgx_gpio gpio_stby;
+};
+
+#endif /* S5K4ECGX_H */
index 8587aaf7364678cbb5a816cd194b568699717b4e..09421a611d73df78ed1d3d6af80571e0511956ce 100644 (file)
@@ -12,6 +12,8 @@
 #ifndef S5P_FIMC_H_
 #define S5P_FIMC_H_
 
+#include <media/media-entity.h>
+
 enum cam_bus_type {
        FIMC_ITU_601 = 1,
        FIMC_ITU_656,
@@ -80,4 +82,20 @@ struct fimc_pipeline {
        struct media_pipeline *m_pipeline;
 };
 
+/*
+ * Media pipeline operations to be called from within the fimc(-lite)
+ * video node when it is the last entity of the pipeline. Implemented
+ * by corresponding media device driver.
+ */
+struct fimc_pipeline_ops {
+       int (*open)(struct fimc_pipeline *p, struct media_entity *me,
+                         bool resume);
+       int (*close)(struct fimc_pipeline *p);
+       int (*set_stream)(struct fimc_pipeline *p, bool state);
+};
+
+#define fimc_pipeline_call(f, op, p, args...)                          \
+       (!(f) ? -ENODEV : (((f)->pipeline_ops && (f)->pipeline_ops->op) ? \
+                           (f)->pipeline_ops->op((p), ##args) : -ENOIOCTLCMD))
+
 #endif /* S5P_FIMC_H_ */
index 773e527deabe3cb04b8371df40648a8100464ce4..96058a5a4acc3870f63298469e5b22e30601bc25 100644 (file)
@@ -117,8 +117,6 @@ struct saa7146_dev
 {
        struct module                   *module;
 
-       struct list_head                item;
-
        struct v4l2_device              v4l2_dev;
        struct v4l2_ctrl_handler        ctrl_handler;
 
@@ -166,8 +164,6 @@ static inline struct saa7146_dev *to_saa7146_dev(struct v4l2_device *v4l2_dev)
 int saa7146_i2c_adapter_prepare(struct saa7146_dev *dev, struct i2c_adapter *i2c_adapter, u32 bitrate);
 
 /* from saa7146_core.c */
-extern struct list_head saa7146_devices;
-extern struct mutex saa7146_devices_lock;
 int saa7146_register_extension(struct saa7146_extension*);
 int saa7146_unregister_extension(struct saa7146_extension*);
 struct saa7146_format* saa7146_format_by_fourcc(struct saa7146_dev *dev, int fourcc);
index d865dcf9879fe18092241e074807b1600ff57bbf..6442edc2a151db0d703b6ebb6f98338499603818 100644 (file)
@@ -85,12 +85,14 @@ struct soc_camera_host_ops {
        void (*put_formats)(struct soc_camera_device *);
        int (*cropcap)(struct soc_camera_device *, struct v4l2_cropcap *);
        int (*get_crop)(struct soc_camera_device *, struct v4l2_crop *);
-       int (*set_crop)(struct soc_camera_device *, struct v4l2_crop *);
+       int (*set_crop)(struct soc_camera_device *, const struct v4l2_crop *);
+       int (*get_selection)(struct soc_camera_device *, struct v4l2_selection *);
+       int (*set_selection)(struct soc_camera_device *, struct v4l2_selection *);
        /*
         * The difference to .set_crop() is, that .set_livecrop is not allowed
         * to change the output sizes
         */
-       int (*set_livecrop)(struct soc_camera_device *, struct v4l2_crop *);
+       int (*set_livecrop)(struct soc_camera_device *, const struct v4l2_crop *);
        int (*set_fmt)(struct soc_camera_device *, struct v4l2_format *);
        int (*try_fmt)(struct soc_camera_device *, struct v4l2_format *);
        void (*init_videobuf)(struct videobuf_queue *,
@@ -254,6 +256,16 @@ unsigned long soc_camera_apply_sensor_flags(struct soc_camera_link *icl,
 unsigned long soc_camera_apply_board_flags(struct soc_camera_link *icl,
                                           const struct v4l2_mbus_config *cfg);
 
+int soc_camera_power_on(struct device *dev, struct soc_camera_link *icl);
+int soc_camera_power_off(struct device *dev, struct soc_camera_link *icl);
+
+static inline int soc_camera_set_power(struct device *dev,
+                                      struct soc_camera_link *icl, bool on)
+{
+       return on ? soc_camera_power_on(dev, icl)
+                 : soc_camera_power_off(dev, icl);
+}
+
 /* This is only temporary here - until v4l2-subdev begins to link to video_device */
 #include <linux/i2c.h>
 static inline struct video_device *soc_camera_i2c_to_vdev(const struct i2c_client *client)
index 58f914a40b208586db30c85cf83346703a3220fe..4ee125bae719ef379e699a6b02e9673e798f8516 100644 (file)
@@ -183,6 +183,9 @@ enum {
        /* module adv7393: just ident 7393 */
        V4L2_IDENT_ADV7393 = 7393,
 
+       /* module adv7604: just ident 7604 */
+       V4L2_IDENT_ADV7604 = 7604,
+
        /* module saa7706h: just ident 7706 */
        V4L2_IDENT_SAA7706H = 7706,
 
@@ -212,6 +215,9 @@ enum {
        V4L2_IDENT_CX23888_AV = 8881, /* Integrated A/V decoder */
        V4L2_IDENT_CX23888_IR = 8882, /* Integrated infrared controller */
 
+       /* module ad9389b: just ident 9389 */
+       V4L2_IDENT_AD9389B = 9389,
+
        /* module tda9840: just ident 9840 */
        V4L2_IDENT_TDA9840 = 9840,
 
index a298ec49ddc489ba70d47003fba8a39f32335ff4..1a0b2db4c5d318c80b135d5a69b7f4b34659327c 100644 (file)
@@ -133,7 +133,7 @@ struct v4l2_subdev *v4l2_i2c_new_subdev_board(struct v4l2_device *v4l2_dev,
                struct i2c_adapter *adapter, struct i2c_board_info *info,
                const unsigned short *probe_addrs);
 
-/* Initialize an v4l2_subdev with data from an i2c_client struct */
+/* Initialize a v4l2_subdev with data from an i2c_client struct */
 void v4l2_i2c_subdev_init(struct v4l2_subdev *sd, struct i2c_client *client,
                const struct v4l2_subdev_ops *ops);
 /* Return i2c client address of v4l2_subdev. */
@@ -166,7 +166,7 @@ struct spi_device;
 struct v4l2_subdev *v4l2_spi_new_subdev(struct v4l2_device *v4l2_dev,
                struct spi_master *master, struct spi_board_info *info);
 
-/* Initialize an v4l2_subdev with data from an spi_device struct */
+/* Initialize a v4l2_subdev with data from an spi_device struct */
 void v4l2_spi_subdev_init(struct v4l2_subdev *sd, struct spi_device *spi,
                const struct v4l2_subdev_ops *ops);
 #endif
@@ -212,4 +212,17 @@ const struct v4l2_frmsize_discrete *v4l2_find_nearest_format(
                const struct v4l2_discrete_probe *probe,
                s32 width, s32 height);
 
+bool v4l_match_dv_timings(const struct v4l2_dv_timings *t1,
+                         const struct v4l2_dv_timings *t2,
+                         unsigned pclock_delta);
+
+bool v4l2_detect_cvt(unsigned frame_height, unsigned hfreq, unsigned vsync,
+               u32 polarities, struct v4l2_dv_timings *fmt);
+
+bool v4l2_detect_gtf(unsigned frame_height, unsigned hfreq, unsigned vsync,
+               u32 polarities, struct v4l2_fract aspect,
+               struct v4l2_dv_timings *fmt);
+
+struct v4l2_fract v4l2_calc_aspect_ratio(u8 hor_landscape, u8 vert_portrait);
+
 #endif /* V4L2_COMMON_H_ */
index 776605f1cbe269514b1f5cc757e9a7176e92022e..96509119f28f42daa6ce3794cea050f4d8768603 100644 (file)
@@ -351,6 +351,29 @@ 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);
 
+/** v4l2_ctrl_new_std_menu_items() - Create a new standard V4L2 menu control
+  * with driver specific menu.
+  * @hdl:      The control handler.
+  * @ops:      The control ops.
+  * @id:       The control ID.
+  * @max:      The control's maximum value.
+  * @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
+  *            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.
+  * @def:      The control's default value.
+  * @qmenu:    The new menu.
+  *
+  * Same as v4l2_ctrl_new_std_menu(), but @qmenu will be the driver specific
+  * menu of this control.
+  *
+  */
+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);
+
 /** v4l2_ctrl_new_int_menu() - Create a new standard V4L2 integer menu control.
   * @hdl:      The control handler.
   * @ops:      The control ops.
@@ -384,14 +407,28 @@ struct v4l2_ctrl *v4l2_ctrl_add_ctrl(struct v4l2_ctrl_handler *hdl,
   * @hdl:      The control handler.
   * @add:      The control handler whose controls you want to add to
   *            the @hdl control handler.
+  * @filter:   This function will filter which controls should be added.
   *
-  * Does nothing if either of the two is a NULL pointer.
+  * Does nothing if either of the two handlers is a NULL pointer.
+  * If @filter is NULL, then all controls are added. Otherwise only those
+  * controls for which @filter returns true will be added.
   * In case of an error @hdl->error will be set to the error code (if it
   * wasn't set already).
   */
 int v4l2_ctrl_add_handler(struct v4l2_ctrl_handler *hdl,
-                         struct v4l2_ctrl_handler *add);
+                         struct v4l2_ctrl_handler *add,
+                         bool (*filter)(const struct v4l2_ctrl *ctrl));
 
+/** v4l2_ctrl_radio_filter() - Standard filter for radio controls.
+  * @ctrl:     The control that is filtered.
+  *
+  * This will return true for any controls that are valid for radio device
+  * nodes. Those are all of the V4L2_CID_AUDIO_* user controls and all FM
+  * transmitter class controls.
+  *
+  * This function is to be used with v4l2_ctrl_add_handler().
+  */
+bool v4l2_ctrl_radio_filter(const struct v4l2_ctrl *ctrl);
 
 /** v4l2_ctrl_cluster() - Mark all controls in the cluster as belonging to that cluster.
   * @ncontrols:        The number of controls in this cluster.
@@ -511,6 +548,29 @@ s32 v4l2_ctrl_g_ctrl(struct v4l2_ctrl *ctrl);
   */
 int v4l2_ctrl_s_ctrl(struct v4l2_ctrl *ctrl, s32 val);
 
+/** v4l2_ctrl_g_ctrl_int64() - Helper function to get a 64-bit control's value from within a driver.
+  * @ctrl:     The control.
+  *
+  * This returns the control's value safely by going through the control
+  * framework. This function will lock the control's handler, so it cannot be
+  * used from within the &v4l2_ctrl_ops functions.
+  *
+  * This function is for 64-bit integer type controls only.
+  */
+s64 v4l2_ctrl_g_ctrl_int64(struct v4l2_ctrl *ctrl);
+
+/** 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.
+  *
+  * This set the control's new value safely by going through the control
+  * framework. This function will lock the control's handler, so it cannot be
+  * used from within the &v4l2_ctrl_ops functions.
+  *
+  * This function is for 64-bit integer type controls only.
+  */
+int v4l2_ctrl_s_ctrl_int64(struct v4l2_ctrl *ctrl, s64 val);
+
 /* Internal helper functions that deal with control events. */
 extern const struct v4l2_subscribed_event_ops v4l2_ctrl_sub_ev_ops;
 void v4l2_ctrl_replace(struct v4l2_event *old, const struct v4l2_event *new);
@@ -523,7 +583,7 @@ int v4l2_ctrl_log_status(struct file *file, void *fh);
 /* Can be used as a vidioc_subscribe_event function that just subscribes
    control events. */
 int v4l2_ctrl_subscribe_event(struct v4l2_fh *fh,
-                               struct v4l2_event_subscription *sub);
+                               const struct v4l2_event_subscription *sub);
 
 /* Can be used as a poll function that just polls for control events. */
 unsigned int v4l2_ctrl_poll(struct file *file, struct poll_table_struct *wait);
index 5c416cdc88d5d44eae38ce5e8445d5c2de6d2c78..95d1c91770f4a4d37d6931b607ab4ae94d2a34a0 100644 (file)
 #define VFL_TYPE_SUBDEV                3
 #define VFL_TYPE_MAX           4
 
+/* Is this a receiver, transmitter or mem-to-mem? */
+/* Ignored for VFL_TYPE_SUBDEV. */
+#define VFL_DIR_RX             0
+#define VFL_DIR_TX             1
+#define VFL_DIR_M2M            2
+
 struct v4l2_ioctl_callbacks;
 struct video_device;
 struct v4l2_device;
@@ -39,9 +45,6 @@ struct v4l2_ctrl_handler;
 #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)
-/* If ioctl core locking is in use, then apply that also to all
-   file operations. Don't use this flag in new drivers! */
-#define V4L2_FL_LOCK_ALL_FOPS  (3)
 
 /* Priority helper functions */
 
@@ -108,7 +111,8 @@ struct video_device
 
        /* device info */
        char name[32];
-       int vfl_type;
+       int vfl_type;   /* device type */
+       int vfl_dir;    /* receiver, transmitter or m2m */
        /* 'minor' is set to -1 if the registration failed */
        int minor;
        u16 num;
index 2885a810a128512afba7bb42803a75ff2203585a..e7c5d170a9cd48c42ae8876d279c1be1dd0479ec 100644 (file)
@@ -124,10 +124,10 @@ void v4l2_event_queue(struct video_device *vdev, const struct v4l2_event *ev);
 void v4l2_event_queue_fh(struct v4l2_fh *fh, const struct v4l2_event *ev);
 int v4l2_event_pending(struct v4l2_fh *fh);
 int v4l2_event_subscribe(struct v4l2_fh *fh,
-                        struct v4l2_event_subscription *sub, unsigned elems,
+                        const struct v4l2_event_subscription *sub, unsigned elems,
                         const struct v4l2_subscribed_event_ops *ops);
 int v4l2_event_unsubscribe(struct v4l2_fh *fh,
-                          struct v4l2_event_subscription *sub);
+                          const struct v4l2_event_subscription *sub);
 void v4l2_event_unsubscribe_all(struct v4l2_fh *fh);
 
 #endif /* V4L2_EVENT_H */
index e614c9c15e56ce0b396a8b03d47c81e08e197691..e48b571ca37d512111125bd8f49463622b38aae2 100644 (file)
@@ -40,8 +40,6 @@ struct v4l2_ioctl_ops {
                                              struct v4l2_fmtdesc *f);
        int (*vidioc_enum_fmt_vid_out_mplane)(struct file *file, void *fh,
                                              struct v4l2_fmtdesc *f);
-       int (*vidioc_enum_fmt_type_private)(struct file *file, void *fh,
-                                           struct v4l2_fmtdesc *f);
 
        /* VIDIOC_G_FMT handlers */
        int (*vidioc_g_fmt_vid_cap)    (struct file *file, void *fh,
@@ -64,8 +62,6 @@ struct v4l2_ioctl_ops {
                                           struct v4l2_format *f);
        int (*vidioc_g_fmt_vid_out_mplane)(struct file *file, void *fh,
                                           struct v4l2_format *f);
-       int (*vidioc_g_fmt_type_private)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
 
        /* VIDIOC_S_FMT handlers */
        int (*vidioc_s_fmt_vid_cap)    (struct file *file, void *fh,
@@ -88,8 +84,6 @@ struct v4l2_ioctl_ops {
                                           struct v4l2_format *f);
        int (*vidioc_s_fmt_vid_out_mplane)(struct file *file, void *fh,
                                           struct v4l2_format *f);
-       int (*vidioc_s_fmt_type_private)(struct file *file, void *fh,
-                                       struct v4l2_format *f);
 
        /* VIDIOC_TRY_FMT handlers */
        int (*vidioc_try_fmt_vid_cap)    (struct file *file, void *fh,
@@ -112,8 +106,6 @@ struct v4l2_ioctl_ops {
                                             struct v4l2_format *f);
        int (*vidioc_try_fmt_vid_out_mplane)(struct file *file, void *fh,
                                             struct v4l2_format *f);
-       int (*vidioc_try_fmt_type_private)(struct file *file, void *fh,
-                                         struct v4l2_format *f);
 
        /* Buffer handlers */
        int (*vidioc_reqbufs) (struct file *file, void *fh, struct v4l2_requestbuffers *b);
@@ -128,7 +120,7 @@ struct v4l2_ioctl_ops {
        int (*vidioc_g_fbuf)   (struct file *file, void *fh,
                                struct v4l2_framebuffer *a);
        int (*vidioc_s_fbuf)   (struct file *file, void *fh,
-                               struct v4l2_framebuffer *a);
+                               const struct v4l2_framebuffer *a);
 
                /* Stream on/off */
        int (*vidioc_streamon) (struct file *file, void *fh, enum v4l2_buf_type i);
@@ -175,7 +167,7 @@ struct v4l2_ioctl_ops {
        int (*vidioc_g_audio)          (struct file *file, void *fh,
                                        struct v4l2_audio *a);
        int (*vidioc_s_audio)          (struct file *file, void *fh,
-                                       struct v4l2_audio *a);
+                                       const struct v4l2_audio *a);
 
        /* Audio out ioctls */
        int (*vidioc_enumaudout)       (struct file *file, void *fh,
@@ -183,18 +175,18 @@ struct v4l2_ioctl_ops {
        int (*vidioc_g_audout)         (struct file *file, void *fh,
                                        struct v4l2_audioout *a);
        int (*vidioc_s_audout)         (struct file *file, void *fh,
-                                       struct v4l2_audioout *a);
+                                       const struct v4l2_audioout *a);
        int (*vidioc_g_modulator)      (struct file *file, void *fh,
                                        struct v4l2_modulator *a);
        int (*vidioc_s_modulator)      (struct file *file, void *fh,
-                                       struct v4l2_modulator *a);
+                                       const struct v4l2_modulator *a);
        /* Crop ioctls */
        int (*vidioc_cropcap)          (struct file *file, void *fh,
                                        struct v4l2_cropcap *a);
        int (*vidioc_g_crop)           (struct file *file, void *fh,
                                        struct v4l2_crop *a);
        int (*vidioc_s_crop)           (struct file *file, void *fh,
-                                       struct v4l2_crop *a);
+                                       const struct v4l2_crop *a);
        int (*vidioc_g_selection)      (struct file *file, void *fh,
                                        struct v4l2_selection *s);
        int (*vidioc_s_selection)      (struct file *file, void *fh,
@@ -203,7 +195,7 @@ struct v4l2_ioctl_ops {
        int (*vidioc_g_jpegcomp)       (struct file *file, void *fh,
                                        struct v4l2_jpegcompression *a);
        int (*vidioc_s_jpegcomp)       (struct file *file, void *fh,
-                                       struct v4l2_jpegcompression *a);
+                                       const struct v4l2_jpegcompression *a);
        int (*vidioc_g_enc_index)      (struct file *file, void *fh,
                                        struct v4l2_enc_idx *a);
        int (*vidioc_encoder_cmd)      (struct file *file, void *fh,
@@ -241,7 +233,7 @@ struct v4l2_ioctl_ops {
        int (*vidioc_log_status)       (struct file *file, void *fh);
 
        int (*vidioc_s_hw_freq_seek)   (struct file *file, void *fh,
-                                       struct v4l2_hw_freq_seek *a);
+                                       const struct v4l2_hw_freq_seek *a);
 
        /* Debugging ioctls */
 #ifdef CONFIG_VIDEO_ADV_DEBUG
@@ -281,9 +273,9 @@ struct v4l2_ioctl_ops {
                                    struct v4l2_dv_timings_cap *cap);
 
        int (*vidioc_subscribe_event)  (struct v4l2_fh *fh,
-                                       struct v4l2_event_subscription *sub);
+                                       const struct v4l2_event_subscription *sub);
        int (*vidioc_unsubscribe_event)(struct v4l2_fh *fh,
-                                       struct v4l2_event_subscription *sub);
+                                       const struct v4l2_event_subscription *sub);
 
        /* For other private ioctls */
        long (*vidioc_default)         (struct file *file, void *fh,
index 16ac4733e80d9bad5822a104f1faa6f1388abf24..131cc4a53675eb97f14c7cd4c5355e06640200d7 100644 (file)
@@ -140,7 +140,7 @@ void v4l2_m2m_buf_queue(struct v4l2_m2m_ctx *m2m_ctx, struct vb2_buffer *vb);
 static inline
 unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
 {
-       return m2m_ctx->cap_q_ctx.num_rdy;
+       return m2m_ctx->out_q_ctx.num_rdy;
 }
 
 /**
@@ -150,7 +150,7 @@ unsigned int v4l2_m2m_num_src_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
 static inline
 unsigned int v4l2_m2m_num_dst_bufs_ready(struct v4l2_m2m_ctx *m2m_ctx)
 {
-       return m2m_ctx->out_q_ctx.num_rdy;
+       return m2m_ctx->cap_q_ctx.num_rdy;
 }
 
 void *v4l2_m2m_next_buf(struct v4l2_m2m_queue_ctx *q_ctx);
index c35a3545e273258bf9afcb7a04fa512f55ef9685..b137a5e1151a5be0ad55c036f721ff6cb4bbe4e4 100644 (file)
@@ -21,6 +21,7 @@
 #ifndef _V4L2_SUBDEV_H
 #define _V4L2_SUBDEV_H
 
+#include <linux/types.h>
 #include <linux/v4l2-subdev.h>
 #include <media/media-entity.h>
 #include <media/v4l2-common.h>
@@ -45,6 +46,7 @@ struct v4l2_fh;
 struct v4l2_subdev;
 struct v4l2_subdev_fh;
 struct tuner_setup;
+struct v4l2_mbus_frame_desc;
 
 /* decode_vbi_line */
 struct v4l2_decode_vbi_line {
@@ -120,7 +122,7 @@ struct v4l2_subdev_io_pin_config {
        each pin being configured.  This function could be called at times
        other than just subdevice initialization.
 
-   init: initialize the sensor registors to some sort of reasonable default
+   init: initialize the sensor registers to some sort of reasonable default
        values. Do not use for new drivers and should be removed in existing
        drivers.
 
@@ -194,7 +196,7 @@ struct v4l2_subdev_tuner_ops {
        int (*g_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
        int (*s_tuner)(struct v4l2_subdev *sd, struct v4l2_tuner *vt);
        int (*g_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
-       int (*s_modulator)(struct v4l2_subdev *sd, struct v4l2_modulator *vm);
+       int (*s_modulator)(struct v4l2_subdev *sd, const struct v4l2_modulator *vm);
        int (*s_type_addr)(struct v4l2_subdev *sd, struct tuner_setup *type);
        int (*s_config)(struct v4l2_subdev *sd, const struct v4l2_priv_tun_config *config);
 };
@@ -226,6 +228,36 @@ struct v4l2_subdev_audio_ops {
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
 };
 
+/* Indicates the @length field specifies maximum data length. */
+#define V4L2_MBUS_FRAME_DESC_FL_LEN_MAX                (1U << 0)
+/* Indicates user defined data format, i.e. non standard frame format. */
+#define V4L2_MBUS_FRAME_DESC_FL_BLOB           (1U << 1)
+
+/**
+ * struct v4l2_mbus_frame_desc_entry - media bus frame description structure
+ * @flags: V4L2_MBUS_FRAME_DESC_FL_* flags
+ * @pixelcode: media bus pixel code, valid if FRAME_DESC_FL_BLOB is not set
+ * @length: number of octets per frame, valid for compressed or unspecified
+ *          formats
+ */
+struct v4l2_mbus_frame_desc_entry {
+       u16 flags;
+       u32 pixelcode;
+       u32 length;
+};
+
+#define V4L2_FRAME_DESC_ENTRY_MAX      4
+
+/**
+ * struct v4l2_mbus_frame_desc - media bus data frame description
+ * @entry: frame descriptors array
+ * @num_entries: number of entries in @entry array
+ */
+struct v4l2_mbus_frame_desc {
+       struct v4l2_mbus_frame_desc_entry entry[V4L2_FRAME_DESC_ENTRY_MAX];
+       unsigned short num_entries;
+};
+
 /*
    s_std_output: set v4l2_std_id for video OUTPUT devices. This is ignored by
        video input devices.
@@ -274,6 +306,10 @@ struct v4l2_subdev_audio_ops {
    s_mbus_config: set a certain mediabus configuration. This operation is added
        for compatibility with soc-camera drivers and should not be used by new
        software.
+
+   s_rx_buffer: set a host allocated memory buffer for the subdev. The subdev
+       can adjust @size to a lower value and must not write more data to the
+       buffer starting at @data than the original value of @size.
  */
 struct v4l2_subdev_video_ops {
        int (*s_routing)(struct v4l2_subdev *sd, u32 input, u32 output, u32 config);
@@ -286,7 +322,7 @@ struct v4l2_subdev_video_ops {
        int (*s_stream)(struct v4l2_subdev *sd, int enable);
        int (*cropcap)(struct v4l2_subdev *sd, struct v4l2_cropcap *cc);
        int (*g_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
-       int (*s_crop)(struct v4l2_subdev *sd, struct v4l2_crop *crop);
+       int (*s_crop)(struct v4l2_subdev *sd, const struct v4l2_crop *crop);
        int (*g_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
        int (*s_parm)(struct v4l2_subdev *sd, struct v4l2_streamparm *param);
        int (*g_frame_interval)(struct v4l2_subdev *sd,
@@ -327,6 +363,8 @@ struct v4l2_subdev_video_ops {
                             struct v4l2_mbus_config *cfg);
        int (*s_mbus_config)(struct v4l2_subdev *sd,
                             const struct v4l2_mbus_config *cfg);
+       int (*s_rx_buffer)(struct v4l2_subdev *sd, void *buf,
+                          unsigned int *size);
 };
 
 /*
@@ -455,6 +493,12 @@ struct v4l2_subdev_ir_ops {
                                struct v4l2_subdev_ir_parameters *params);
 };
 
+/**
+ * struct v4l2_subdev_pad_ops - v4l2-subdev pad level operations
+ * @get_frame_desc: get the current low level media bus frame parameters.
+ * @get_frame_desc: set the low level media bus frame parameters, @fd array
+ *                  may be adjusted by the subdev driver to device capabilities.
+ */
 struct v4l2_subdev_pad_ops {
        int (*enum_mbus_code)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                              struct v4l2_subdev_mbus_code_enum *code);
@@ -476,11 +520,17 @@ struct v4l2_subdev_pad_ops {
                             struct v4l2_subdev_selection *sel);
        int (*set_selection)(struct v4l2_subdev *sd, struct v4l2_subdev_fh *fh,
                             struct v4l2_subdev_selection *sel);
+       int (*get_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
+       int (*set_edid)(struct v4l2_subdev *sd, struct v4l2_subdev_edid *edid);
 #ifdef CONFIG_MEDIA_CONTROLLER
        int (*link_validate)(struct v4l2_subdev *sd, struct media_link *link,
                             struct v4l2_subdev_format *source_fmt,
                             struct v4l2_subdev_format *sink_fmt);
 #endif /* CONFIG_MEDIA_CONTROLLER */
+       int (*get_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
+       int (*set_frame_desc)(struct v4l2_subdev *sd, unsigned int pad,
+                             struct v4l2_mbus_frame_desc *fd);
 };
 
 struct v4l2_subdev_ops {
index bf365721d6b05f180169bfb4030c05b2c0345cab..d63965a1faaf6984aa2d1dd2c42e6984586801e5 100644 (file)
@@ -45,9 +45,7 @@ int videobuf_dvb_register_bus(struct videobuf_dvb_frontends *f,
                          void *adapter_priv,
                          struct device *device,
                          short *adapter_nr,
-                         int mfe_shared,
-                         int (*fe_ioctl_override)(struct dvb_frontend *,
-                                       unsigned int, void *, unsigned int));
+                         int mfe_shared);
 
 void videobuf_dvb_unregister_bus(struct videobuf_dvb_frontends *f);
 
index 8dd9b6cc296b57c2ee2b37612f796d6cb975aca1..e04252a9fea65e5f5db25a901368e82a3aa8b4d6 100644 (file)
@@ -324,7 +324,7 @@ int vb2_reqbufs(struct vb2_queue *q, struct v4l2_requestbuffers *req);
 int vb2_create_bufs(struct vb2_queue *q, struct v4l2_create_buffers *create);
 int vb2_prepare_buf(struct vb2_queue *q, struct v4l2_buffer *b);
 
-int vb2_queue_init(struct vb2_queue *q);
+int __must_check vb2_queue_init(struct vb2_queue *q);
 
 void vb2_queue_release(struct vb2_queue *q);
 
index ca356a7349202272236b9d7db421f6d8804d89a5..8b27927b2a55de3dfd5f94c5a40ef3c3b886eb06 100644 (file)
@@ -136,7 +136,7 @@ struct smp_chan {
 };
 
 /* SMP Commands */
-int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level);
+int smp_conn_security(struct hci_conn *hcon, __u8 sec_level);
 int smp_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb);
 int smp_distribute_keys(struct l2cap_conn *conn, __u8 force);
 int smp_user_confirm_reply(struct hci_conn *conn, u16 mgmt_op, __le32 passkey);
index 0fedbd8d747a049db1810fdc325b032d62782b1b..9fc7114159e885031550abedebf67c74f08bde76 100644 (file)
@@ -111,9 +111,8 @@ struct rt6_info {
        struct inet6_dev                *rt6i_idev;
        unsigned long                   _rt6i_peer;
 
-#ifdef CONFIG_XFRM
-       u32                             rt6i_flow_cache_genid;
-#endif
+       u32                             rt6i_genid;
+
        /* more non-fragment space at head required */
        unsigned short                  rt6i_nfheader_len;
 
index ae1cd6c9ba521bb6ca9a57706b4ca77180bdcc7a..fd87963a0ea5878cecae892541b9fc9f79e64814 100644 (file)
@@ -102,6 +102,7 @@ struct net {
 #endif
        struct netns_ipvs       *ipvs;
        struct sock             *diag_nlsk;
+       atomic_t                rt_genid;
 };
 
 
@@ -300,5 +301,14 @@ static inline void unregister_net_sysctl_table(struct ctl_table_header *header)
 }
 #endif
 
+static inline int rt_genid(struct net *net)
+{
+       return atomic_read(&net->rt_genid);
+}
+
+static inline void rt_genid_bump(struct net *net)
+{
+       atomic_inc(&net->rt_genid);
+}
 
 #endif /* __NET_NET_NAMESPACE_H */
index e1ce1048fe5fa1142196cb88e08829b7bb1d60f5..4a045cda9c60c75a96b956b051dfbf5a6d6581b7 100644 (file)
@@ -18,6 +18,7 @@ struct nf_conntrack_ecache {
        u16 ctmask;             /* bitmask of ct events to be delivered */
        u16 expmask;            /* bitmask of expect events to be delivered */
        u32 pid;                /* netlink pid of destroyer */
+       struct timer_list timeout;
 };
 
 static inline struct nf_conntrack_ecache *
index 1474dd65c66f558999a70f38c081dea247fbee5a..eb24dbccd81e81aff5fac76c8792e93df66e7bb6 100644 (file)
@@ -65,7 +65,6 @@ struct netns_ipv4 {
        unsigned int sysctl_ping_group_range[2];
        long sysctl_tcp_mem[3];
 
-       atomic_t rt_genid;
        atomic_t dev_addr_genid;
 
 #ifdef CONFIG_IP_MROUTE
index 776a27f1ab78ef5a385ef8b8d2f21b9e0101e115..da22243d27600cd66b5fb70da61f5cadc05d5468 100644 (file)
@@ -108,7 +108,7 @@ extern struct ip_rt_acct __percpu *ip_rt_acct;
 
 struct in_device;
 extern int             ip_rt_init(void);
-extern void            rt_cache_flush(struct net *net, int how);
+extern void            rt_cache_flush(struct net *net);
 extern void            rt_flush_dev(struct net_device *dev);
 extern struct rtable *__ip_route_output_key(struct net *, struct flowi4 *flp);
 extern struct rtable *ip_route_output_flow(struct net *, struct flowi4 *flp,
index 72132aef53fc61a721ce23c8fbc4fe17cb7a9699..adb7da20b5a10b2679d59734f6f46b971acf0094 100644 (file)
@@ -1332,7 +1332,7 @@ static inline bool sk_wmem_schedule(struct sock *sk, int size)
 }
 
 static inline bool
-sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, unsigned int size)
+sk_rmem_schedule(struct sock *sk, struct sk_buff *skb, int size)
 {
        if (!sk_has_account(sk))
                return true;
index 976a81abe1a231de348085a92c8f3110a21fc3fa..639dd1316d375aeb2802c73032cc4cae6dcb8b0c 100644 (file)
@@ -273,6 +273,9 @@ struct xfrm_replay {
        int     (*check)(struct xfrm_state *x,
                         struct sk_buff *skb,
                         __be32 net_seq);
+       int     (*recheck)(struct xfrm_state *x,
+                          struct sk_buff *skb,
+                          __be32 net_seq);
        void    (*notify)(struct xfrm_state *x, int event);
        int     (*overflow)(struct xfrm_state *x, struct sk_buff *skb);
 };
index fe8590cac5c2653b414ec4517e8ea0f35bcafb4a..098c4de4494573a3ecbb5f697d9fc9a34f8416a7 100644 (file)
@@ -28,6 +28,7 @@
 #include <media/v4l2-device.h>
 
 #define TEA575X_FMIF   10700
+#define TEA575X_AMIF     450
 
 #define TEA575X_DATA   (1 << 0)
 #define TEA575X_CLK    (1 << 1)
@@ -52,12 +53,14 @@ struct snd_tea575x {
        struct video_device vd;         /* video device */
        int radio_nr;                   /* radio_nr */
        bool tea5759;                   /* 5759 chip is present */
+       bool has_am;                    /* Device can tune to AM freqs */
        bool cannot_read_data;          /* Device cannot read the data pin */
        bool cannot_mute;               /* Device cannot mute */
        bool mute;                      /* Device is muted? */
        bool stereo;                    /* receiving stereo */
        bool tuned;                     /* tuned to a station */
        unsigned int val;               /* hw value */
+       u32 band;                       /* 0: FM, 1: FM-Japan, 2: AM */
        u32 freq;                       /* frequency */
        struct mutex mutex;
        struct snd_tea575x_ops *ops;
@@ -70,5 +73,6 @@ struct snd_tea575x {
 
 int snd_tea575x_init(struct snd_tea575x *tea, struct module *owner);
 void snd_tea575x_exit(struct snd_tea575x *tea);
+void snd_tea575x_set_freq(struct snd_tea575x *tea);
 
 #endif /* __SOUND_TEA575X_TUNER_H */
index f1405d335a968d093aadafee06ab4be105970f88..941c84bf1065f406cfbc3eeb5f4b09e4fdcd58ec 100644 (file)
@@ -23,7 +23,9 @@ struct se_subsystem_api {
        struct se_device *(*create_virtdevice)(struct se_hba *,
                                struct se_subsystem_dev *, void *);
        void (*free_device)(void *);
-       int (*transport_complete)(struct se_cmd *cmd, struct scatterlist *);
+       void (*transport_complete)(struct se_cmd *cmd,
+                                  struct scatterlist *,
+                                  unsigned char *);
 
        int (*parse_cdb)(struct se_cmd *cmd);
        ssize_t (*check_configfs_dev_params)(struct se_hba *,
index 015cea01ae39bedd1a1bf796e23a8f90f061e5e2..5be89373ceac659c92e671a463c80f146656c416 100644 (file)
 
 #define SE_INQUIRY_BUF                         512
 #define SE_MODE_PAGE_BUF                       512
+#define SE_SENSE_BUF                           96
 
 /* struct se_hba->hba_flags */
 enum hba_flags_table {
index 5f889f16b0c891dbedafd65686c48688aa7110da..08fa27244da740787539bd391ef3d61dc8060158 100644 (file)
@@ -214,7 +214,7 @@ TRACE_EVENT(mm_page_alloc,
 
        TP_printk("page=%p pfn=%lu order=%d migratetype=%d gfp_flags=%s",
                __entry->page,
-               page_to_pfn(__entry->page),
+               __entry->page ? page_to_pfn(__entry->page) : 0,
                __entry->order,
                __entry->migratetype,
                show_gfp_flags(__entry->gfp_flags))
@@ -240,7 +240,7 @@ DECLARE_EVENT_CLASS(mm_page,
 
        TP_printk("page=%p pfn=%lu order=%u migratetype=%d percpu_refill=%d",
                __entry->page,
-               page_to_pfn(__entry->page),
+               __entry->page ? page_to_pfn(__entry->page) : 0,
                __entry->order,
                __entry->migratetype,
                __entry->order == 0)
index 9c641deb65d2c62236343b4934d0db6ecb6c0dff..04399b28e821bf694a58d706e0b6c9f66e9c7d9f 100644 (file)
@@ -58,8 +58,6 @@ void notify_remote_via_irq(int irq);
 
 void xen_irq_resume(void);
 
-void xen_hvm_prepare_kexec(struct shared_info *sip, unsigned long pfn);
-
 /* Clear an irq's pending state, in preparation for polling on it */
 void xen_clear_irq_pending(int irq);
 void xen_set_irq_pending(int irq);
index 11e27c3af3cb45c63d9c689442096b4afd66c55f..f19fff8650e93075aae1717034f29898f1199646 100644 (file)
@@ -187,6 +187,7 @@ int gnttab_map_refs(struct gnttab_map_grant_ref *map_ops,
                    struct gnttab_map_grant_ref *kmap_ops,
                    struct page **pages, unsigned int count);
 int gnttab_unmap_refs(struct gnttab_unmap_grant_ref *unmap_ops,
-                     struct page **pages, unsigned int count, bool clear_pte);
+                     struct gnttab_map_grant_ref *kunmap_ops,
+                     struct page **pages, unsigned int count);
 
 #endif /* __ASM_GNTTAB_H__ */
index b7935fcec7d923b0b0b89fe0fe7dfdf61967b447..7fee567153f022cc2a097135a524bf393887e1a2 100644 (file)
@@ -1253,7 +1253,7 @@ retry:
 /*
  * Cross CPU call to disable a performance event
  */
-static int __perf_event_disable(void *info)
+int __perf_event_disable(void *info)
 {
        struct perf_event *event = info;
        struct perf_event_context *ctx = event->ctx;
@@ -2935,12 +2935,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel);
 /*
  * Called when the last reference to the file is gone.
  */
-static int perf_release(struct inode *inode, struct file *file)
+static void put_event(struct perf_event *event)
 {
-       struct perf_event *event = file->private_data;
        struct task_struct *owner;
 
-       file->private_data = NULL;
+       if (!atomic_long_dec_and_test(&event->refcount))
+               return;
 
        rcu_read_lock();
        owner = ACCESS_ONCE(event->owner);
@@ -2975,7 +2975,13 @@ static int perf_release(struct inode *inode, struct file *file)
                put_task_struct(owner);
        }
 
-       return perf_event_release_kernel(event);
+       perf_event_release_kernel(event);
+}
+
+static int perf_release(struct inode *inode, struct file *file)
+{
+       put_event(file->private_data);
+       return 0;
 }
 
 u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
@@ -3227,7 +3233,7 @@ unlock:
 
 static const struct file_operations perf_fops;
 
-static struct perf_event *perf_fget_light(int fd, int *fput_needed)
+static struct file *perf_fget_light(int fd, int *fput_needed)
 {
        struct file *file;
 
@@ -3241,7 +3247,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed)
                return ERR_PTR(-EBADF);
        }
 
-       return file->private_data;
+       return file;
 }
 
 static int perf_event_set_output(struct perf_event *event,
@@ -3273,19 +3279,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 
        case PERF_EVENT_IOC_SET_OUTPUT:
        {
+               struct file *output_file = NULL;
                struct perf_event *output_event = NULL;
                int fput_needed = 0;
                int ret;
 
                if (arg != -1) {
-                       output_event = perf_fget_light(arg, &fput_needed);
-                       if (IS_ERR(output_event))
-                               return PTR_ERR(output_event);
+                       output_file = perf_fget_light(arg, &fput_needed);
+                       if (IS_ERR(output_file))
+                               return PTR_ERR(output_file);
+                       output_event = output_file->private_data;
                }
 
                ret = perf_event_set_output(event, output_event);
                if (output_event)
-                       fput_light(output_event->filp, fput_needed);
+                       fput_light(output_file, fput_needed);
 
                return ret;
        }
@@ -5950,6 +5958,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
 
        mutex_init(&event->mmap_mutex);
 
+       atomic_long_set(&event->refcount, 1);
        event->cpu              = cpu;
        event->attr             = *attr;
        event->group_leader     = group_leader;
@@ -6260,12 +6269,12 @@ SYSCALL_DEFINE5(perf_event_open,
                return event_fd;
 
        if (group_fd != -1) {
-               group_leader = perf_fget_light(group_fd, &fput_needed);
-               if (IS_ERR(group_leader)) {
-                       err = PTR_ERR(group_leader);
+               group_file = perf_fget_light(group_fd, &fput_needed);
+               if (IS_ERR(group_file)) {
+                       err = PTR_ERR(group_file);
                        goto err_fd;
                }
-               group_file = group_leader->filp;
+               group_leader = group_file->private_data;
                if (flags & PERF_FLAG_FD_OUTPUT)
                        output_event = group_leader;
                if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6402,7 +6411,6 @@ SYSCALL_DEFINE5(perf_event_open,
                put_ctx(gctx);
        }
 
-       event->filp = event_file;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
 
@@ -6496,7 +6504,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
                goto err_free;
        }
 
-       event->filp = NULL;
        WARN_ON_ONCE(ctx->parent_ctx);
        mutex_lock(&ctx->mutex);
        perf_install_in_context(ctx, event, cpu);
@@ -6578,7 +6585,7 @@ static void sync_child_event(struct perf_event *child_event,
         * Release the parent event, if this was the last
         * reference to it.
         */
-       fput(parent_event->filp);
+       put_event(parent_event);
 }
 
 static void
@@ -6654,9 +6661,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
         *
         *   __perf_event_exit_task()
         *     sync_child_event()
-        *       fput(parent_event->filp)
-        *         perf_release()
-        *           mutex_lock(&ctx->mutex)
+        *       put_event()
+        *         mutex_lock(&ctx->mutex)
         *
         * But since its the parent context it won't be the same instance.
         */
@@ -6724,7 +6730,7 @@ static void perf_free_event(struct perf_event *event,
        list_del_init(&event->child_list);
        mutex_unlock(&parent->child_mutex);
 
-       fput(parent->filp);
+       put_event(parent);
 
        perf_group_detach(event);
        list_del_event(event, ctx);
@@ -6804,6 +6810,12 @@ inherit_event(struct perf_event *parent_event,
                                           NULL, NULL);
        if (IS_ERR(child_event))
                return child_event;
+
+       if (!atomic_long_inc_not_zero(&parent_event->refcount)) {
+               free_event(child_event);
+               return NULL;
+       }
+
        get_ctx(child_ctx);
 
        /*
@@ -6844,14 +6856,6 @@ inherit_event(struct perf_event *parent_event,
        add_event_to_ctx(child_event, child_ctx);
        raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
 
-       /*
-        * Get a reference to the parent filp - we will fput it
-        * when the child event exits. This is safe to do because
-        * we are in the parent and we know that the filp still
-        * exists and has a nonzero count:
-        */
-       atomic_long_inc(&parent_event->filp->f_count);
-
        /*
         * Link this into the parent event's child list
         */
index bb38c4d3ee129ab06c1b46dc295ca6864c39c416..9a7b487c6fe240c1a2e4f5c70ef68da6370ebf78 100644 (file)
@@ -453,7 +453,16 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
        int old_type = bp->attr.bp_type;
        int err = 0;
 
-       perf_event_disable(bp);
+       /*
+        * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it
+        * will not be possible to raise IPIs that invoke __perf_event_disable.
+        * So call the function directly after making sure we are targeting the
+        * current task.
+        */
+       if (irqs_disabled() && bp->ctx && bp->ctx->task == current)
+               __perf_event_disable(bp);
+       else
+               perf_event_disable(bp);
 
        bp->attr.bp_addr = attr->bp_addr;
        bp->attr.bp_type = attr->bp_type;
index 3bd2280d79f6b5507537c3e294e05c77a69d678f..2c8857e12855393759562b3c6eeec2d23de6f080 100644 (file)
@@ -455,8 +455,8 @@ static int dup_mmap(struct mm_struct *mm, struct mm_struct *oldmm)
                if (retval)
                        goto out;
 
-               if (file && uprobe_mmap(tmp))
-                       goto out;
+               if (file)
+                       uprobe_mmap(tmp);
        }
        /* a new mm has just been created */
        arch_dup_mmap(oldmm, mm);
index b3c7fd5542500ab13940814211692bbe3b7ef8d3..6144bab8fd8eeed14327c116bea39ba0061cbdb5 100644 (file)
@@ -232,15 +232,19 @@ static int pid_ns_ctl_handler(struct ctl_table *table, int write,
         */
 
        tmp.data = &current->nsproxy->pid_ns->last_pid;
-       return proc_dointvec(&tmp, write, buffer, lenp, ppos);
+       return proc_dointvec_minmax(&tmp, write, buffer, lenp, ppos);
 }
 
+extern int pid_max;
+static int zero = 0;
 static struct ctl_table pid_ns_ctl_table[] = {
        {
                .procname = "ns_last_pid",
                .maxlen = sizeof(int),
                .mode = 0666, /* permissions are checked in the handler */
                .proc_handler = pid_ns_ctl_handler,
+               .extra1 = &zero,
+               .extra2 = &pid_max,
        },
        { }
 };
index fbf1fd098dc6cca687f0e9296a931aa0425c6fee..649c9f876cb164b0e16683479b59bf4d4f3b794b 100644 (file)
@@ -5304,27 +5304,17 @@ void idle_task_exit(void)
 }
 
 /*
- * While a dead CPU has no uninterruptible tasks queued at this point,
- * it might still have a nonzero ->nr_uninterruptible counter, because
- * for performance reasons the counter is not stricly tracking tasks to
- * their home CPUs. So we just add the counter to another CPU's counter,
- * to keep the global sum constant after CPU-down:
- */
-static void migrate_nr_uninterruptible(struct rq *rq_src)
-{
-       struct rq *rq_dest = cpu_rq(cpumask_any(cpu_active_mask));
-
-       rq_dest->nr_uninterruptible += rq_src->nr_uninterruptible;
-       rq_src->nr_uninterruptible = 0;
-}
-
-/*
- * remove the tasks which were accounted by rq from calc_load_tasks.
+ * Since this CPU is going 'away' for a while, fold any nr_active delta
+ * we might have. Assumes we're called after migrate_tasks() so that the
+ * nr_active count is stable.
+ *
+ * Also see the comment "Global load-average calculations".
  */
-static void calc_global_load_remove(struct rq *rq)
+static void calc_load_migrate(struct rq *rq)
 {
-       atomic_long_sub(rq->calc_load_active, &calc_load_tasks);
-       rq->calc_load_active = 0;
+       long delta = calc_load_fold_active(rq);
+       if (delta)
+               atomic_long_add(delta, &calc_load_tasks);
 }
 
 /*
@@ -5352,9 +5342,6 @@ static void migrate_tasks(unsigned int dead_cpu)
         */
        rq->stop = NULL;
 
-       /* Ensure any throttled groups are reachable by pick_next_task */
-       unthrottle_offline_cfs_rqs(rq);
-
        for ( ; ; ) {
                /*
                 * There's this thread running, bail when that's the only
@@ -5618,8 +5605,7 @@ migration_call(struct notifier_block *nfb, unsigned long action, void *hcpu)
                BUG_ON(rq->nr_running != 1); /* the migration thread */
                raw_spin_unlock_irqrestore(&rq->lock, flags);
 
-               migrate_nr_uninterruptible(rq);
-               calc_global_load_remove(rq);
+               calc_load_migrate(rq);
                break;
 #endif
        }
@@ -6028,11 +6014,6 @@ static void destroy_sched_domains(struct sched_domain *sd, int cpu)
  * SD_SHARE_PKG_RESOURCE set (Last Level Cache Domain) for this
  * allows us to avoid some pointer chasing select_idle_sibling().
  *
- * Iterate domains and sched_groups downward, assigning CPUs to be
- * select_idle_sibling() hw buddy.  Cross-wiring hw makes bouncing
- * due to random perturbation self canceling, ie sw buddies pull
- * their counterpart to their CPU's hw counterpart.
- *
  * Also keep a unique ID per domain (we use the first cpu number in
  * the cpumask of the domain), this allows us to quickly tell if
  * two cpus are in the same cache domain, see cpus_share_cache().
@@ -6046,40 +6027,8 @@ static void update_top_cache_domain(int cpu)
        int id = cpu;
 
        sd = highest_flag_domain(cpu, SD_SHARE_PKG_RESOURCES);
-       if (sd) {
-               struct sched_domain *tmp = sd;
-               struct sched_group *sg, *prev;
-               bool right;
-
-               /*
-                * Traverse to first CPU in group, and count hops
-                * to cpu from there, switching direction on each
-                * hop, never ever pointing the last CPU rightward.
-                */
-               do {
-                       id = cpumask_first(sched_domain_span(tmp));
-                       prev = sg = tmp->groups;
-                       right = 1;
-
-                       while (cpumask_first(sched_group_cpus(sg)) != id)
-                               sg = sg->next;
-
-                       while (!cpumask_test_cpu(cpu, sched_group_cpus(sg))) {
-                               prev = sg;
-                               sg = sg->next;
-                               right = !right;
-                       }
-
-                       /* A CPU went down, never point back to domain start. */
-                       if (right && cpumask_first(sched_group_cpus(sg->next)) == id)
-                               right = false;
-
-                       sg = right ? sg->next : prev;
-                       tmp->idle_buddy = cpumask_first(sched_group_cpus(sg));
-               } while ((tmp = tmp->child));
-
+       if (sd)
                id = cpumask_first(sched_domain_span(sd));
-       }
 
        rcu_assign_pointer(per_cpu(sd_llc, cpu), sd);
        per_cpu(sd_llc_id, cpu) = id;
index c219bf8d704c5460291abee8416264ee32d36e22..96e2b18b628312dd69e8ad2ee6e3a6e08f33cce7 100644 (file)
@@ -2052,7 +2052,7 @@ static void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b)
        hrtimer_cancel(&cfs_b->slack_timer);
 }
 
-void unthrottle_offline_cfs_rqs(struct rq *rq)
+static void unthrottle_offline_cfs_rqs(struct rq *rq)
 {
        struct cfs_rq *cfs_rq;
 
@@ -2106,7 +2106,7 @@ static inline struct cfs_bandwidth *tg_cfs_bandwidth(struct task_group *tg)
        return NULL;
 }
 static inline void destroy_cfs_bandwidth(struct cfs_bandwidth *cfs_b) {}
-void unthrottle_offline_cfs_rqs(struct rq *rq) {}
+static inline void unthrottle_offline_cfs_rqs(struct rq *rq) {}
 
 #endif /* CONFIG_CFS_BANDWIDTH */
 
@@ -2637,6 +2637,8 @@ static int select_idle_sibling(struct task_struct *p, int target)
        int cpu = smp_processor_id();
        int prev_cpu = task_cpu(p);
        struct sched_domain *sd;
+       struct sched_group *sg;
+       int i;
 
        /*
         * If the task is going to be woken-up on this cpu and if it is
@@ -2653,17 +2655,29 @@ static int select_idle_sibling(struct task_struct *p, int target)
                return prev_cpu;
 
        /*
-        * Otherwise, check assigned siblings to find an elegible idle cpu.
+        * Otherwise, iterate the domains and find an elegible idle cpu.
         */
        sd = rcu_dereference(per_cpu(sd_llc, target));
-
        for_each_lower_domain(sd) {
-               if (!cpumask_test_cpu(sd->idle_buddy, tsk_cpus_allowed(p)))
-                       continue;
-               if (idle_cpu(sd->idle_buddy))
-                       return sd->idle_buddy;
-       }
+               sg = sd->groups;
+               do {
+                       if (!cpumask_intersects(sched_group_cpus(sg),
+                                               tsk_cpus_allowed(p)))
+                               goto next;
 
+                       for_each_cpu(i, sched_group_cpus(sg)) {
+                               if (!idle_cpu(i))
+                                       goto next;
+                       }
+
+                       target = cpumask_first_and(sched_group_cpus(sg),
+                                       tsk_cpus_allowed(p));
+                       goto done;
+next:
+                       sg = sg->next;
+               } while (sg != sd->groups);
+       }
+done:
        return target;
 }
 
@@ -3658,7 +3672,6 @@ fix_small_capacity(struct sched_domain *sd, struct sched_group *group)
  * @group: sched_group whose statistics are to be updated.
  * @load_idx: Load index of sched_domain of this_cpu for load calc.
  * @local_group: Does group contain this_cpu.
- * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
  * @sgs: variable to hold the statistics for this group.
  */
@@ -3805,7 +3818,6 @@ static bool update_sd_pick_busiest(struct lb_env *env,
 /**
  * update_sd_lb_stats - Update sched_domain's statistics for load balancing.
  * @env: The load balancing environment.
- * @cpus: Set of cpus considered for load balancing.
  * @balance: Should we balance.
  * @sds: variable to hold the statistics for this sched_domain.
  */
@@ -4956,6 +4968,9 @@ static void rq_online_fair(struct rq *rq)
 static void rq_offline_fair(struct rq *rq)
 {
        update_sysctl();
+
+       /* Ensure any throttled groups are reachable by pick_next_task */
+       unthrottle_offline_cfs_rqs(rq);
 }
 
 #endif /* CONFIG_SMP */
index 944cb68420e957cbde71f9cacaaa4e81c4b1de20..e0b7ba9c040f74b22bb63e0d957b672dac4adce0 100644 (file)
@@ -691,6 +691,7 @@ balanced:
                 * runtime - in which case borrowing doesn't make sense.
                 */
                rt_rq->rt_runtime = RUNTIME_INF;
+               rt_rq->rt_throttled = 0;
                raw_spin_unlock(&rt_rq->rt_runtime_lock);
                raw_spin_unlock(&rt_b->rt_runtime_lock);
        }
index f6714d009e779a225ef295d33ceff7f2f8573be8..0848fa36c383e940a1e4245c611312dbdb7459d3 100644 (file)
@@ -1144,7 +1144,6 @@ extern void print_rt_stats(struct seq_file *m, int cpu);
 
 extern void init_cfs_rq(struct cfs_rq *cfs_rq);
 extern void init_rt_rq(struct rt_rq *rt_rq, struct rq *rq);
-extern void unthrottle_offline_cfs_rqs(struct rq *rq);
 
 extern void account_cfs_bandwidth_used(int enabled, int was_enabled);
 
index 024540f97f74c3e94205826f33d3968ea765f626..3a9e5d5c10916a7e67c131df489617a485a39bfc 100644 (file)
@@ -573,6 +573,7 @@ static void tick_nohz_restart_sched_tick(struct tick_sched *ts, ktime_t now)
        tick_do_update_jiffies64(now);
        update_cpu_load_nohz();
 
+       calc_load_exit_idle();
        touch_softlockup_watchdog();
        /*
         * Cancel the scheduled timer and restore the tick
index e16af197a2bc54c8f81070a1043ed1f81923679f..d3b91e75cecd0df7895033aff87f588c6ba2d4df 100644 (file)
@@ -115,6 +115,7 @@ static void tk_xtime_add(struct timekeeper *tk, const struct timespec *ts)
 {
        tk->xtime_sec += ts->tv_sec;
        tk->xtime_nsec += (u64)ts->tv_nsec << tk->shift;
+       tk_normalize_xtime(tk);
 }
 
 static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
@@ -276,7 +277,7 @@ static void timekeeping_forward_now(struct timekeeper *tk)
        tk->xtime_nsec += cycle_delta * tk->mult;
 
        /* If arch requires, add in gettimeoffset() */
-       tk->xtime_nsec += arch_gettimeoffset() << tk->shift;
+       tk->xtime_nsec += (u64)arch_gettimeoffset() << tk->shift;
 
        tk_normalize_xtime(tk);
 
@@ -302,10 +303,11 @@ void getnstimeofday(struct timespec *ts)
                seq = read_seqbegin(&tk->lock);
 
                ts->tv_sec = tk->xtime_sec;
-               ts->tv_nsec = timekeeping_get_ns(tk);
+               nsecs = timekeeping_get_ns(tk);
 
        } while (read_seqretry(&tk->lock, seq));
 
+       ts->tv_nsec = 0;
        timespec_add_ns(ts, nsecs);
 }
 EXPORT_SYMBOL(getnstimeofday);
@@ -344,6 +346,7 @@ void ktime_get_ts(struct timespec *ts)
 {
        struct timekeeper *tk = &timekeeper;
        struct timespec tomono;
+       s64 nsec;
        unsigned int seq;
 
        WARN_ON(timekeeping_suspended);
@@ -351,13 +354,14 @@ void ktime_get_ts(struct timespec *ts)
        do {
                seq = read_seqbegin(&tk->lock);
                ts->tv_sec = tk->xtime_sec;
-               ts->tv_nsec = timekeeping_get_ns(tk);
+               nsec = timekeeping_get_ns(tk);
                tomono = tk->wall_to_monotonic;
 
        } while (read_seqretry(&tk->lock, seq));
 
-       set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec,
-                               ts->tv_nsec + tomono.tv_nsec);
+       ts->tv_sec += tomono.tv_sec;
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, nsec + tomono.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(ktime_get_ts);
 
@@ -427,7 +431,7 @@ int do_settimeofday(const struct timespec *tv)
        struct timespec ts_delta, xt;
        unsigned long flags;
 
-       if ((unsigned long)tv->tv_nsec >= NSEC_PER_SEC)
+       if (!timespec_valid_strict(tv))
                return -EINVAL;
 
        write_seqlock_irqsave(&tk->lock, flags);
@@ -463,6 +467,8 @@ int timekeeping_inject_offset(struct timespec *ts)
 {
        struct timekeeper *tk = &timekeeper;
        unsigned long flags;
+       struct timespec tmp;
+       int ret = 0;
 
        if ((unsigned long)ts->tv_nsec >= NSEC_PER_SEC)
                return -EINVAL;
@@ -471,10 +477,17 @@ int timekeeping_inject_offset(struct timespec *ts)
 
        timekeeping_forward_now(tk);
 
+       /* Make sure the proposed value is valid */
+       tmp = timespec_add(tk_xtime(tk),  *ts);
+       if (!timespec_valid_strict(&tmp)) {
+               ret = -EINVAL;
+               goto error;
+       }
 
        tk_xtime_add(tk, ts);
        tk_set_wall_to_mono(tk, timespec_sub(tk->wall_to_monotonic, *ts));
 
+error: /* even if we error out, we forwarded the time, so call update */
        timekeeping_update(tk, true);
 
        write_sequnlock_irqrestore(&tk->lock, flags);
@@ -482,7 +495,7 @@ int timekeeping_inject_offset(struct timespec *ts)
        /* signal hrtimers about time change */
        clock_was_set();
 
-       return 0;
+       return ret;
 }
 EXPORT_SYMBOL(timekeeping_inject_offset);
 
@@ -649,7 +662,20 @@ void __init timekeeping_init(void)
        struct timespec now, boot, tmp;
 
        read_persistent_clock(&now);
+       if (!timespec_valid_strict(&now)) {
+               pr_warn("WARNING: Persistent clock returned invalid value!\n"
+                       "         Check your CMOS/BIOS settings.\n");
+               now.tv_sec = 0;
+               now.tv_nsec = 0;
+       }
+
        read_boot_clock(&boot);
+       if (!timespec_valid_strict(&boot)) {
+               pr_warn("WARNING: Boot clock returned invalid value!\n"
+                       "         Check your CMOS/BIOS settings.\n");
+               boot.tv_sec = 0;
+               boot.tv_nsec = 0;
+       }
 
        seqlock_init(&tk->lock);
 
@@ -690,7 +716,7 @@ static struct timespec timekeeping_suspend_time;
 static void __timekeeping_inject_sleeptime(struct timekeeper *tk,
                                                        struct timespec *delta)
 {
-       if (!timespec_valid(delta)) {
+       if (!timespec_valid_strict(delta)) {
                printk(KERN_WARNING "__timekeeping_inject_sleeptime: Invalid "
                                        "sleep delta value!\n");
                return;
@@ -1129,6 +1155,10 @@ static void update_wall_time(void)
        offset = (clock->read(clock) - clock->cycle_last) & clock->mask;
 #endif
 
+       /* Check if there's really nothing to do */
+       if (offset < tk->cycle_interval)
+               goto out;
+
        /*
         * With NO_HZ we may have to accumulate many cycle_intervals
         * (think "ticks") worth of time at once. To do this efficiently,
@@ -1161,9 +1191,9 @@ static void update_wall_time(void)
        * the vsyscall implementations are converted to use xtime_nsec
        * (shifted nanoseconds), this can be killed.
        */
-       remainder = tk->xtime_nsec & ((1 << tk->shift) - 1);
+       remainder = tk->xtime_nsec & ((1ULL << tk->shift) - 1);
        tk->xtime_nsec -= remainder;
-       tk->xtime_nsec += 1 << tk->shift;
+       tk->xtime_nsec += 1ULL << tk->shift;
        tk->ntp_error += remainder << tk->ntp_error_shift;
 
        /*
@@ -1217,6 +1247,7 @@ void get_monotonic_boottime(struct timespec *ts)
 {
        struct timekeeper *tk = &timekeeper;
        struct timespec tomono, sleep;
+       s64 nsec;
        unsigned int seq;
 
        WARN_ON(timekeeping_suspended);
@@ -1224,14 +1255,15 @@ void get_monotonic_boottime(struct timespec *ts)
        do {
                seq = read_seqbegin(&tk->lock);
                ts->tv_sec = tk->xtime_sec;
-               ts->tv_nsec = timekeeping_get_ns(tk);
+               nsec = timekeeping_get_ns(tk);
                tomono = tk->wall_to_monotonic;
                sleep = tk->total_sleep_time;
 
        } while (read_seqretry(&tk->lock, seq));
 
-       set_normalized_timespec(ts, ts->tv_sec + tomono.tv_sec + sleep.tv_sec,
-                       ts->tv_nsec + tomono.tv_nsec + sleep.tv_nsec);
+       ts->tv_sec += tomono.tv_sec + sleep.tv_sec;
+       ts->tv_nsec = 0;
+       timespec_add_ns(ts, nsec + tomono.tv_nsec + sleep.tv_nsec);
 }
 EXPORT_SYMBOL_GPL(get_monotonic_boottime);
 
index 60e4d78756723189b95d11390bc566a6578a4bbe..6b245f64c8dd850bbbd7a16132d997fccd25206e 100644 (file)
@@ -506,6 +506,8 @@ static void perf_syscall_enter(void *ignore, struct pt_regs *regs, long id)
        int size;
 
        syscall_nr = syscall_get_nr(current, regs);
+       if (syscall_nr < 0)
+               return;
        if (!test_bit(syscall_nr, enabled_perf_enter_syscalls))
                return;
 
@@ -580,6 +582,8 @@ static void perf_syscall_exit(void *ignore, struct pt_regs *regs, long ret)
        int size;
 
        syscall_nr = syscall_get_nr(current, regs);
+       if (syscall_nr < 0)
+               return;
        if (!test_bit(syscall_nr, enabled_perf_exit_syscalls))
                return;
 
index 692d97628a106360683dfef46797952cdf1861e1..3c5a79e2134cac6f404673093a84df5c8b371d80 100644 (file)
@@ -66,6 +66,7 @@ enum {
 
        /* pool flags */
        POOL_MANAGE_WORKERS     = 1 << 0,       /* need to manage workers */
+       POOL_MANAGING_WORKERS   = 1 << 1,       /* managing workers */
 
        /* worker flags */
        WORKER_STARTED          = 1 << 0,       /* started */
@@ -652,7 +653,7 @@ static bool need_to_manage_workers(struct worker_pool *pool)
 /* Do we have too many workers and should some go away? */
 static bool too_many_workers(struct worker_pool *pool)
 {
-       bool managing = mutex_is_locked(&pool->manager_mutex);
+       bool managing = pool->flags & POOL_MANAGING_WORKERS;
        int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
        int nr_busy = pool->nr_workers - nr_idle;
 
@@ -1326,6 +1327,15 @@ static void idle_worker_rebind(struct worker *worker)
 
        /* we did our part, wait for rebind_workers() to finish up */
        wait_event(gcwq->rebind_hold, !(worker->flags & WORKER_REBIND));
+
+       /*
+        * rebind_workers() shouldn't finish until all workers passed the
+        * above WORKER_REBIND wait.  Tell it when done.
+        */
+       spin_lock_irq(&worker->pool->gcwq->lock);
+       if (!--worker->idle_rebind->cnt)
+               complete(&worker->idle_rebind->done);
+       spin_unlock_irq(&worker->pool->gcwq->lock);
 }
 
 /*
@@ -1339,8 +1349,16 @@ static void busy_worker_rebind_fn(struct work_struct *work)
        struct worker *worker = container_of(work, struct worker, rebind_work);
        struct global_cwq *gcwq = worker->pool->gcwq;
 
-       if (worker_maybe_bind_and_lock(worker))
-               worker_clr_flags(worker, WORKER_REBIND);
+       worker_maybe_bind_and_lock(worker);
+
+       /*
+        * %WORKER_REBIND must be cleared even if the above binding failed;
+        * otherwise, we may confuse the next CPU_UP cycle or oops / get
+        * stuck by calling idle_worker_rebind() prematurely.  If CPU went
+        * down again inbetween, %WORKER_UNBOUND would be set, so clearing
+        * %WORKER_REBIND is always safe.
+        */
+       worker_clr_flags(worker, WORKER_REBIND);
 
        spin_unlock_irq(&gcwq->lock);
 }
@@ -1396,12 +1414,15 @@ retry:
        /* set REBIND and kick idle ones, we'll wait for these later */
        for_each_worker_pool(pool, gcwq) {
                list_for_each_entry(worker, &pool->idle_list, entry) {
+                       unsigned long worker_flags = worker->flags;
+
                        if (worker->flags & WORKER_REBIND)
                                continue;
 
-                       /* morph UNBOUND to REBIND */
-                       worker->flags &= ~WORKER_UNBOUND;
-                       worker->flags |= WORKER_REBIND;
+                       /* morph UNBOUND to REBIND atomically */
+                       worker_flags &= ~WORKER_UNBOUND;
+                       worker_flags |= WORKER_REBIND;
+                       ACCESS_ONCE(worker->flags) = worker_flags;
 
                        idle_rebind.cnt++;
                        worker->idle_rebind = &idle_rebind;
@@ -1419,25 +1440,15 @@ retry:
                goto retry;
        }
 
-       /*
-        * All idle workers are rebound and waiting for %WORKER_REBIND to
-        * be cleared inside idle_worker_rebind().  Clear and release.
-        * Clearing %WORKER_REBIND from this foreign context is safe
-        * because these workers are still guaranteed to be idle.
-        */
-       for_each_worker_pool(pool, gcwq)
-               list_for_each_entry(worker, &pool->idle_list, entry)
-                       worker->flags &= ~WORKER_REBIND;
-
-       wake_up_all(&gcwq->rebind_hold);
-
-       /* rebind busy workers */
+       /* all idle workers are rebound, rebind busy workers */
        for_each_busy_worker(worker, i, pos, gcwq) {
                struct work_struct *rebind_work = &worker->rebind_work;
+               unsigned long worker_flags = worker->flags;
 
-               /* morph UNBOUND to REBIND */
-               worker->flags &= ~WORKER_UNBOUND;
-               worker->flags |= WORKER_REBIND;
+               /* morph UNBOUND to REBIND atomically */
+               worker_flags &= ~WORKER_UNBOUND;
+               worker_flags |= WORKER_REBIND;
+               ACCESS_ONCE(worker->flags) = worker_flags;
 
                if (test_and_set_bit(WORK_STRUCT_PENDING_BIT,
                                     work_data_bits(rebind_work)))
@@ -1449,6 +1460,34 @@ retry:
                            worker->scheduled.next,
                            work_color_to_flags(WORK_NO_COLOR));
        }
+
+       /*
+        * All idle workers are rebound and waiting for %WORKER_REBIND to
+        * be cleared inside idle_worker_rebind().  Clear and release.
+        * Clearing %WORKER_REBIND from this foreign context is safe
+        * because these workers are still guaranteed to be idle.
+        *
+        * We need to make sure all idle workers passed WORKER_REBIND wait
+        * in idle_worker_rebind() before returning; otherwise, workers can
+        * get stuck at the wait if hotplug cycle repeats.
+        */
+       idle_rebind.cnt = 1;
+       INIT_COMPLETION(idle_rebind.done);
+
+       for_each_worker_pool(pool, gcwq) {
+               list_for_each_entry(worker, &pool->idle_list, entry) {
+                       worker->flags &= ~WORKER_REBIND;
+                       idle_rebind.cnt++;
+               }
+       }
+
+       wake_up_all(&gcwq->rebind_hold);
+
+       if (--idle_rebind.cnt) {
+               spin_unlock_irq(&gcwq->lock);
+               wait_for_completion(&idle_rebind.done);
+               spin_lock_irq(&gcwq->lock);
+       }
 }
 
 static struct worker *alloc_worker(void)
@@ -1794,9 +1833,45 @@ static bool manage_workers(struct worker *worker)
        struct worker_pool *pool = worker->pool;
        bool ret = false;
 
-       if (!mutex_trylock(&pool->manager_mutex))
+       if (pool->flags & POOL_MANAGING_WORKERS)
                return ret;
 
+       pool->flags |= POOL_MANAGING_WORKERS;
+
+       /*
+        * To simplify both worker management and CPU hotplug, hold off
+        * management while hotplug is in progress.  CPU hotplug path can't
+        * grab %POOL_MANAGING_WORKERS to achieve this because that can
+        * lead to idle worker depletion (all become busy thinking someone
+        * else is managing) which in turn can result in deadlock under
+        * extreme circumstances.  Use @pool->manager_mutex to synchronize
+        * manager against CPU hotplug.
+        *
+        * manager_mutex would always be free unless CPU hotplug is in
+        * progress.  trylock first without dropping @gcwq->lock.
+        */
+       if (unlikely(!mutex_trylock(&pool->manager_mutex))) {
+               spin_unlock_irq(&pool->gcwq->lock);
+               mutex_lock(&pool->manager_mutex);
+               /*
+                * CPU hotplug could have happened while we were waiting
+                * for manager_mutex.  Hotplug itself can't handle us
+                * because manager isn't either on idle or busy list, and
+                * @gcwq's state and ours could have deviated.
+                *
+                * As hotplug is now excluded via manager_mutex, we can
+                * simply try to bind.  It will succeed or fail depending
+                * on @gcwq's current state.  Try it and adjust
+                * %WORKER_UNBOUND accordingly.
+                */
+               if (worker_maybe_bind_and_lock(worker))
+                       worker->flags &= ~WORKER_UNBOUND;
+               else
+                       worker->flags |= WORKER_UNBOUND;
+
+               ret = true;
+       }
+
        pool->flags &= ~POOL_MANAGE_WORKERS;
 
        /*
@@ -1806,6 +1881,7 @@ static bool manage_workers(struct worker *worker)
        ret |= maybe_destroy_workers(pool);
        ret |= maybe_create_worker(pool);
 
+       pool->flags &= ~POOL_MANAGING_WORKERS;
        mutex_unlock(&pool->manager_mutex);
        return ret;
 }
@@ -3500,18 +3576,17 @@ static int __devinit workqueue_cpu_down_callback(struct notifier_block *nfb,
 #ifdef CONFIG_SMP
 
 struct work_for_cpu {
-       struct completion completion;
+       struct work_struct work;
        long (*fn)(void *);
        void *arg;
        long ret;
 };
 
-static int do_work_for_cpu(void *_wfc)
+static void work_for_cpu_fn(struct work_struct *work)
 {
-       struct work_for_cpu *wfc = _wfc;
+       struct work_for_cpu *wfc = container_of(work, struct work_for_cpu, work);
+
        wfc->ret = wfc->fn(wfc->arg);
-       complete(&wfc->completion);
-       return 0;
 }
 
 /**
@@ -3526,19 +3601,11 @@ static int do_work_for_cpu(void *_wfc)
  */
 long work_on_cpu(unsigned int cpu, long (*fn)(void *), void *arg)
 {
-       struct task_struct *sub_thread;
-       struct work_for_cpu wfc = {
-               .completion = COMPLETION_INITIALIZER_ONSTACK(wfc.completion),
-               .fn = fn,
-               .arg = arg,
-       };
+       struct work_for_cpu wfc = { .fn = fn, .arg = arg };
 
-       sub_thread = kthread_create(do_work_for_cpu, &wfc, "work_for_cpu");
-       if (IS_ERR(sub_thread))
-               return PTR_ERR(sub_thread);
-       kthread_bind(sub_thread, cpu);
-       wake_up_process(sub_thread);
-       wait_for_completion(&wfc.completion);
+       INIT_WORK_ONSTACK(&wfc.work, work_for_cpu_fn);
+       schedule_work_on(cpu, &wfc.work);
+       flush_work(&wfc.work);
        return wfc.ret;
 }
 EXPORT_SYMBOL_GPL(work_on_cpu);
index 286d558033e270524ff3fdeac9c96393b81170a6..8c0e62975c88d49a09c9c29ab9e7a2b1334a6587 100644 (file)
@@ -163,9 +163,11 @@ static int digsig_verify_rsa(struct key *key,
        memcpy(out1 + head, p, l);
 
        err = pkcs_1_v1_5_decode_emsa(out1, len, mblen, out2, &len);
+       if (err)
+               goto err;
 
-       if (!err && len == hlen)
-               err = memcmp(out2, h, hlen);
+       if (len != hlen || memcmp(out2, h, hlen))
+               err = -EINVAL;
 
 err:
        mpi_free(in);
index c785554f95237897edc7e86f7c3ea6f1811b9bbf..ebf3bac460b01c3638e87d23975426f448d58064 100644 (file)
@@ -62,7 +62,7 @@ void fprop_global_destroy(struct fprop_global *p)
  */
 bool fprop_new_period(struct fprop_global *p, int periods)
 {
-       u64 events;
+       s64 events;
        unsigned long flags;
 
        local_irq_save(flags);
index fa5ca304148e7b4756bf2e52cd6afde1dba2b5c3..384344575c375e1a1464734670218557c31e0e27 100644 (file)
@@ -1412,12 +1412,8 @@ generic_file_aio_read(struct kiocb *iocb, const struct iovec *iov,
                        retval = filemap_write_and_wait_range(mapping, pos,
                                        pos + iov_length(iov, nr_segs) - 1);
                        if (!retval) {
-                               struct blk_plug plug;
-
-                               blk_start_plug(&plug);
                                retval = mapping->a_ops->direct_IO(READ, iocb,
                                                        iov, pos, nr_segs);
-                               blk_finish_plug(&plug);
                        }
                        if (retval > 0) {
                                *ppos = pos + retval;
@@ -2527,14 +2523,12 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
 {
        struct file *file = iocb->ki_filp;
        struct inode *inode = file->f_mapping->host;
-       struct blk_plug plug;
        ssize_t ret;
 
        BUG_ON(iocb->ki_pos != pos);
 
        sb_start_write(inode->i_sb);
        mutex_lock(&inode->i_mutex);
-       blk_start_plug(&plug);
        ret = __generic_file_aio_write(iocb, iov, nr_segs, &iocb->ki_pos);
        mutex_unlock(&inode->i_mutex);
 
@@ -2545,7 +2539,6 @@ ssize_t generic_file_aio_write(struct kiocb *iocb, const struct iovec *iov,
                if (err < 0 && ret > 0)
                        ret = err;
        }
-       blk_finish_plug(&plug);
        sb_end_write(inode->i_sb);
        return ret;
 }
index 57c4b93090151f2acbc1271b7b214fe5bc96478c..141dbb695097c1f0674b8978456eb1d0c98e3e67 100644 (file)
@@ -1811,7 +1811,6 @@ static void __collapse_huge_page_copy(pte_t *pte, struct page *page,
                        src_page = pte_page(pteval);
                        copy_user_highpage(page, src_page, address, vma);
                        VM_BUG_ON(page_mapcount(src_page) != 1);
-                       VM_BUG_ON(page_count(src_page) != 2);
                        release_pte_page(src_page);
                        /*
                         * ptl mostly unnecessary, but preempt has to
index 4d9393c7edc9072ff929175eec6e611788da124b..82aa349d2f7a040b489bee441bf848b61119f788 100644 (file)
@@ -246,7 +246,7 @@ static int __init_memblock memblock_double_array(struct memblock_type *type,
                                min(new_area_start, memblock.current_limit),
                                new_alloc_size, PAGE_SIZE);
 
-               new_array = addr ? __va(addr) : 0;
+               new_array = addr ? __va(addr) : NULL;
        }
        if (!addr) {
                pr_err("memblock: Failed to double %s array from %ld to %ld entries !\n",
index 3ad25f9d1fc134dc09e9672fad40f508e12e9502..6a5b90d0cfd7cbd61f4bc679bb4313e7a374ac0d 100644 (file)
@@ -126,9 +126,6 @@ static void register_page_bootmem_info_section(unsigned long start_pfn)
        struct mem_section *ms;
        struct page *page, *memmap;
 
-       if (!pfn_valid(start_pfn))
-               return;
-
        section_nr = pfn_to_section_nr(start_pfn);
        ms = __nr_to_section(section_nr);
 
@@ -187,9 +184,16 @@ void register_page_bootmem_info_node(struct pglist_data *pgdat)
        end_pfn = pfn + pgdat->node_spanned_pages;
 
        /* register_section info */
-       for (; pfn < end_pfn; pfn += PAGES_PER_SECTION)
-               register_page_bootmem_info_section(pfn);
-
+       for (; pfn < end_pfn; pfn += PAGES_PER_SECTION) {
+               /*
+                * Some platforms can assign the same pfn to multiple nodes - on
+                * node0 as well as nodeN.  To avoid registering a pfn against
+                * multiple nodes we check that this pfn does not already
+                * reside in some other node.
+                */
+               if (pfn_valid(pfn) && (pfn_to_nid(pfn) == node))
+                       register_page_bootmem_info_section(pfn);
+       }
 }
 #endif /* !CONFIG_SPARSEMEM_VMEMMAP */
 
index bd92431d4c49a8e29f4b46d50d6d0e66c69098d5..4ada3be6e2521278de6da6e110995d63ccd7ed8f 100644 (file)
@@ -2562,7 +2562,7 @@ int mpol_to_str(char *buffer, int maxlen, struct mempolicy *pol, int no_context)
                break;
 
        default:
-               BUG();
+               return -EINVAL;
        }
 
        l = strlen(policy_modes[mode]);
index 9adee9fc0d8a6d799843ee0b010e8c4133f227f5..ae18a48e7e4e7944af308bbff226217ae7d1601e 100644 (file)
--- a/mm/mmap.c
+++ b/mm/mmap.c
@@ -1356,9 +1356,8 @@ out:
        } else if ((flags & MAP_POPULATE) && !(flags & MAP_NONBLOCK))
                make_pages_present(addr, addr + len);
 
-       if (file && uprobe_mmap(vma))
-               /* matching probes but cannot insert */
-               goto unmap_and_free_vma;
+       if (file)
+               uprobe_mmap(vma);
 
        return addr;
 
index c66fb875104ab99feccb0e116b48b9d54a6011e4..c13ea7538891d85988b029236f11e233632b58ec 100644 (file)
@@ -584,7 +584,7 @@ static inline void __free_one_page(struct page *page,
                combined_idx = buddy_idx & page_idx;
                higher_page = page + (combined_idx - page_idx);
                buddy_idx = __find_buddy_index(combined_idx, order + 1);
-               higher_buddy = page + (buddy_idx - combined_idx);
+               higher_buddy = higher_page + (buddy_idx - combined_idx);
                if (page_is_buddy(higher_page, higher_buddy, order + 1)) {
                        list_add_tail(&page->lru,
                                &zone->free_area[order].free_list[migratetype]);
index f8b0d539b4822af7812c8f9edcb51224450f3f64..c6854759bcf1e041d7a21781921ac45cfd2f5484 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -983,7 +983,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
                }
 
                /* The caller cannot use PFMEMALLOC objects, find another one */
-               for (i = 1; i < ac->avail; i++) {
+               for (i = 0; i < ac->avail; i++) {
                        /* If a !PFMEMALLOC object is found, swap them */
                        if (!is_obj_pfmemalloc(ac->entry[i])) {
                                objp = ac->entry[i];
@@ -1000,7 +1000,7 @@ static void *__ac_get_obj(struct kmem_cache *cachep, struct array_cache *ac,
                l3 = cachep->nodelists[numa_mem_id()];
                if (!list_empty(&l3->slabs_free) && force_refill) {
                        struct slab *slabp = virt_to_slab(objp);
-                       ClearPageSlabPfmemalloc(virt_to_page(slabp->s_mem));
+                       ClearPageSlabPfmemalloc(virt_to_head_page(slabp->s_mem));
                        clear_obj_pfmemalloc(&objp);
                        recheck_pfmemalloc_active(cachep, ac);
                        return objp;
@@ -1032,7 +1032,7 @@ static void *__ac_put_obj(struct kmem_cache *cachep, struct array_cache *ac,
 {
        if (unlikely(pfmemalloc_active)) {
                /* Some pfmemalloc slabs exist, check if this is one */
-               struct page *page = virt_to_page(objp);
+               struct page *page = virt_to_head_page(objp);
                if (PageSlabPfmemalloc(page))
                        set_obj_pfmemalloc(&objp);
        }
@@ -3260,6 +3260,7 @@ force_grow:
 
                /* cache_grow can reenable interrupts, then ac could change. */
                ac = cpu_cache_get(cachep);
+               node = numa_mem_id();
 
                /* no objects in sight? abort */
                if (!x && (ac->avail == 0 || force_refill))
index 8f78e25770317e63a37c741d66c2761f71afa2e9..2fdd96f9e9986b4c1244c13fde954d586afa7952 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -1524,12 +1524,13 @@ static inline void *acquire_slab(struct kmem_cache *s,
 }
 
 static int put_cpu_partial(struct kmem_cache *s, struct page *page, int drain);
+static inline bool pfmemalloc_match(struct page *page, gfp_t gfpflags);
 
 /*
  * Try to allocate a partial slab from a specific node.
  */
-static void *get_partial_node(struct kmem_cache *s,
-               struct kmem_cache_node *n, struct kmem_cache_cpu *c)
+static void *get_partial_node(struct kmem_cache *s, struct kmem_cache_node *n,
+                               struct kmem_cache_cpu *c, gfp_t flags)
 {
        struct page *page, *page2;
        void *object = NULL;
@@ -1545,9 +1546,13 @@ static void *get_partial_node(struct kmem_cache *s,
 
        spin_lock(&n->list_lock);
        list_for_each_entry_safe(page, page2, &n->partial, lru) {
-               void *t = acquire_slab(s, n, page, object == NULL);
+               void *t;
                int available;
 
+               if (!pfmemalloc_match(page, flags))
+                       continue;
+
+               t = acquire_slab(s, n, page, object == NULL);
                if (!t)
                        break;
 
@@ -1614,7 +1619,7 @@ static void *get_any_partial(struct kmem_cache *s, gfp_t flags,
 
                        if (n && cpuset_zone_allowed_hardwall(zone, flags) &&
                                        n->nr_partial > s->min_partial) {
-                               object = get_partial_node(s, n, c);
+                               object = get_partial_node(s, n, c, flags);
                                if (object) {
                                        /*
                                         * Return the object even if
@@ -1643,7 +1648,7 @@ static void *get_partial(struct kmem_cache *s, gfp_t flags, int node,
        void *object;
        int searchnode = (node == NUMA_NO_NODE) ? numa_node_id() : node;
 
-       object = get_partial_node(s, get_node(s, searchnode), c);
+       object = get_partial_node(s, get_node(s, searchnode), c, flags);
        if (object || node != NUMA_NO_NODE)
                return object;
 
index 8d01243d9560e0ea8d8a04cf51cd4087ed8b280d..99b434b674c02b4099bcfe58632ad56e183801fd 100644 (file)
@@ -3102,6 +3102,7 @@ int kswapd_run(int nid)
                /* failure at boot is fatal */
                BUG_ON(system_state == SYSTEM_BOOTING);
                printk("Failed to start kswapd on node %d\n",nid);
+               pgdat->kswapd = NULL;
                ret = -1;
        }
        return ret;
index e877af8bdd1e8551335ec810ea1ad2c32bedc64e..469daabd90c7bf28572c3f9066ee2146ed590fd1 100644 (file)
@@ -642,7 +642,8 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        struct batadv_neigh_node *router = NULL;
        struct batadv_orig_node *orig_node_tmp;
        struct hlist_node *node;
-       uint8_t bcast_own_sum_orig, bcast_own_sum_neigh;
+       int if_num;
+       uint8_t sum_orig, sum_neigh;
        uint8_t *neigh_addr;
 
        batadv_dbg(BATADV_DBG_BATMAN, bat_priv,
@@ -727,17 +728,17 @@ batadv_iv_ogm_orig_update(struct batadv_priv *bat_priv,
        if (router && (neigh_node->tq_avg == router->tq_avg)) {
                orig_node_tmp = router->orig_node;
                spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
-               bcast_own_sum_orig =
-                       orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+               if_num = router->if_incoming->if_num;
+               sum_orig = orig_node_tmp->bcast_own_sum[if_num];
                spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 
                orig_node_tmp = neigh_node->orig_node;
                spin_lock_bh(&orig_node_tmp->ogm_cnt_lock);
-               bcast_own_sum_neigh =
-                       orig_node_tmp->bcast_own_sum[if_incoming->if_num];
+               if_num = neigh_node->if_incoming->if_num;
+               sum_neigh = orig_node_tmp->bcast_own_sum[if_num];
                spin_unlock_bh(&orig_node_tmp->ogm_cnt_lock);
 
-               if (bcast_own_sum_orig >= bcast_own_sum_neigh)
+               if (sum_orig >= sum_neigh)
                        goto update_tt;
        }
 
index a081ce1c05140d43473dbc02518bfc51f913f6eb..cebaae7e148b7f8a88f8b265bb625256363cde5a 100644 (file)
@@ -20,8 +20,8 @@
 #ifndef _NET_BATMAN_ADV_BITARRAY_H_
 #define _NET_BATMAN_ADV_BITARRAY_H_
 
-/* returns true if the corresponding bit in the given seq_bits indicates true
- * and curr_seqno is within range of last_seqno
+/* Returns 1 if the corresponding bit in the given seq_bits indicates true
+ * and curr_seqno is within range of last_seqno. Otherwise returns 0.
  */
 static inline int batadv_test_bit(const unsigned long *seq_bits,
                                  uint32_t last_seqno, uint32_t curr_seqno)
@@ -32,7 +32,7 @@ static inline int batadv_test_bit(const unsigned long *seq_bits,
        if (diff < 0 || diff >= BATADV_TQ_LOCAL_WINDOW_SIZE)
                return 0;
        else
-               return  test_bit(diff, seq_bits);
+               return test_bit(diff, seq_bits) != 0;
 }
 
 /* turn corresponding bit on, so we can remember that we got the packet */
index 109ea2aae96cde266aef1123bb73a3fa7d219e79..21c53577c8d6a5e65599aa5c01d8d9d93c6fb838 100644 (file)
@@ -100,18 +100,21 @@ static int batadv_interface_set_mac_addr(struct net_device *dev, void *p)
 {
        struct batadv_priv *bat_priv = netdev_priv(dev);
        struct sockaddr *addr = p;
+       uint8_t old_addr[ETH_ALEN];
 
        if (!is_valid_ether_addr(addr->sa_data))
                return -EADDRNOTAVAIL;
 
+       memcpy(old_addr, dev->dev_addr, ETH_ALEN);
+       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
+
        /* only modify transtable if it has been initialized before */
        if (atomic_read(&bat_priv->mesh_state) == BATADV_MESH_ACTIVE) {
-               batadv_tt_local_remove(bat_priv, dev->dev_addr,
+               batadv_tt_local_remove(bat_priv, old_addr,
                                       "mac address changed", false);
                batadv_tt_local_add(dev, addr->sa_data, BATADV_NULL_IFINDEX);
        }
 
-       memcpy(dev->dev_addr, addr->sa_data, ETH_ALEN);
        dev->addr_assign_type &= ~NET_ADDR_RANDOM;
        return 0;
 }
index 5e5f5b410e0b24f751eb158ad235fe16bfa3ee6f..1eaacf10d19d9ea078f49f225423dff96ebee8a2 100644 (file)
@@ -58,7 +58,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
        switch (cmd) {
        case BNEPCONNADD:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&ca, argp, sizeof(ca)))
                        return -EFAULT;
@@ -84,7 +84,7 @@ static int bnep_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
 
        case BNEPCONNDEL:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&cd, argp, sizeof(cd)))
                        return -EFAULT;
index 311668d14571626dac778201a65ed21f05c72cbe..32dc83dcb6b2edd669d7a9ce2fc00480d249b4be 100644 (file)
@@ -72,7 +72,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
        switch (cmd) {
        case CMTPCONNADD:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&ca, argp, sizeof(ca)))
                        return -EFAULT;
@@ -97,7 +97,7 @@ static int cmtp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
 
        case CMTPCONNDEL:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&cd, argp, sizeof(cd)))
                        return -EFAULT;
index 5ad7da21747413f50ba0106041c6e73d6ce727d4..3c094e78dde98cafed3ac893abd3b2fa86b76a92 100644 (file)
@@ -29,6 +29,7 @@
 #include <net/bluetooth/bluetooth.h>
 #include <net/bluetooth/hci_core.h>
 #include <net/bluetooth/a2mp.h>
+#include <net/bluetooth/smp.h>
 
 static void hci_le_connect(struct hci_conn *conn)
 {
@@ -619,6 +620,9 @@ int hci_conn_security(struct hci_conn *conn, __u8 sec_level, __u8 auth_type)
 {
        BT_DBG("hcon %p", conn);
 
+       if (conn->type == LE_LINK)
+               return smp_conn_security(conn, sec_level);
+
        /* For sdp we don't need the link key. */
        if (sec_level == BT_SECURITY_SDP)
                return 1;
index d4de5db18d5a8e48d950a368e7ef93840d269a07..0b997c8f965531d22da050339d17011ab9dd5b3c 100644 (file)
@@ -734,6 +734,8 @@ static int hci_dev_do_close(struct hci_dev *hdev)
 
        cancel_work_sync(&hdev->le_scan);
 
+       cancel_delayed_work(&hdev->power_off);
+
        hci_req_cancel(hdev, ENODEV);
        hci_req_lock(hdev);
 
index 19fdac78e555b97c44dd6826bc60ef89a888395b..d5ace1eda3ed8c3fd06f422bb7cbf340d3187c6c 100644 (file)
@@ -490,7 +490,7 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
        switch (cmd) {
        case HCISETRAW:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (test_bit(HCI_QUIRK_RAW_DEVICE, &hdev->quirks))
                        return -EPERM;
@@ -510,12 +510,12 @@ static int hci_sock_bound_ioctl(struct sock *sk, unsigned int cmd,
 
        case HCIBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_sock_blacklist_add(hdev, (void __user *) arg);
 
        case HCIUNBLOCKADDR:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_sock_blacklist_del(hdev, (void __user *) arg);
 
        default:
@@ -546,22 +546,22 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
 
        case HCIDEVUP:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_dev_open(arg);
 
        case HCIDEVDOWN:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_dev_close(arg);
 
        case HCIDEVRESET:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_dev_reset(arg);
 
        case HCIDEVRESTAT:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_dev_reset_stat(arg);
 
        case HCISETSCAN:
@@ -573,7 +573,7 @@ static int hci_sock_ioctl(struct socket *sock, unsigned int cmd,
        case HCISETACLMTU:
        case HCISETSCOMTU:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
                return hci_dev_cmd(cmd, argp);
 
        case HCIINQUIRY:
index 18b3f6892a36847de621954cbae7358ae719c0be..b24fb3bd862555c81746fe664e7f90270cc6a2df 100644 (file)
@@ -56,7 +56,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
        switch (cmd) {
        case HIDPCONNADD:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&ca, argp, sizeof(ca)))
                        return -EFAULT;
@@ -91,7 +91,7 @@ static int hidp_sock_ioctl(struct socket *sock, unsigned int cmd, unsigned long
 
        case HIDPCONNDEL:
                if (!capable(CAP_NET_ADMIN))
-                       return -EACCES;
+                       return -EPERM;
 
                if (copy_from_user(&cd, argp, sizeof(cd)))
                        return -EFAULT;
index daa149b7003cdd659120e79225a50c6216a6dce4..38c00f142203505d3a3c809e8e6162f159ae0196 100644 (file)
@@ -1008,7 +1008,7 @@ static void l2cap_send_disconn_req(struct l2cap_conn *conn, struct l2cap_chan *c
        if (!conn)
                return;
 
-       if (chan->mode == L2CAP_MODE_ERTM) {
+       if (chan->mode == L2CAP_MODE_ERTM && chan->state == BT_CONNECTED) {
                __clear_retrans_timer(chan);
                __clear_monitor_timer(chan);
                __clear_ack_timer(chan);
@@ -1199,14 +1199,15 @@ clean:
 static void l2cap_conn_ready(struct l2cap_conn *conn)
 {
        struct l2cap_chan *chan;
+       struct hci_conn *hcon = conn->hcon;
 
        BT_DBG("conn %p", conn);
 
-       if (!conn->hcon->out && conn->hcon->type == LE_LINK)
+       if (!hcon->out && hcon->type == LE_LINK)
                l2cap_le_conn_ready(conn);
 
-       if (conn->hcon->out && conn->hcon->type == LE_LINK)
-               smp_conn_security(conn, conn->hcon->pending_sec_level);
+       if (hcon->out && hcon->type == LE_LINK)
+               smp_conn_security(hcon, hcon->pending_sec_level);
 
        mutex_lock(&conn->chan_lock);
 
@@ -1219,8 +1220,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn)
                        continue;
                }
 
-               if (conn->hcon->type == LE_LINK) {
-                       if (smp_conn_security(conn, chan->sec_level))
+               if (hcon->type == LE_LINK) {
+                       if (smp_conn_security(hcon, chan->sec_level))
                                l2cap_chan_ready(chan);
 
                } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) {
index 1497edd191a2e04ee3121624db92547059f24369..34bbe1c5e389500f080e15b30c194e95ea36f189 100644 (file)
@@ -616,7 +616,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, ch
                                break;
                        }
 
-                       if (smp_conn_security(conn, sec.level))
+                       if (smp_conn_security(conn->hcon, sec.level))
                                break;
                        sk->sk_state = BT_CONFIG;
                        chan->state = BT_CONFIG;
index ad6613d17ca6de815be200b9576d6ecf510fef0d..eba022de3c205bb55f2ed9639e4faf21d78ae9a8 100644 (file)
@@ -2875,6 +2875,22 @@ int mgmt_powered(struct hci_dev *hdev, u8 powered)
                if (scan)
                        hci_send_cmd(hdev, HCI_OP_WRITE_SCAN_ENABLE, 1, &scan);
 
+               if (test_bit(HCI_SSP_ENABLED, &hdev->dev_flags)) {
+                       u8 ssp = 1;
+
+                       hci_send_cmd(hdev, HCI_OP_WRITE_SSP_MODE, 1, &ssp);
+               }
+
+               if (test_bit(HCI_LE_ENABLED, &hdev->dev_flags)) {
+                       struct hci_cp_write_le_host_supported cp;
+
+                       cp.le = 1;
+                       cp.simul = !!(hdev->features[6] & LMP_SIMUL_LE_BR);
+
+                       hci_send_cmd(hdev, HCI_OP_WRITE_LE_HOST_SUPPORTED,
+                                    sizeof(cp), &cp);
+               }
+
                update_class(hdev);
                update_name(hdev, hdev->dev_name);
                update_eir(hdev);
index 901a616c8083e22f5163f8bbd1613b1529c63519..8c225ef349cd733614dfeaca0f2f1bceccdae064 100644 (file)
@@ -267,10 +267,10 @@ static void smp_failure(struct l2cap_conn *conn, u8 reason, u8 send)
        mgmt_auth_failed(conn->hcon->hdev, conn->dst, hcon->type,
                         hcon->dst_type, reason);
 
-       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags)) {
-               cancel_delayed_work_sync(&conn->security_timer);
+       cancel_delayed_work_sync(&conn->security_timer);
+
+       if (test_and_clear_bit(HCI_CONN_LE_SMP_PEND, &conn->hcon->flags))
                smp_chan_destroy(conn);
-       }
 }
 
 #define JUST_WORKS     0x00
@@ -760,9 +760,9 @@ static u8 smp_cmd_security_req(struct l2cap_conn *conn, struct sk_buff *skb)
        return 0;
 }
 
-int smp_conn_security(struct l2cap_conn *conn, __u8 sec_level)
+int smp_conn_security(struct hci_conn *hcon, __u8 sec_level)
 {
-       struct hci_conn *hcon = conn->hcon;
+       struct l2cap_conn *conn = hcon->l2cap_data;
        struct smp_chan *smp = conn->smp_chan;
        __u8 authreq;
 
index f88ee537fb2b811347c109cfa19dbdd34c2923c0..92de5e5f9db211fb004a5b8f095c2bd215276682 100644 (file)
@@ -80,7 +80,7 @@ ebt_log_packet(u_int8_t pf, unsigned int hooknum,
        unsigned int bitmask;
 
        spin_lock_bh(&ebt_log_lock);
-       printk("<%c>%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
+       printk(KERN_SOH "%c%s IN=%s OUT=%s MAC source = %pM MAC dest = %pM proto = 0x%04x",
               '0' + loginfo->u.log.level, prefix,
               in ? in->name : "", out ? out->name : "",
               eth_hdr(skb)->h_source, eth_hdr(skb)->h_dest,
index dd485f6128e81df5f8b1b454f57dac3b3871158a..ba217e90765e11024251feae5bbcb46450101ea7 100644 (file)
@@ -211,9 +211,10 @@ void caif_client_register_refcnt(struct cflayer *adapt_layer,
                                        void (*put)(struct cflayer *lyr))
 {
        struct cfsrvl *service;
-       service = container_of(adapt_layer->dn, struct cfsrvl, layer);
 
-       WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL);
+       if (WARN_ON(adapt_layer == NULL || adapt_layer->dn == NULL))
+               return;
+       service = container_of(adapt_layer->dn, struct cfsrvl, layer);
        service->hold = hold;
        service->put = put;
 }
index 24c5eea8c45bb1233edfad141baf6a6391e023c6..159aa8bef9e7fe2f89f9b508c39a209aa92d3c0d 100644 (file)
@@ -1073,16 +1073,13 @@ static int write_partial_msg_pages(struct ceph_connection *con)
                        BUG_ON(kaddr == NULL);
                        base = kaddr + con->out_msg_pos.page_pos + bio_offset;
                        crc = crc32c(crc, base, len);
+                       kunmap(page);
                        msg->footer.data_crc = cpu_to_le32(crc);
                        con->out_msg_pos.did_page_crc = true;
                }
                ret = ceph_tcp_sendpage(con->sock, page,
                                      con->out_msg_pos.page_pos + bio_offset,
                                      len, 1);
-
-               if (do_datacrc)
-                       kunmap(page);
-
                if (ret <= 0)
                        goto out;
 
index 83988362805ef1453efb37bfcb3692f59f4edd21..89e33a5d4d932c54af74a08cb080809affc7dd67 100644 (file)
@@ -2134,7 +2134,8 @@ static bool can_checksum_protocol(netdev_features_t features, __be16 protocol)
 static netdev_features_t harmonize_features(struct sk_buff *skb,
        __be16 protocol, netdev_features_t features)
 {
-       if (!can_checksum_protocol(features, protocol)) {
+       if (skb->ip_summed != CHECKSUM_NONE &&
+           !can_checksum_protocol(features, protocol)) {
                features &= ~NETIF_F_ALL_CSUM;
                features &= ~NETIF_F_SG;
        } else if (illegal_highdma(skb->dev, skb)) {
@@ -2647,15 +2648,16 @@ void __skb_get_rxhash(struct sk_buff *skb)
        if (!skb_flow_dissect(skb, &keys))
                return;
 
-       if (keys.ports) {
-               if ((__force u16)keys.port16[1] < (__force u16)keys.port16[0])
-                       swap(keys.port16[0], keys.port16[1]);
+       if (keys.ports)
                skb->l4_rxhash = 1;
-       }
 
        /* get a consistent hash (same value on both flow directions) */
-       if ((__force u32)keys.dst < (__force u32)keys.src)
+       if (((__force u32)keys.dst < (__force u32)keys.src) ||
+           (((__force u32)keys.dst == (__force u32)keys.src) &&
+            ((__force u16)keys.port16[1] < (__force u16)keys.port16[0]))) {
                swap(keys.dst, keys.src);
+               swap(keys.port16[0], keys.port16[1]);
+       }
 
        hash = jhash_3words((__force u32)keys.dst,
                            (__force u32)keys.src,
@@ -3321,7 +3323,7 @@ ncls:
 
        if (pt_prev) {
                if (unlikely(skb_orphan_frags(skb, GFP_ATOMIC)))
-                       ret = -ENOMEM;
+                       goto drop;
                else
                        ret = pt_prev->func(skb, skb->dev, pt_prev, orig_dev);
        } else {
index 346b1eb83a1f0336ed1e9dcf4f5905b733022dff..e4ba3e70c1747684ad480815f67b2410e87974a7 100644 (file)
@@ -168,24 +168,16 @@ static void poll_napi(struct net_device *dev)
        struct napi_struct *napi;
        int budget = 16;
 
-       WARN_ON_ONCE(!irqs_disabled());
-
        list_for_each_entry(napi, &dev->napi_list, dev_list) {
-               local_irq_enable();
                if (napi->poll_owner != smp_processor_id() &&
                    spin_trylock(&napi->poll_lock)) {
-                       rcu_read_lock_bh();
                        budget = poll_one_napi(rcu_dereference_bh(dev->npinfo),
                                               napi, budget);
-                       rcu_read_unlock_bh();
                        spin_unlock(&napi->poll_lock);
 
-                       if (!budget) {
-                               local_irq_disable();
+                       if (!budget)
                                break;
-                       }
                }
-               local_irq_disable();
        }
 }
 
index cce9e53528b169a67a8b5cd8bf0e568460587e24..148e73d2c4515d777d577733f32205c38d03932e 100644 (file)
@@ -2721,7 +2721,7 @@ static struct sk_buff *fill_packet_ipv4(struct net_device *odev,
        /* Eth + IPh + UDPh + mpls */
        datalen = pkt_dev->cur_pkt_size - 14 - 20 - 8 -
                  pkt_dev->pkt_overhead;
-       if (datalen < sizeof(struct pktgen_hdr))
+       if (datalen < 0 || datalen < sizeof(struct pktgen_hdr))
                datalen = sizeof(struct pktgen_hdr);
 
        udph->source = htons(pkt_dev->cur_udp_src);
index fe00d12081671a22c65d05d290069d7358dda1d6..e33ebae519c8c3283dadde917cdf46d413229a54 100644 (file)
@@ -3502,7 +3502,9 @@ bool skb_try_coalesce(struct sk_buff *to, struct sk_buff *from,
        if (!skb_cloned(from))
                skb_shinfo(from)->nr_frags = 0;
 
-       /* if the skb is cloned this does nothing since we set nr_frags to 0 */
+       /* if the skb is not cloned this does nothing
+        * since we set nr_frags to 0.
+        */
        for (i = 0; i < skb_shinfo(from)->nr_frags; i++)
                skb_frag_ref(from, i);
 
index 8f67ced8d6a808689255435dd412df132138af65..a6000fbad2949f58a079322f4e328e0c051df896 100644 (file)
@@ -691,7 +691,8 @@ set_rcvbuf:
 
        case SO_KEEPALIVE:
 #ifdef CONFIG_INET
-               if (sk->sk_protocol == IPPROTO_TCP)
+               if (sk->sk_protocol == IPPROTO_TCP &&
+                   sk->sk_type == SOCK_STREAM)
                        tcp_set_keepalive(sk, valbool);
 #endif
                sock_valbool_flag(sk, SOCK_KEEPOPEN, valbool);
@@ -1523,7 +1524,14 @@ EXPORT_SYMBOL(sock_rfree);
 
 void sock_edemux(struct sk_buff *skb)
 {
-       sock_put(skb->sk);
+       struct sock *sk = skb->sk;
+
+#ifdef CONFIG_INET
+       if (sk->sk_state == TCP_TIME_WAIT)
+               inet_twsk_put(inet_twsk(sk));
+       else
+#endif
+               sock_put(sk);
 }
 EXPORT_SYMBOL(sock_edemux);
 
index 77e87aff419ab105ef3ad3b5f852ef676b18a827..47800459e4cb341c395f54f2d161c300a112c1cf 100644 (file)
@@ -1225,7 +1225,7 @@ static int arp_netdev_event(struct notifier_block *this, unsigned long event,
        switch (event) {
        case NETDEV_CHANGEADDR:
                neigh_changeaddr(&arp_tbl, dev);
-               rt_cache_flush(dev_net(dev), 0);
+               rt_cache_flush(dev_net(dev));
                break;
        default:
                break;
index 44bf82e3aef7d6d4b5afc39a357b7da6d85a44e7..e12fad773852b5271afafa414ffc1f2706ff4428 100644 (file)
@@ -725,7 +725,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
                break;
 
        case SIOCSIFFLAGS:
-               ret = -EACCES;
+               ret = -EPERM;
                if (!capable(CAP_NET_ADMIN))
                        goto out;
                break;
@@ -733,7 +733,7 @@ int devinet_ioctl(struct net *net, unsigned int cmd, void __user *arg)
        case SIOCSIFBRDADDR:    /* Set the broadcast address */
        case SIOCSIFDSTADDR:    /* Set the destination address */
        case SIOCSIFNETMASK:    /* Set the netmask for the interface */
-               ret = -EACCES;
+               ret = -EPERM;
                if (!capable(CAP_NET_ADMIN))
                        goto out;
                ret = -EINVAL;
@@ -1503,7 +1503,7 @@ static int devinet_conf_proc(ctl_table *ctl, int write,
                if (i == IPV4_DEVCONF_ACCEPT_LOCAL - 1 ||
                    i == IPV4_DEVCONF_ROUTE_LOCALNET - 1)
                        if ((new_value == 0) && (old_value != 0))
-                               rt_cache_flush(net, 0);
+                               rt_cache_flush(net);
        }
 
        return ret;
@@ -1537,7 +1537,7 @@ static int devinet_sysctl_forward(ctl_table *ctl, int write,
                                dev_disable_lro(idev->dev);
                        }
                        rtnl_unlock();
-                       rt_cache_flush(net, 0);
+                       rt_cache_flush(net);
                }
        }
 
@@ -1554,7 +1554,7 @@ static int ipv4_doint_and_flush(ctl_table *ctl, int write,
        struct net *net = ctl->extra2;
 
        if (write && *valp != val)
-               rt_cache_flush(net, 0);
+               rt_cache_flush(net);
 
        return ret;
 }
index c43ae3fba7921e590859cea407ba9b9e030b16be..8e2b475da9faca9f7e27482f7e416908e7cf66fa 100644 (file)
@@ -148,7 +148,7 @@ static void fib_flush(struct net *net)
        }
 
        if (flushed)
-               rt_cache_flush(net, -1);
+               rt_cache_flush(net);
 }
 
 /*
@@ -999,11 +999,11 @@ static void nl_fib_lookup_exit(struct net *net)
        net->ipv4.fibnl = NULL;
 }
 
-static void fib_disable_ip(struct net_device *dev, int force, int delay)
+static void fib_disable_ip(struct net_device *dev, int force)
 {
        if (fib_sync_down_dev(dev, force))
                fib_flush(dev_net(dev));
-       rt_cache_flush(dev_net(dev), delay);
+       rt_cache_flush(dev_net(dev));
        arp_ifdown(dev);
 }
 
@@ -1020,7 +1020,7 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
                fib_sync_up(dev);
 #endif
                atomic_inc(&net->ipv4.dev_addr_genid);
-               rt_cache_flush(dev_net(dev), -1);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_DOWN:
                fib_del_ifaddr(ifa, NULL);
@@ -1029,9 +1029,9 @@ static int fib_inetaddr_event(struct notifier_block *this, unsigned long event,
                        /* Last address was deleted from this interface.
                         * Disable IP.
                         */
-                       fib_disable_ip(dev, 1, 0);
+                       fib_disable_ip(dev, 1);
                } else {
-                       rt_cache_flush(dev_net(dev), -1);
+                       rt_cache_flush(dev_net(dev));
                }
                break;
        }
@@ -1045,7 +1045,7 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
        struct net *net = dev_net(dev);
 
        if (event == NETDEV_UNREGISTER) {
-               fib_disable_ip(dev, 2, -1);
+               fib_disable_ip(dev, 2);
                rt_flush_dev(dev);
                return NOTIFY_DONE;
        }
@@ -1062,14 +1062,14 @@ static int fib_netdev_event(struct notifier_block *this, unsigned long event, vo
                fib_sync_up(dev);
 #endif
                atomic_inc(&net->ipv4.dev_addr_genid);
-               rt_cache_flush(dev_net(dev), -1);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_DOWN:
-               fib_disable_ip(dev, 0, 0);
+               fib_disable_ip(dev, 0);
                break;
        case NETDEV_CHANGEMTU:
        case NETDEV_CHANGE:
-               rt_cache_flush(dev_net(dev), 0);
+               rt_cache_flush(dev_net(dev));
                break;
        case NETDEV_UNREGISTER_BATCH:
                break;
index a83d74e498d23af8c104bc3d68eca5ca4a8ac228..274309d3aded0ffbf351dbf5f4ad128d87ff5a0b 100644 (file)
@@ -259,7 +259,7 @@ static size_t fib4_rule_nlmsg_payload(struct fib_rule *rule)
 
 static void fib4_rule_flush_cache(struct fib_rules_ops *ops)
 {
-       rt_cache_flush(ops->fro_net, -1);
+       rt_cache_flush(ops->fro_net);
 }
 
 static const struct fib_rules_ops __net_initdata fib4_rules_ops_template = {
index 57bd978483e1fe47a96c964f356432e51e62d6b7..d1b93595b4a7dce1e7701bb713bd5f0bc5adf1f6 100644 (file)
@@ -1286,7 +1286,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
 
                        fib_release_info(fi_drop);
                        if (state & FA_S_ACCESSED)
-                               rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+                               rt_cache_flush(cfg->fc_nlinfo.nl_net);
                        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen,
                                tb->tb_id, &cfg->fc_nlinfo, NLM_F_REPLACE);
 
@@ -1333,7 +1333,7 @@ int fib_table_insert(struct fib_table *tb, struct fib_config *cfg)
        list_add_tail_rcu(&new_fa->fa_list,
                          (fa ? &fa->fa_list : fa_head));
 
-       rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+       rt_cache_flush(cfg->fc_nlinfo.nl_net);
        rtmsg_fib(RTM_NEWROUTE, htonl(key), new_fa, plen, tb->tb_id,
                  &cfg->fc_nlinfo, 0);
 succeeded:
@@ -1708,7 +1708,7 @@ int fib_table_delete(struct fib_table *tb, struct fib_config *cfg)
                trie_leaf_remove(t, l);
 
        if (fa->fa_state & FA_S_ACCESSED)
-               rt_cache_flush(cfg->fc_nlinfo.nl_net, -1);
+               rt_cache_flush(cfg->fc_nlinfo.nl_net);
 
        fib_release_info(fa->fa_info);
        alias_free_mem_rcu(fa);
index e1e0a4e8fd3469f7534cdc65b7ba3312ad66fa39..c7527f6b9ad9b54f36185975aed21171757c4600 100644 (file)
@@ -510,7 +510,10 @@ relookup:
                                        secure_ipv6_id(daddr->addr.a6));
                p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
                p->rate_tokens = 0;
-               p->rate_last = 0;
+               /* 60*HZ is arbitrary, but chosen enough high so that the first
+                * calculation of tokens is at its maximum.
+                */
+               p->rate_last = jiffies - 60*HZ;
                INIT_LIST_HEAD(&p->gc_list);
 
                /* Link the node. */
index 8eec8f4a05360d24897719495100ea100f0c69b2..ebdf06f938bf040eebc91763c3e952c63d00f92b 100644 (file)
@@ -124,6 +124,8 @@ static DEFINE_SPINLOCK(mfc_unres_lock);
 static struct kmem_cache *mrt_cachep __read_mostly;
 
 static struct mr_table *ipmr_new_table(struct net *net, u32 id);
+static void ipmr_free_table(struct mr_table *mrt);
+
 static int ip_mr_forward(struct net *net, struct mr_table *mrt,
                         struct sk_buff *skb, struct mfc_cache *cache,
                         int local);
@@ -131,6 +133,7 @@ static int ipmr_cache_report(struct mr_table *mrt,
                             struct sk_buff *pkt, vifi_t vifi, int assert);
 static int __ipmr_fill_mroute(struct mr_table *mrt, struct sk_buff *skb,
                              struct mfc_cache *c, struct rtmsg *rtm);
+static void mroute_clean_tables(struct mr_table *mrt);
 static void ipmr_expire_process(unsigned long arg);
 
 #ifdef CONFIG_IP_MROUTE_MULTIPLE_TABLES
@@ -271,7 +274,7 @@ static void __net_exit ipmr_rules_exit(struct net *net)
 
        list_for_each_entry_safe(mrt, next, &net->ipv4.mr_tables, list) {
                list_del(&mrt->list);
-               kfree(mrt);
+               ipmr_free_table(mrt);
        }
        fib_rules_unregister(net->ipv4.mr_rules_ops);
 }
@@ -299,7 +302,7 @@ static int __net_init ipmr_rules_init(struct net *net)
 
 static void __net_exit ipmr_rules_exit(struct net *net)
 {
-       kfree(net->ipv4.mrt);
+       ipmr_free_table(net->ipv4.mrt);
 }
 #endif
 
@@ -336,6 +339,13 @@ static struct mr_table *ipmr_new_table(struct net *net, u32 id)
        return mrt;
 }
 
+static void ipmr_free_table(struct mr_table *mrt)
+{
+       del_timer_sync(&mrt->ipmr_expire_timer);
+       mroute_clean_tables(mrt);
+       kfree(mrt);
+}
+
 /* Service routines creating virtual interfaces: DVMRP tunnels and PIMREG */
 
 static void ipmr_del_tunnel(struct net_device *dev, struct vifctl *v)
index 4ad9cf1739922cfb4b13d3135d01381dd70bf0be..9c87cde28ff831472cc7072a05526d753727d1fa 100644 (file)
@@ -502,7 +502,10 @@ static unsigned int ip_nat_sdp_media(struct sk_buff *skb, unsigned int dataoff,
                ret = nf_ct_expect_related(rtcp_exp);
                if (ret == 0)
                        break;
-               else if (ret != -EBUSY) {
+               else if (ret == -EBUSY) {
+                       nf_ct_unexpect_related(rtp_exp);
+                       continue;
+               } else if (ret < 0) {
                        nf_ct_unexpect_related(rtp_exp);
                        port = 0;
                        break;
index ff0f071969ea77dbdb6797584765e32bc958203f..d23c6571ba1c34525114af16f0818cfe6bbf1f14 100644 (file)
@@ -131,18 +131,20 @@ found:
  *     0 - deliver
  *     1 - block
  */
-static __inline__ int icmp_filter(struct sock *sk, struct sk_buff *skb)
+static int icmp_filter(const struct sock *sk, const struct sk_buff *skb)
 {
-       int type;
+       struct icmphdr _hdr;
+       const struct icmphdr *hdr;
 
-       if (!pskb_may_pull(skb, sizeof(struct icmphdr)))
+       hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+                                sizeof(_hdr), &_hdr);
+       if (!hdr)
                return 1;
 
-       type = icmp_hdr(skb)->type;
-       if (type < 32) {
+       if (hdr->type < 32) {
                __u32 data = raw_sk(sk)->filter.data;
 
-               return ((1 << type) & data) != 0;
+               return ((1U << hdr->type) & data) != 0;
        }
 
        /* Do not block unknown ICMP types */
index fd9ecb52c66bf8815c09e678c452017e9a7e2122..fd9af60397b590dd817e02a52a33fdf99bb24c8e 100644 (file)
@@ -202,11 +202,6 @@ EXPORT_SYMBOL(ip_tos2prio);
 static DEFINE_PER_CPU(struct rt_cache_stat, rt_cache_stat);
 #define RT_CACHE_STAT_INC(field) __this_cpu_inc(rt_cache_stat.field)
 
-static inline int rt_genid(struct net *net)
-{
-       return atomic_read(&net->ipv4.rt_genid);
-}
-
 #ifdef CONFIG_PROC_FS
 static void *rt_cache_seq_start(struct seq_file *seq, loff_t *pos)
 {
@@ -447,27 +442,9 @@ static inline bool rt_is_expired(const struct rtable *rth)
        return rth->rt_genid != rt_genid(dev_net(rth->dst.dev));
 }
 
-/*
- * Perturbation of rt_genid by a small quantity [1..256]
- * Using 8 bits of shuffling ensure we can call rt_cache_invalidate()
- * many times (2^24) without giving recent rt_genid.
- * Jenkins hash is strong enough that litle changes of rt_genid are OK.
- */
-static void rt_cache_invalidate(struct net *net)
+void rt_cache_flush(struct net *net)
 {
-       unsigned char shuffle;
-
-       get_random_bytes(&shuffle, sizeof(shuffle));
-       atomic_add(shuffle + 1U, &net->ipv4.rt_genid);
-}
-
-/*
- * delay < 0  : invalidate cache (fast : entries will be deleted later)
- * delay >= 0 : invalidate & flush cache (can be long)
- */
-void rt_cache_flush(struct net *net, int delay)
-{
-       rt_cache_invalidate(net);
+       rt_genid_bump(net);
 }
 
 static struct neighbour *ipv4_neigh_lookup(const struct dst_entry *dst,
@@ -934,12 +911,14 @@ static u32 __ip_rt_update_pmtu(struct rtable *rt, struct flowi4 *fl4, u32 mtu)
        if (mtu < ip_rt_min_pmtu)
                mtu = ip_rt_min_pmtu;
 
+       rcu_read_lock();
        if (fib_lookup(dev_net(rt->dst.dev), fl4, &res) == 0) {
                struct fib_nh *nh = &FIB_RES_NH(res);
 
                update_or_create_fnhe(nh, fl4->daddr, 0, mtu,
                                      jiffies + ip_rt_mtu_expires);
        }
+       rcu_read_unlock();
        return mtu;
 }
 
@@ -956,7 +935,7 @@ static void ip_rt_update_pmtu(struct dst_entry *dst, struct sock *sk,
                dst->obsolete = DST_OBSOLETE_KILL;
        } else {
                rt->rt_pmtu = mtu;
-               dst_set_expires(&rt->dst, ip_rt_mtu_expires);
+               rt->dst.expires = max(1UL, jiffies + ip_rt_mtu_expires);
        }
 }
 
@@ -1263,7 +1242,7 @@ static void ipv4_dst_destroy(struct dst_entry *dst)
 {
        struct rtable *rt = (struct rtable *) dst;
 
-       if (dst->flags & DST_NOCACHE) {
+       if (!list_empty(&rt->rt_uncached)) {
                spin_lock_bh(&rt_uncached_lock);
                list_del(&rt->rt_uncached);
                spin_unlock_bh(&rt_uncached_lock);
@@ -2343,7 +2322,7 @@ int ip_rt_dump(struct sk_buff *skb,  struct netlink_callback *cb)
 
 void ip_rt_multicast_event(struct in_device *in_dev)
 {
-       rt_cache_flush(dev_net(in_dev->dev), 0);
+       rt_cache_flush(dev_net(in_dev->dev));
 }
 
 #ifdef CONFIG_SYSCTL
@@ -2352,16 +2331,7 @@ static int ipv4_sysctl_rtcache_flush(ctl_table *__ctl, int write,
                                        size_t *lenp, loff_t *ppos)
 {
        if (write) {
-               int flush_delay;
-               ctl_table ctl;
-               struct net *net;
-
-               memcpy(&ctl, __ctl, sizeof(ctl));
-               ctl.data = &flush_delay;
-               proc_dointvec(&ctl, write, buffer, lenp, ppos);
-
-               net = (struct net *)__ctl->extra1;
-               rt_cache_flush(net, flush_delay);
+               rt_cache_flush((struct net *)__ctl->extra1);
                return 0;
        }
 
@@ -2531,8 +2501,7 @@ static __net_initdata struct pernet_operations sysctl_route_ops = {
 
 static __net_init int rt_genid_init(struct net *net)
 {
-       get_random_bytes(&net->ipv4.rt_genid,
-                        sizeof(net->ipv4.rt_genid));
+       atomic_set(&net->rt_genid, 0);
        get_random_bytes(&net->ipv4.dev_addr_genid,
                         sizeof(net->ipv4.dev_addr_genid));
        return 0;
index 2109ff4a1dafd489fbe0e2240075432df4517374..5f64193418216393448ec9d8e839f83e85636716 100644 (file)
@@ -1762,8 +1762,14 @@ int tcp_recvmsg(struct kiocb *iocb, struct sock *sk, struct msghdr *msg,
                }
 
 #ifdef CONFIG_NET_DMA
-               if (tp->ucopy.dma_chan)
-                       dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+               if (tp->ucopy.dma_chan) {
+                       if (tp->rcv_wnd == 0 &&
+                           !skb_queue_empty(&sk->sk_async_wait_queue)) {
+                               tcp_service_net_dma(sk, true);
+                               tcp_cleanup_rbuf(sk, copied);
+                       } else
+                               dma_async_memcpy_issue_pending(tp->ucopy.dma_chan);
+               }
 #endif
                if (copied >= target) {
                        /* Do not sleep, just process backlog. */
@@ -2325,10 +2331,17 @@ static int tcp_repair_options_est(struct tcp_sock *tp,
                        tp->rx_opt.mss_clamp = opt.opt_val;
                        break;
                case TCPOPT_WINDOW:
-                       if (opt.opt_val > 14)
-                               return -EFBIG;
+                       {
+                               u16 snd_wscale = opt.opt_val & 0xFFFF;
+                               u16 rcv_wscale = opt.opt_val >> 16;
+
+                               if (snd_wscale > 14 || rcv_wscale > 14)
+                                       return -EFBIG;
 
-                       tp->rx_opt.snd_wscale = opt.opt_val;
+                               tp->rx_opt.snd_wscale = snd_wscale;
+                               tp->rx_opt.rcv_wscale = rcv_wscale;
+                               tp->rx_opt.wscale_ok = 1;
+                       }
                        break;
                case TCPOPT_SACK_PERM:
                        if (opt.opt_val != 0)
index 85308b90df80a844119a8cc773783f78aab5de04..d377f4854cb853c454541062fb6f8438608d470c 100644 (file)
@@ -2926,13 +2926,14 @@ static void tcp_enter_recovery(struct sock *sk, bool ece_ack)
  * tcp_xmit_retransmit_queue().
  */
 static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
-                                 int newly_acked_sacked, bool is_dupack,
+                                 int prior_sacked, bool is_dupack,
                                  int flag)
 {
        struct inet_connection_sock *icsk = inet_csk(sk);
        struct tcp_sock *tp = tcp_sk(sk);
        int do_lost = is_dupack || ((flag & FLAG_DATA_SACKED) &&
                                    (tcp_fackets_out(tp) > tp->reordering));
+       int newly_acked_sacked = 0;
        int fast_rexmit = 0;
 
        if (WARN_ON(!tp->packets_out && tp->sacked_out))
@@ -2992,6 +2993,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                                tcp_add_reno_sack(sk);
                } else
                        do_lost = tcp_try_undo_partial(sk, pkts_acked);
+               newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
                break;
        case TCP_CA_Loss:
                if (flag & FLAG_DATA_ACKED)
@@ -3013,6 +3015,7 @@ static void tcp_fastretrans_alert(struct sock *sk, int pkts_acked,
                        if (is_dupack)
                                tcp_add_reno_sack(sk);
                }
+               newly_acked_sacked = pkts_acked + tp->sacked_out - prior_sacked;
 
                if (icsk->icsk_ca_state <= TCP_CA_Disorder)
                        tcp_try_undo_dsack(sk);
@@ -3590,7 +3593,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        int prior_packets;
        int prior_sacked = tp->sacked_out;
        int pkts_acked = 0;
-       int newly_acked_sacked = 0;
        bool frto_cwnd = false;
 
        /* If the ack is older than previous acks
@@ -3666,8 +3668,6 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
        flag |= tcp_clean_rtx_queue(sk, prior_fackets, prior_snd_una);
 
        pkts_acked = prior_packets - tp->packets_out;
-       newly_acked_sacked = (prior_packets - prior_sacked) -
-                            (tp->packets_out - tp->sacked_out);
 
        if (tp->frto_counter)
                frto_cwnd = tcp_process_frto(sk, flag);
@@ -3681,7 +3681,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
                    tcp_may_raise_cwnd(sk, flag))
                        tcp_cong_avoid(sk, ack, prior_in_flight);
                is_dupack = !(flag & (FLAG_SND_UNA_ADVANCED | FLAG_NOT_DUP));
-               tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
                                      is_dupack, flag);
        } else {
                if ((flag & FLAG_DATA_ACKED) && !frto_cwnd)
@@ -3698,7 +3698,7 @@ static int tcp_ack(struct sock *sk, const struct sk_buff *skb, int flag)
 no_queue:
        /* If data was DSACKed, see if we can undo a cwnd reduction. */
        if (flag & FLAG_DSACKING_ACK)
-               tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
                                      is_dupack, flag);
        /* If this ack opens up a zero window, clear backoff.  It was
         * being used to time the probes, and is probably far higher than
@@ -3718,8 +3718,7 @@ old_ack:
         */
        if (TCP_SKB_CB(skb)->sacked) {
                flag |= tcp_sacktag_write_queue(sk, skb, prior_snd_una);
-               newly_acked_sacked = tp->sacked_out - prior_sacked;
-               tcp_fastretrans_alert(sk, pkts_acked, newly_acked_sacked,
+               tcp_fastretrans_alert(sk, pkts_acked, prior_sacked,
                                      is_dupack, flag);
        }
 
@@ -4662,7 +4661,7 @@ queue_and_out:
 
                if (eaten > 0)
                        kfree_skb_partial(skb, fragstolen);
-               else if (!sock_flag(sk, SOCK_DEAD))
+               if (!sock_flag(sk, SOCK_DEAD))
                        sk->sk_data_ready(sk, 0);
                return;
        }
@@ -5557,8 +5556,7 @@ no_ack:
 #endif
                        if (eaten)
                                kfree_skb_partial(skb, fragstolen);
-                       else
-                               sk->sk_data_ready(sk, 0);
+                       sk->sk_data_ready(sk, 0);
                        return 0;
                }
        }
index 6f6d1aca3c3de0e21036c075c0a13c429ef4f8ae..2814f66dac64cf5775806138c91903c7a02eeae3 100644 (file)
@@ -1226,6 +1226,11 @@ try_again:
 
        if (unlikely(err)) {
                trace_kfree_skb(skb, udp_recvmsg);
+               if (!peeked) {
+                       atomic_inc(&sk->sk_drops);
+                       UDP_INC_STATS_USER(sock_net(sk),
+                                          UDP_MIB_INERRORS, is_udplite);
+               }
                goto out_free;
        }
 
index 6dc7fd353ef53f9c08c9202340fc953bf3b294c5..282f3723ee194704ab7fa0757e2c032254903300 100644 (file)
@@ -167,8 +167,6 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
        struct esp_data *esp = x->data;
 
        /* skb is pure payload to encrypt */
-       err = -ENOMEM;
-
        aead = esp->aead;
        alen = crypto_aead_authsize(aead);
 
@@ -203,8 +201,10 @@ static int esp6_output(struct xfrm_state *x, struct sk_buff *skb)
        }
 
        tmp = esp_alloc_tmp(aead, nfrags + sglists, seqhilen);
-       if (!tmp)
+       if (!tmp) {
+               err = -ENOMEM;
                goto error;
+       }
 
        seqhi = esp_tmp_seqhi(tmp);
        iv = esp_tmp_iv(aead, tmp, seqhilen);
index 0251a6005be8ff8d35cffe7fb0e2611b43296158..c4f934176cabd92ebfb4bba774335427b9f8932a 100644 (file)
@@ -175,33 +175,12 @@ void __inet6_csk_dst_store(struct sock *sk, struct dst_entry *dst,
                           const struct in6_addr *saddr)
 {
        __ip6_dst_store(sk, dst, daddr, saddr);
-
-#ifdef CONFIG_XFRM
-       {
-               struct rt6_info *rt = (struct rt6_info  *)dst;
-               rt->rt6i_flow_cache_genid = atomic_read(&flow_cache_genid);
-       }
-#endif
 }
 
 static inline
 struct dst_entry *__inet6_csk_dst_check(struct sock *sk, u32 cookie)
 {
-       struct dst_entry *dst;
-
-       dst = __sk_dst_check(sk, cookie);
-
-#ifdef CONFIG_XFRM
-       if (dst) {
-               struct rt6_info *rt = (struct rt6_info *)dst;
-               if (rt->rt6i_flow_cache_genid != atomic_read(&flow_cache_genid)) {
-                       __sk_dst_reset(sk);
-                       dst = NULL;
-               }
-       }
-#endif
-
-       return dst;
+       return __sk_dst_check(sk, cookie);
 }
 
 static struct dst_entry *inet6_csk_route_socket(struct sock *sk,
index 13690d650c3e227de6579ed6ee489fbff1cbddef..286acfc21250cd760565b182cbc2d3d4490463dd 100644 (file)
@@ -819,6 +819,10 @@ int fib6_add(struct fib6_node *root, struct rt6_info *rt, struct nl_info *info)
                                        offsetof(struct rt6_info, rt6i_src),
                                        allow_create, replace_required);
 
+                       if (IS_ERR(sn)) {
+                               err = PTR_ERR(sn);
+                               sn = NULL;
+                       }
                        if (!sn) {
                                /* If it is failed, discard just allocated
                                   root, and then (in st_failure) stale node
index 5b087c31d87b54f5a2574903775b81692bcd2616..0f9bdc5ee9f38c70f1c4c265e8ebe43467d6b59a 100644 (file)
@@ -86,28 +86,30 @@ static int mip6_mh_len(int type)
 
 static int mip6_mh_filter(struct sock *sk, struct sk_buff *skb)
 {
-       struct ip6_mh *mh;
+       struct ip6_mh _hdr;
+       const struct ip6_mh *mh;
 
-       if (!pskb_may_pull(skb, (skb_transport_offset(skb)) + 8) ||
-           !pskb_may_pull(skb, (skb_transport_offset(skb) +
-                                ((skb_transport_header(skb)[1] + 1) << 3))))
+       mh = skb_header_pointer(skb, skb_transport_offset(skb),
+                               sizeof(_hdr), &_hdr);
+       if (!mh)
                return -1;
 
-       mh = (struct ip6_mh *)skb_transport_header(skb);
+       if (((mh->ip6mh_hdrlen + 1) << 3) > skb->len)
+               return -1;
 
        if (mh->ip6mh_hdrlen < mip6_mh_len(mh->ip6mh_type)) {
                LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH message too short: %d vs >=%d\n",
                               mh->ip6mh_hdrlen, mip6_mh_len(mh->ip6mh_type));
-               mip6_param_prob(skb, 0, ((&mh->ip6mh_hdrlen) -
-                                        skb_network_header(skb)));
+               mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_hdrlen) +
+                               skb_network_header_len(skb));
                return -1;
        }
 
        if (mh->ip6mh_proto != IPPROTO_NONE) {
                LIMIT_NETDEBUG(KERN_DEBUG "mip6: MH invalid payload proto = %d\n",
                               mh->ip6mh_proto);
-               mip6_param_prob(skb, 0, ((&mh->ip6mh_proto) -
-                                        skb_network_header(skb)));
+               mip6_param_prob(skb, 0, offsetof(struct ip6_mh, ip6mh_proto) +
+                               skb_network_header_len(skb));
                return -1;
        }
 
index ef0579d5bca6b3794007145279f8ead1626aafe3..4a5f78b50495060470777aa41edd540bb699662f 100644 (file)
@@ -107,21 +107,20 @@ found:
  *     0 - deliver
  *     1 - block
  */
-static __inline__ int icmpv6_filter(struct sock *sk, struct sk_buff *skb)
+static int icmpv6_filter(const struct sock *sk, const struct sk_buff *skb)
 {
-       struct icmp6hdr *icmph;
-       struct raw6_sock *rp = raw6_sk(sk);
-
-       if (pskb_may_pull(skb, sizeof(struct icmp6hdr))) {
-               __u32 *data = &rp->filter.data[0];
-               int bit_nr;
+       struct icmp6hdr *_hdr;
+       const struct icmp6hdr *hdr;
 
-               icmph = (struct icmp6hdr *) skb->data;
-               bit_nr = icmph->icmp6_type;
+       hdr = skb_header_pointer(skb, skb_transport_offset(skb),
+                                sizeof(_hdr), &_hdr);
+       if (hdr) {
+               const __u32 *data = &raw6_sk(sk)->filter.data[0];
+               unsigned int type = hdr->icmp6_type;
 
-               return (data[bit_nr >> 5] & (1 << (bit_nr & 31))) != 0;
+               return (data[type >> 5] & (1U << (type & 31))) != 0;
        }
-       return 0;
+       return 1;
 }
 
 #if defined(CONFIG_IPV6_MIP6) || defined(CONFIG_IPV6_MIP6_MODULE)
index 8e80fd279100d7d18d111eff1be73f10fdd6eeaf..854e4018d205c826032633ce2641cbc1af2c057a 100644 (file)
@@ -226,7 +226,7 @@ static struct rt6_info ip6_null_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
                .__use          = 1,
-               .obsolete       = -1,
+               .obsolete       = DST_OBSOLETE_FORCE_CHK,
                .error          = -ENETUNREACH,
                .input          = ip6_pkt_discard,
                .output         = ip6_pkt_discard_out,
@@ -246,7 +246,7 @@ static struct rt6_info ip6_prohibit_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
                .__use          = 1,
-               .obsolete       = -1,
+               .obsolete       = DST_OBSOLETE_FORCE_CHK,
                .error          = -EACCES,
                .input          = ip6_pkt_prohibit,
                .output         = ip6_pkt_prohibit_out,
@@ -261,7 +261,7 @@ static struct rt6_info ip6_blk_hole_entry_template = {
        .dst = {
                .__refcnt       = ATOMIC_INIT(1),
                .__use          = 1,
-               .obsolete       = -1,
+               .obsolete       = DST_OBSOLETE_FORCE_CHK,
                .error          = -EINVAL,
                .input          = dst_discard,
                .output         = dst_discard,
@@ -281,13 +281,14 @@ static inline struct rt6_info *ip6_dst_alloc(struct net *net,
                                             struct fib6_table *table)
 {
        struct rt6_info *rt = dst_alloc(&net->ipv6.ip6_dst_ops, dev,
-                                       0, DST_OBSOLETE_NONE, flags);
+                                       0, DST_OBSOLETE_FORCE_CHK, flags);
 
        if (rt) {
                struct dst_entry *dst = &rt->dst;
 
                memset(dst + 1, 0, sizeof(*rt) - sizeof(*dst));
                rt6_init_peer(rt, table ? &table->tb6_peers : net->ipv6.peers);
+               rt->rt6i_genid = rt_genid(net);
        }
        return rt;
 }
@@ -1031,6 +1032,13 @@ static struct dst_entry *ip6_dst_check(struct dst_entry *dst, u32 cookie)
 
        rt = (struct rt6_info *) dst;
 
+       /* All IPV6 dsts are created with ->obsolete set to the value
+        * DST_OBSOLETE_FORCE_CHK which forces validation calls down
+        * into this function always.
+        */
+       if (rt->rt6i_genid != rt_genid(dev_net(rt->dst.dev)))
+               return NULL;
+
        if (rt->rt6i_node && (rt->rt6i_node->fn_sernum == cookie)) {
                if (rt->rt6i_peer_genid != rt6_peer_genid()) {
                        if (!rt6_has_peer(rt))
@@ -1397,8 +1405,6 @@ int ip6_route_add(struct fib6_config *cfg)
                goto out;
        }
 
-       rt->dst.obsolete = -1;
-
        if (cfg->fc_flags & RTF_EXPIRES)
                rt6_set_expires(rt, jiffies +
                                clock_t_to_jiffies(cfg->fc_expires));
@@ -2080,7 +2086,6 @@ struct rt6_info *addrconf_dst_alloc(struct inet6_dev *idev,
        rt->dst.input = ip6_input;
        rt->dst.output = ip6_output;
        rt->rt6i_idev = idev;
-       rt->dst.obsolete = -1;
 
        rt->rt6i_flags = RTF_UP | RTF_NONEXTHOP;
        if (anycast)
index a3e60cc04a8a17e229afb44f38643ed86ac0c63e..acd32e3f1b68e7c11fd211383e05b50dfd07ee6a 100644 (file)
@@ -403,8 +403,9 @@ static void tcp_v6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                tp->mtu_info = ntohl(info);
                if (!sock_owned_by_user(sk))
                        tcp_v6_mtu_reduced(sk);
-               else
-                       set_bit(TCP_MTU_REDUCED_DEFERRED, &tp->tsq_flags);
+               else if (!test_and_set_bit(TCP_MTU_REDUCED_DEFERRED,
+                                          &tp->tsq_flags))
+                       sock_hold(sk);
                goto out;
        }
 
index 99d0077b56b86f088a4a2fd2819a7b03e0eabd49..07e2bfef6845429ee7e359a6c21141db0a0219de 100644 (file)
@@ -394,6 +394,17 @@ try_again:
        }
        if (unlikely(err)) {
                trace_kfree_skb(skb, udpv6_recvmsg);
+               if (!peeked) {
+                       atomic_inc(&sk->sk_drops);
+                       if (is_udp4)
+                               UDP_INC_STATS_USER(sock_net(sk),
+                                                  UDP_MIB_INERRORS,
+                                                  is_udplite);
+                       else
+                               UDP6_INC_STATS_USER(sock_net(sk),
+                                                   UDP_MIB_INERRORS,
+                                                   is_udplite);
+               }
                goto out_free;
        }
        if (!peeked) {
index 393355d37b476bc67219d57221759c3a1bdb52e8..1a9f3723c13cb45b608bbc07fe4a9803df926523 100644 (file)
@@ -1347,11 +1347,10 @@ static void l2tp_tunnel_free(struct l2tp_tunnel *tunnel)
        /* Remove from tunnel list */
        spin_lock_bh(&pn->l2tp_tunnel_list_lock);
        list_del_rcu(&tunnel->list);
+       kfree_rcu(tunnel, rcu);
        spin_unlock_bh(&pn->l2tp_tunnel_list_lock);
-       synchronize_rcu();
 
        atomic_dec(&l2tp_tunnel_count);
-       kfree(tunnel);
 }
 
 /* Create a socket for the tunnel, if one isn't set up by
@@ -1502,6 +1501,8 @@ out:
        return err;
 }
 
+static struct lock_class_key l2tp_socket_class;
+
 int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32 peer_tunnel_id, struct l2tp_tunnel_cfg *cfg, struct l2tp_tunnel **tunnelp)
 {
        struct l2tp_tunnel *tunnel = NULL;
@@ -1606,6 +1607,8 @@ int l2tp_tunnel_create(struct net *net, int fd, int version, u32 tunnel_id, u32
        tunnel->old_sk_destruct = sk->sk_destruct;
        sk->sk_destruct = &l2tp_tunnel_destruct;
        tunnel->sock = sk;
+       lockdep_set_class_and_name(&sk->sk_lock.slock, &l2tp_socket_class, "l2tp_sock");
+
        sk->sk_allocation = GFP_ATOMIC;
 
        /* Add tunnel to our list */
index a38ec6cdeee1a7ba81dc0ea9f659ca3f46bccb46..56d583e083a7baf7b0cf707a76882a88701d8025 100644 (file)
@@ -163,6 +163,7 @@ struct l2tp_tunnel_cfg {
 
 struct l2tp_tunnel {
        int                     magic;          /* Should be L2TP_TUNNEL_MAGIC */
+       struct rcu_head rcu;
        rwlock_t                hlist_lock;     /* protect session_hlist */
        struct hlist_head       session_hlist[L2TP_HASH_SIZE];
                                                /* hashed list of sessions,
index f9ee74deeac26f5469271a0800669cc82ffddc63..3bfb34aaee293cb697f36ae88a060f3329571214 100644 (file)
@@ -153,7 +153,7 @@ static void l2tp_eth_dev_recv(struct l2tp_session *session, struct sk_buff *skb,
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, skb->data, length);
        }
 
-       if (!pskb_may_pull(skb, sizeof(ETH_HLEN)))
+       if (!pskb_may_pull(skb, ETH_HLEN))
                goto error;
 
        secpath_reset(skb);
index d71cd9229a47a8fd85efbf3f5430c66a3e3ad5cd..6f936358d664cd3a8946317ca879180a937c8b22 100644 (file)
@@ -80,8 +80,8 @@ static int l2tp_nl_cmd_noop(struct sk_buff *skb, struct genl_info *info)
 
        hdr = genlmsg_put(msg, info->snd_pid, info->snd_seq,
                          &l2tp_nl_family, 0, L2TP_CMD_NOOP);
-       if (IS_ERR(hdr)) {
-               ret = PTR_ERR(hdr);
+       if (!hdr) {
+               ret = -EMSGSIZE;
                goto err_out;
        }
 
@@ -250,8 +250,8 @@ static int l2tp_nl_tunnel_send(struct sk_buff *skb, u32 pid, u32 seq, int flags,
 
        hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags,
                          L2TP_CMD_TUNNEL_GET);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -EMSGSIZE;
 
        if (nla_put_u8(skb, L2TP_ATTR_PROTO_VERSION, tunnel->version) ||
            nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
@@ -617,8 +617,8 @@ static int l2tp_nl_session_send(struct sk_buff *skb, u32 pid, u32 seq, int flags
        sk = tunnel->sock;
 
        hdr = genlmsg_put(skb, pid, seq, &l2tp_nl_family, flags, L2TP_CMD_SESSION_GET);
-       if (IS_ERR(hdr))
-               return PTR_ERR(hdr);
+       if (!hdr)
+               return -EMSGSIZE;
 
        if (nla_put_u32(skb, L2TP_ATTR_CONN_ID, tunnel->tunnel_id) ||
            nla_put_u32(skb, L2TP_ATTR_SESSION_ID, session->session_id) ||
index d41974aacf5168597fd559f1c976252f9e36ffd9..a58c0b649ba137b09214c031bf3508b5fe2974eb 100644 (file)
@@ -1378,6 +1378,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
        else
                memset(next_hop, 0, ETH_ALEN);
 
+       memset(pinfo, 0, sizeof(*pinfo));
+
        pinfo->generation = mesh_paths_generation;
 
        pinfo->filled = MPATH_INFO_FRAME_QLEN |
@@ -1396,7 +1398,6 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
        pinfo->discovery_timeout =
                        jiffies_to_msecs(mpath->discovery_timeout);
        pinfo->discovery_retries = mpath->discovery_retries;
-       pinfo->flags = 0;
        if (mpath->flags & MESH_PATH_ACTIVE)
                pinfo->flags |= NL80211_MPATH_FLAG_ACTIVE;
        if (mpath->flags & MESH_PATH_RESOLVING)
@@ -1405,10 +1406,8 @@ static void mpath_set_pinfo(struct mesh_path *mpath, u8 *next_hop,
                pinfo->flags |= NL80211_MPATH_FLAG_SN_VALID;
        if (mpath->flags & MESH_PATH_FIXED)
                pinfo->flags |= NL80211_MPATH_FLAG_FIXED;
-       if (mpath->flags & MESH_PATH_RESOLVING)
-               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVING;
-
-       pinfo->flags = mpath->flags;
+       if (mpath->flags & MESH_PATH_RESOLVED)
+               pinfo->flags |= NL80211_MPATH_FLAG_RESOLVED;
 }
 
 static int ieee80211_get_mpath(struct wiphy *wiphy, struct net_device *dev,
index a4a5acdbaa4dd3ac5e2fb8c5f0ff1d1b97553d6a..f76b83341cf9a39db0e14092a85f2e576245a306 100644 (file)
@@ -3248,6 +3248,8 @@ int ieee80211_mgd_auth(struct ieee80211_sub_if_data *sdata,
        goto out_unlock;
 
  err_clear:
+       memset(ifmgd->bssid, 0, ETH_ALEN);
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->auth_data = NULL;
  err_free:
        kfree(auth_data);
@@ -3439,6 +3441,8 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
        err = 0;
        goto out;
  err_clear:
+       memset(ifmgd->bssid, 0, ETH_ALEN);
+       ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BSSID);
        ifmgd->assoc_data = NULL;
  err_free:
        kfree(assoc_data);
index acf712ffb5e630b3c1fc74c6390c7606d4f043bd..c5e8c9c31f7687d9922d0011ea1b31e8244ea8d2 100644 (file)
@@ -1811,37 +1811,31 @@ netdev_tx_t ieee80211_subif_start_xmit(struct sk_buff *skb,
                        meshhdrlen = ieee80211_new_mesh_header(&mesh_hdr,
                                        sdata, NULL, NULL);
                } else {
-                       int is_mesh_mcast = 1;
-                       const u8 *mesh_da;
+                       /* DS -> MBSS (802.11-2012 13.11.3.3).
+                        * For unicast with unknown forwarding information,
+                        * destination might be in the MBSS or if that fails
+                        * forwarded to another mesh gate. In either case
+                        * resolution will be handled in ieee80211_xmit(), so
+                        * leave the original DA. This also works for mcast */
+                       const u8 *mesh_da = skb->data;
+
+                       if (mppath)
+                               mesh_da = mppath->mpp;
+                       else if (mpath)
+                               mesh_da = mpath->dst;
+                       rcu_read_unlock();
 
-                       if (is_multicast_ether_addr(skb->data))
-                               /* DA TA mSA AE:SA */
-                               mesh_da = skb->data;
-                       else {
-                               static const u8 bcast[ETH_ALEN] =
-                                       { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
-                               if (mppath) {
-                                       /* RA TA mDA mSA AE:DA SA */
-                                       mesh_da = mppath->mpp;
-                                       is_mesh_mcast = 0;
-                               } else if (mpath) {
-                                       mesh_da = mpath->dst;
-                                       is_mesh_mcast = 0;
-                               } else {
-                                       /* DA TA mSA AE:SA */
-                                       mesh_da = bcast;
-                               }
-                       }
                        hdrlen = ieee80211_fill_mesh_addresses(&hdr, &fc,
                                        mesh_da, sdata->vif.addr);
-                       rcu_read_unlock();
-                       if (is_mesh_mcast)
+                       if (is_multicast_ether_addr(mesh_da))
+                               /* DA TA mSA AE:SA */
                                meshhdrlen =
                                        ieee80211_new_mesh_header(&mesh_hdr,
                                                        sdata,
                                                        skb->data + ETH_ALEN,
                                                        NULL);
                        else
+                               /* RA TA mDA mSA AE:DA SA */
                                meshhdrlen =
                                        ieee80211_new_mesh_header(&mesh_hdr,
                                                        sdata,
index 72bf32a84874718927a4bcbdc2e26395be00bdd8..f51013c07b9f4e5a81885f0462d5423ccbc8a44f 100644 (file)
@@ -1171,8 +1171,10 @@ ip_vs_add_service(struct net *net, struct ip_vs_service_user_kern *u,
                goto out_err;
        }
        svc->stats.cpustats = alloc_percpu(struct ip_vs_cpu_stats);
-       if (!svc->stats.cpustats)
+       if (!svc->stats.cpustats) {
+               ret = -ENOMEM;
                goto out_err;
+       }
 
        /* I'm the first user of the service */
        atomic_set(&svc->usecnt, 0);
index cf4875565d6755af8cb7e3ee952b723a007f1b4c..2ceec64b19f9866a222787531ba948b4c9e7e75b 100644 (file)
@@ -249,12 +249,15 @@ static void death_by_event(unsigned long ul_conntrack)
 {
        struct nf_conn *ct = (void *)ul_conntrack;
        struct net *net = nf_ct_net(ct);
+       struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+       BUG_ON(ecache == NULL);
 
        if (nf_conntrack_event(IPCT_DESTROY, ct) < 0) {
                /* bad luck, let's retry again */
-               ct->timeout.expires = jiffies +
+               ecache->timeout.expires = jiffies +
                        (random32() % net->ct.sysctl_events_retry_timeout);
-               add_timer(&ct->timeout);
+               add_timer(&ecache->timeout);
                return;
        }
        /* we've got the event delivered, now it's dying */
@@ -268,6 +271,9 @@ static void death_by_event(unsigned long ul_conntrack)
 void nf_ct_insert_dying_list(struct nf_conn *ct)
 {
        struct net *net = nf_ct_net(ct);
+       struct nf_conntrack_ecache *ecache = nf_ct_ecache_find(ct);
+
+       BUG_ON(ecache == NULL);
 
        /* add this conntrack to the dying list */
        spin_lock_bh(&nf_conntrack_lock);
@@ -275,10 +281,10 @@ void nf_ct_insert_dying_list(struct nf_conn *ct)
                             &net->ct.dying);
        spin_unlock_bh(&nf_conntrack_lock);
        /* set a new timer to retry event delivery */
-       setup_timer(&ct->timeout, death_by_event, (unsigned long)ct);
-       ct->timeout.expires = jiffies +
+       setup_timer(&ecache->timeout, death_by_event, (unsigned long)ct);
+       ecache->timeout.expires = jiffies +
                (random32() % net->ct.sysctl_events_retry_timeout);
-       add_timer(&ct->timeout);
+       add_timer(&ecache->timeout);
 }
 EXPORT_SYMBOL_GPL(nf_ct_insert_dying_list);
 
index da4fc37a8578b6ef4590cbd0abf6e04241ebb8fc..9807f3278fcbcdfcc28c61b9b19e6a8c74d02b18 100644 (file)
@@ -2790,7 +2790,8 @@ static int __init ctnetlink_init(void)
                goto err_unreg_subsys;
        }
 
-       if (register_pernet_subsys(&ctnetlink_net_ops)) {
+       ret = register_pernet_subsys(&ctnetlink_net_ops);
+       if (ret < 0) {
                pr_err("ctnetlink_init: cannot register pernet operations\n");
                goto err_unreg_exp_subsys;
        }
index a5ac11ebef331895f39af5e86ca4406e56562ceb..e046b3756aab755080d3edced132c459b7c8d4c4 100644 (file)
@@ -158,21 +158,18 @@ static const u8 tcp_conntracks[2][6][TCP_CONNTRACK_MAX] = {
  *     sCL -> sSS
  */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
-/*synack*/ { sIV, sIV, sIG, sIG, sIG, sIG, sIG, sIG, sIG, sSR },
+/*synack*/ { sIV, sIV, sSR, sIV, sIV, sIV, sIV, sIV, sIV, sSR },
 /*
  *     sNO -> sIV      Too late and no reason to do anything
  *     sSS -> sIV      Client can't send SYN and then SYN/ACK
  *     sS2 -> sSR      SYN/ACK sent to SYN2 in simultaneous open
- *     sSR -> sIG
- *     sES -> sIG      Error: SYNs in window outside the SYN_SENT state
- *                     are errors. Receiver will reply with RST
- *                     and close the connection.
- *                     Or we are not in sync and hold a dead connection.
- *     sFW -> sIG
- *     sCW -> sIG
- *     sLA -> sIG
- *     sTW -> sIG
- *     sCL -> sIG
+ *     sSR -> sSR      Late retransmitted SYN/ACK in simultaneous open
+ *     sES -> sIV      Invalid SYN/ACK packets sent by the client
+ *     sFW -> sIV
+ *     sCW -> sIV
+ *     sLA -> sIV
+ *     sTW -> sIV
+ *     sCL -> sIV
  */
 /*          sNO, sSS, sSR, sES, sFW, sCW, sLA, sTW, sCL, sS2   */
 /*fin*/    { sIV, sIV, sFW, sFW, sLA, sLA, sLA, sTW, sCL, sIV },
@@ -633,15 +630,9 @@ static bool tcp_in_window(const struct nf_conn *ct,
                ack = sack = receiver->td_end;
        }
 
-       if (seq == end
-           && (!tcph->rst
-               || (seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)))
+       if (tcph->rst && seq == 0 && state->state == TCP_CONNTRACK_SYN_SENT)
                /*
-                * Packets contains no data: we assume it is valid
-                * and check the ack value only.
-                * However RST segments are always validated by their
-                * SEQ number, except when seq == 0 (reset sent answering
-                * SYN.
+                * RST sent answering SYN.
                 */
                seq = end = sender->td_end;
 
index 169ab59ed9d49073105443bfcae75c89a2f30024..5cfb5bedb2b8e8f2fa44ed936a7cab265b5878e6 100644 (file)
@@ -381,6 +381,7 @@ __build_packet_message(struct nfulnl_instance *inst,
        struct nlmsghdr *nlh;
        struct nfgenmsg *nfmsg;
        sk_buff_data_t old_tail = inst->skb->tail;
+       struct sock *sk;
 
        nlh = nlmsg_put(inst->skb, 0, 0,
                        NFNL_SUBSYS_ULOG << 8 | NFULNL_MSG_PACKET,
@@ -480,7 +481,7 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        if (indev && skb_mac_header_was_set(skb)) {
-               if (nla_put_be32(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
+               if (nla_put_be16(inst->skb, NFULA_HWTYPE, htons(skb->dev->type)) ||
                    nla_put_be16(inst->skb, NFULA_HWLEN,
                                 htons(skb->dev->hard_header_len)) ||
                    nla_put(inst->skb, NFULA_HWHEADER, skb->dev->hard_header_len,
@@ -499,18 +500,19 @@ __build_packet_message(struct nfulnl_instance *inst,
        }
 
        /* UID */
-       if (skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file) {
-                       struct file *file = skb->sk->sk_socket->file;
+       sk = skb->sk;
+       if (sk && sk->sk_state != TCP_TIME_WAIT) {
+               read_lock_bh(&sk->sk_callback_lock);
+               if (sk->sk_socket && sk->sk_socket->file) {
+                       struct file *file = sk->sk_socket->file;
                        __be32 uid = htonl(file->f_cred->fsuid);
                        __be32 gid = htonl(file->f_cred->fsgid);
-                       read_unlock_bh(&skb->sk->sk_callback_lock);
+                       read_unlock_bh(&sk->sk_callback_lock);
                        if (nla_put_be32(inst->skb, NFULA_UID, uid) ||
                            nla_put_be32(inst->skb, NFULA_GID, gid))
                                goto nla_put_failure;
                } else
-                       read_unlock_bh(&skb->sk->sk_callback_lock);
+                       read_unlock_bh(&sk->sk_callback_lock);
        }
 
        /* local sequence number */
@@ -996,8 +998,10 @@ static int __init nfnetlink_log_init(void)
 
 #ifdef CONFIG_PROC_FS
        if (!proc_create("nfnetlink_log", 0440,
-                        proc_net_netfilter, &nful_file_ops))
+                        proc_net_netfilter, &nful_file_ops)) {
+               status = -ENOMEM;
                goto cleanup_logger;
+       }
 #endif
        return status;
 
index ff5f75fddb15175c408a1e0a1cf8a656453aff80..91e9af4d1f42c3baef9af1261c9464c70cd1bac0 100644 (file)
@@ -145,6 +145,19 @@ static int dump_tcp_header(struct sbuff *m, const struct sk_buff *skb,
        return 0;
 }
 
+static void dump_sk_uid_gid(struct sbuff *m, struct sock *sk)
+{
+       if (!sk || sk->sk_state == TCP_TIME_WAIT)
+               return;
+
+       read_lock_bh(&sk->sk_callback_lock);
+       if (sk->sk_socket && sk->sk_socket->file)
+               sb_add(m, "UID=%u GID=%u ",
+                       sk->sk_socket->file->f_cred->fsuid,
+                       sk->sk_socket->file->f_cred->fsgid);
+       read_unlock_bh(&sk->sk_callback_lock);
+}
+
 /* One level of recursion won't kill us */
 static void dump_ipv4_packet(struct sbuff *m,
                        const struct nf_loginfo *info,
@@ -361,14 +374,8 @@ static void dump_ipv4_packet(struct sbuff *m,
        }
 
        /* Max length: 15 "UID=4294967295 " */
-       if ((logflags & XT_LOG_UID) && !iphoff && skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-                       sb_add(m, "UID=%u GID=%u ",
-                               skb->sk->sk_socket->file->f_cred->fsuid,
-                               skb->sk->sk_socket->file->f_cred->fsgid);
-               read_unlock_bh(&skb->sk->sk_callback_lock);
-       }
+       if ((logflags & XT_LOG_UID) && !iphoff)
+               dump_sk_uid_gid(m, skb->sk);
 
        /* Max length: 16 "MARK=0xFFFFFFFF " */
        if (!iphoff && skb->mark)
@@ -436,8 +443,8 @@ log_packet_common(struct sbuff *m,
                  const struct nf_loginfo *loginfo,
                  const char *prefix)
 {
-       sb_add(m, "<%d>%sIN=%s OUT=%s ", loginfo->u.log.level,
-              prefix,
+       sb_add(m, KERN_SOH "%c%sIN=%s OUT=%s ",
+              '0' + loginfo->u.log.level, prefix,
               in ? in->name : "",
               out ? out->name : "");
 #ifdef CONFIG_BRIDGE_NETFILTER
@@ -717,14 +724,8 @@ static void dump_ipv6_packet(struct sbuff *m,
        }
 
        /* Max length: 15 "UID=4294967295 " */
-       if ((logflags & XT_LOG_UID) && recurse && skb->sk) {
-               read_lock_bh(&skb->sk->sk_callback_lock);
-               if (skb->sk->sk_socket && skb->sk->sk_socket->file)
-                       sb_add(m, "UID=%u GID=%u ",
-                               skb->sk->sk_socket->file->f_cred->fsuid,
-                               skb->sk->sk_socket->file->f_cred->fsgid);
-               read_unlock_bh(&skb->sk->sk_callback_lock);
-       }
+       if ((logflags & XT_LOG_UID) && recurse)
+               dump_sk_uid_gid(m, skb->sk);
 
        /* Max length: 16 "MARK=0xFFFFFFFF " */
        if (!recurse && skb->mark)
index 5c22ce8ab3090b103ac75c7ae54d0489c1bc84e2..a4c1e4528cac7e3e820f1cecfb8ec22e8dcf5966 100644 (file)
@@ -117,11 +117,11 @@ static int limit_mt_check(const struct xt_mtchk_param *par)
 
        /* For SMP, we only want to use one set of state. */
        r->master = priv;
+       /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
+          128. */
+       priv->prev = jiffies;
+       priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
        if (r->cost == 0) {
-               /* User avg in seconds * XT_LIMIT_SCALE: convert to jiffies *
-                  128. */
-               priv->prev = jiffies;
-               priv->credit = user2credits(r->avg * r->burst); /* Credits full. */
                r->credit_cap = priv->credit; /* Credits full. */
                r->cost = user2credits(r->avg);
        }
index 1445d73533ed13ac9aa43dd85d6f58b4a006c130..527023823b5c5ea1a48c373b49e9f1688891a494 100644 (file)
@@ -1373,7 +1373,8 @@ static int netlink_sendmsg(struct kiocb *kiocb, struct socket *sock,
                dst_pid = addr->nl_pid;
                dst_group = ffs(addr->nl_groups);
                err =  -EPERM;
-               if (dst_group && !netlink_capable(sock, NL_NONROOT_SEND))
+               if ((dst_group || dst_pid) &&
+                   !netlink_capable(sock, NL_NONROOT_SEND))
                        goto out;
        } else {
                dst_pid = nlk->dst_pid;
@@ -2147,6 +2148,7 @@ static void __init netlink_add_usersock_entry(void)
        rcu_assign_pointer(nl_table[NETLINK_USERSOCK].listeners, listeners);
        nl_table[NETLINK_USERSOCK].module = THIS_MODULE;
        nl_table[NETLINK_USERSOCK].registered = 1;
+       nl_table[NETLINK_USERSOCK].nl_nonroot = NL_NONROOT_SEND;
 
        netlink_table_ungrab();
 }
index 06592d8b4a2b4eba33d9e71e44fc75ca206b38a8..7261eb81974ff9f3761976372c9272db04a62abd 100644 (file)
@@ -601,7 +601,7 @@ static int nr_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
                if (!capable(CAP_NET_BIND_SERVICE)) {
                        dev_put(dev);
                        release_sock(sk);
-                       return -EACCES;
+                       return -EPERM;
                }
                nr->user_addr   = addr->fsa_digipeater[0];
                nr->source_addr = addr->fsa_ax25.sax25_call;
@@ -1169,7 +1169,12 @@ static int nr_recvmsg(struct kiocb *iocb, struct socket *sock,
                msg->msg_flags |= MSG_TRUNC;
        }
 
-       skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       er = skb_copy_datagram_iovec(skb, 0, msg->msg_iov, copied);
+       if (er < 0) {
+               skb_free_datagram(sk, skb);
+               release_sock(sk);
+               return er;
+       }
 
        if (sax != NULL) {
                sax->sax25_family = AF_NETROM;
index f3f96badf5aac0202a2bd54155d595b0373a18df..954405ceae9ed5141293d3f47ce7c784aeee3c31 100644 (file)
@@ -45,7 +45,7 @@ static int make_writable(struct sk_buff *skb, int write_len)
        return pskb_expand_head(skb, 0, 0, GFP_ATOMIC);
 }
 
-/* remove VLAN header from packet and update csum accrodingly. */
+/* remove VLAN header from packet and update csum accordingly. */
 static int __pop_vlan_tci(struct sk_buff *skb, __be16 *current_tci)
 {
        struct vlan_hdr *vhdr;
index d8277d29e7102caf343d78b802f3371283c40de1..cf58cedad0833f9e9e704401fdecb5480c121caf 100644 (file)
@@ -425,10 +425,10 @@ static int validate_sample(const struct nlattr *attr,
 static int validate_tp_port(const struct sw_flow_key *flow_key)
 {
        if (flow_key->eth.type == htons(ETH_P_IP)) {
-               if (flow_key->ipv4.tp.src && flow_key->ipv4.tp.dst)
+               if (flow_key->ipv4.tp.src || flow_key->ipv4.tp.dst)
                        return 0;
        } else if (flow_key->eth.type == htons(ETH_P_IPV6)) {
-               if (flow_key->ipv6.tp.src && flow_key->ipv6.tp.dst)
+               if (flow_key->ipv6.tp.src || flow_key->ipv6.tp.dst)
                        return 0;
        }
 
@@ -460,7 +460,7 @@ static int validate_set(const struct nlattr *a,
                if (flow_key->eth.type != htons(ETH_P_IP))
                        return -EINVAL;
 
-               if (!flow_key->ipv4.addr.src || !flow_key->ipv4.addr.dst)
+               if (!flow_key->ip.proto)
                        return -EINVAL;
 
                ipv4_key = nla_data(ovs_key);
index 9b75617ca4e031db60ddbeb609bb658af7f8de0c..c30df1a10c670ad01b7b8b88c49434c95c0c659e 100644 (file)
@@ -145,15 +145,17 @@ u64 ovs_flow_used_time(unsigned long flow_jiffies);
  *  OVS_KEY_ATTR_PRIORITY      4    --     4      8
  *  OVS_KEY_ATTR_IN_PORT       4    --     4      8
  *  OVS_KEY_ATTR_ETHERNET     12    --     4     16
+ *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (outer VLAN ethertype)
  *  OVS_KEY_ATTR_8021Q         4    --     4      8
- *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8
+ *  OVS_KEY_ATTR_ENCAP         0    --     4      4  (VLAN encapsulation)
+ *  OVS_KEY_ATTR_ETHERTYPE     2     2     4      8  (inner VLAN ethertype)
  *  OVS_KEY_ATTR_IPV6         40    --     4     44
  *  OVS_KEY_ATTR_ICMPV6        2     2     4      8
  *  OVS_KEY_ATTR_ND           28    --     4     32
  *  -------------------------------------------------
- *  total                                       132
+ *  total                                       144
  */
-#define FLOW_BUFSIZE 132
+#define FLOW_BUFSIZE 144
 
 int ovs_flow_to_nlattrs(const struct sw_flow_key *, struct sk_buff *);
 int ovs_flow_from_nlattrs(struct sw_flow_key *swkey, int *key_lenp,
index aee7196aac36c990eedfc7b494a04351c29bb167..c5c9e2a54218207f0dba9b16920b2e17da84c353 100644 (file)
@@ -1273,7 +1273,7 @@ static void __fanout_unlink(struct sock *sk, struct packet_sock *po)
        spin_unlock(&f->lock);
 }
 
-bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
+static bool match_fanout_group(struct packet_type *ptype, struct sock * sk)
 {
        if (ptype->af_packet_priv == (void*)((struct packet_sock *)sk)->fanout)
                return true;
index 6aabd77d1cfdd5cddd34b55dc69699cae9956e57..564b9fc8efd3c8778ef8ba155cf17f79d92a9a80 100644 (file)
@@ -250,10 +250,11 @@ cbq_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
                        else if ((cl = defmap[res.classid & TC_PRIO_MAX]) == NULL)
                                cl = defmap[TC_PRIO_BESTEFFORT];
 
-                       if (cl == NULL || cl->level >= head->level)
+                       if (cl == NULL)
                                goto fallback;
                }
-
+               if (cl->level >= head->level)
+                       goto fallback;
 #ifdef CONFIG_NET_CLS_ACT
                switch (result) {
                case TC_ACT_QUEUED:
index 9fc1c62ec80e1ad56b760b2820c0c4f2e495d4a0..4e606fcb2534929a2470e807816ac1089d81b7b2 100644 (file)
@@ -191,7 +191,6 @@ static int fq_codel_enqueue(struct sk_buff *skb, struct Qdisc *sch)
 
        if (list_empty(&flow->flowchain)) {
                list_add_tail(&flow->flowchain, &q->new_flows);
-               codel_vars_init(&flow->cvars);
                q->new_flow_count++;
                flow->deficit = q->quantum;
                flow->dropped = 0;
@@ -418,6 +417,7 @@ static int fq_codel_init(struct Qdisc *sch, struct nlattr *opt)
                        struct fq_codel_flow *flow = q->flows + i;
 
                        INIT_LIST_HEAD(&flow->flowchain);
+                       codel_vars_init(&flow->cvars);
                }
        }
        if (sch->limit >= 1)
index e901583e4ea533581f13e0fb39599f72e57b3e4c..d42234c0f13bf4d4829930e0f6bcb30681ad4782 100644 (file)
@@ -102,9 +102,8 @@ static inline int gred_wred_mode_check(struct Qdisc *sch)
                if (q == NULL)
                        continue;
 
-               for (n = 0; n < table->DPs; n++)
-                       if (table->tab[n] && table->tab[n] != q &&
-                           table->tab[n]->prio == q->prio)
+               for (n = i + 1; n < table->DPs; n++)
+                       if (table->tab[n] && table->tab[n]->prio == q->prio)
                                return 1;
        }
 
@@ -137,6 +136,7 @@ static inline void gred_store_wred_set(struct gred_sched *table,
                                       struct gred_sched_data *q)
 {
        table->wred_set.qavg = q->vars.qavg;
+       table->wred_set.qidlestart = q->vars.qidlestart;
 }
 
 static inline int gred_use_ecn(struct gred_sched *t)
@@ -176,7 +176,7 @@ static int gred_enqueue(struct sk_buff *skb, struct Qdisc *sch)
                skb->tc_index = (skb->tc_index & ~GRED_VQ_MASK) | dp;
        }
 
-       /* sum up all the qaves of prios <= to ours to get the new qave */
+       /* sum up all the qaves of prios < ours to get the new qave */
        if (!gred_wred_mode(t) && gred_rio_mode(t)) {
                int i;
 
@@ -260,16 +260,18 @@ static struct sk_buff *gred_dequeue(struct Qdisc *sch)
                } else {
                        q->backlog -= qdisc_pkt_len(skb);
 
-                       if (!q->backlog && !gred_wred_mode(t))
-                               red_start_of_idle_period(&q->vars);
+                       if (gred_wred_mode(t)) {
+                               if (!sch->qstats.backlog)
+                                       red_start_of_idle_period(&t->wred_set);
+                       } else {
+                               if (!q->backlog)
+                                       red_start_of_idle_period(&q->vars);
+                       }
                }
 
                return skb;
        }
 
-       if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
-               red_start_of_idle_period(&t->wred_set);
-
        return NULL;
 }
 
@@ -291,19 +293,20 @@ static unsigned int gred_drop(struct Qdisc *sch)
                        q->backlog -= len;
                        q->stats.other++;
 
-                       if (!q->backlog && !gred_wred_mode(t))
-                               red_start_of_idle_period(&q->vars);
+                       if (gred_wred_mode(t)) {
+                               if (!sch->qstats.backlog)
+                                       red_start_of_idle_period(&t->wred_set);
+                       } else {
+                               if (!q->backlog)
+                                       red_start_of_idle_period(&q->vars);
+                       }
                }
 
                qdisc_drop(skb, sch);
                return len;
        }
 
-       if (gred_wred_mode(t) && !red_is_idling(&t->wred_set))
-               red_start_of_idle_period(&t->wred_set);
-
        return 0;
-
 }
 
 static void gred_reset(struct Qdisc *sch)
@@ -535,6 +538,7 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
        for (i = 0; i < MAX_DPs; i++) {
                struct gred_sched_data *q = table->tab[i];
                struct tc_gred_qopt opt;
+               unsigned long qavg;
 
                memset(&opt, 0, sizeof(opt));
 
@@ -566,7 +570,9 @@ static int gred_dump(struct Qdisc *sch, struct sk_buff *skb)
                if (gred_wred_mode(table))
                        gred_load_wred_set(table, q);
 
-               opt.qave = red_calc_qavg(&q->parms, &q->vars, q->vars.qavg);
+               qavg = red_calc_qavg(&q->parms, &q->vars,
+                                    q->vars.qavg >> q->parms.Wlog);
+               opt.qave = qavg >> q->parms.Wlog;
 
 append_opt:
                if (nla_append(skb, sizeof(opt), &opt) < 0)
index e4723d31fdd56d6a46b2519afd19d612c7336749..211a212170451c41f352f087dc9e0b3af9e8ae2c 100644 (file)
@@ -865,7 +865,10 @@ static void qfq_update_start(struct qfq_sched *q, struct qfq_class *cl)
                if (mask) {
                        struct qfq_group *next = qfq_ffs(q, mask);
                        if (qfq_gt(roundedF, next->F)) {
-                               cl->S = next->F;
+                               if (qfq_gt(limit, next->F))
+                                       cl->S = next->F;
+                               else /* preserve timestamp correctness */
+                                       cl->S = limit;
                                return;
                        }
                }
index 838e18b4d7ea62cfd4d57e9d64a86630a0100f67..be50aa234dcdea30a5c7986eaeaae3570f64a6e3 100644 (file)
@@ -364,6 +364,25 @@ finish:
        return retval;
 }
 
+static void sctp_packet_release_owner(struct sk_buff *skb)
+{
+       sk_free(skb->sk);
+}
+
+static void sctp_packet_set_owner_w(struct sk_buff *skb, struct sock *sk)
+{
+       skb_orphan(skb);
+       skb->sk = sk;
+       skb->destructor = sctp_packet_release_owner;
+
+       /*
+        * The data chunks have already been accounted for in sctp_sendmsg(),
+        * therefore only reserve a single byte to keep socket around until
+        * the packet has been transmitted.
+        */
+       atomic_inc(&sk->sk_wmem_alloc);
+}
+
 /* All packets are sent to the network through this function from
  * sctp_outq_tail().
  *
@@ -405,7 +424,7 @@ int sctp_packet_transmit(struct sctp_packet *packet)
        /* Set the owning socket so that we know where to get the
         * destination IP address.
         */
-       skb_set_owner_w(nskb, sk);
+       sctp_packet_set_owner_w(nskb, sk);
 
        if (!sctp_transport_dst_check(tp)) {
                sctp_transport_route(tp, NULL, sctp_sk(sk));
index a5471f804d994ece8c31df6be0e04d5076b6dfd0..edc3c4af9085362c7227e31babfc19a489bf9cf6 100644 (file)
@@ -2604,7 +2604,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timeval(up, &ktv);
+               err = compat_put_timeval(&ktv, up);
 
        return err;
 }
@@ -2620,7 +2620,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
-               err = compat_put_timespec(up, &kts);
+               err = compat_put_timespec(&kts, up);
 
        return err;
 }
index 88f2bf671960d444e73d3d9eba2998f75ac2885b..bac973a313673eaab9dc5300a86cef0cfbd577e0 100644 (file)
@@ -316,7 +316,6 @@ static bool svc_xprt_has_something_to_do(struct svc_xprt *xprt)
  */
 void svc_xprt_enqueue(struct svc_xprt *xprt)
 {
-       struct svc_serv *serv = xprt->xpt_server;
        struct svc_pool *pool;
        struct svc_rqst *rqstp;
        int cpu;
@@ -362,8 +361,6 @@ void svc_xprt_enqueue(struct svc_xprt *xprt)
                                rqstp, rqstp->rq_xprt);
                rqstp->rq_xprt = xprt;
                svc_xprt_get(xprt);
-               rqstp->rq_reserved = serv->sv_max_mesg;
-               atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
                pool->sp_stats.threads_woken++;
                wake_up(&rqstp->rq_wait);
        } else {
@@ -640,8 +637,6 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
        if (xprt) {
                rqstp->rq_xprt = xprt;
                svc_xprt_get(xprt);
-               rqstp->rq_reserved = serv->sv_max_mesg;
-               atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
 
                /* As there is a shortage of threads and this request
                 * had to be queued, don't allow the thread to wait so
@@ -738,6 +733,8 @@ int svc_recv(struct svc_rqst *rqstp, long timeout)
                else
                        len = xprt->xpt_ops->xpo_recvfrom(rqstp);
                dprintk("svc: got len=%d\n", len);
+               rqstp->rq_reserved = serv->sv_max_mesg;
+               atomic_add(rqstp->rq_reserved, &xprt->xpt_reserved);
        }
        svc_xprt_received(xprt);
 
@@ -794,7 +791,8 @@ int svc_send(struct svc_rqst *rqstp)
 
        /* Grab mutex to serialize outgoing data. */
        mutex_lock(&xprt->xpt_mutex);
-       if (test_bit(XPT_DEAD, &xprt->xpt_flags))
+       if (test_bit(XPT_DEAD, &xprt->xpt_flags)
+                       || test_bit(XPT_CLOSE, &xprt->xpt_flags))
                len = -ENOTCONN;
        else
                len = xprt->xpt_ops->xpo_sendto(rqstp);
index 18bc130255a75e537f87d15bddde82faf165d91e..998aa8c1807cd7cd548023d4ea2e80fedc9c2ca9 100644 (file)
@@ -1129,9 +1129,9 @@ static int svc_tcp_recvfrom(struct svc_rqst *rqstp)
        if (len >= 0)
                svsk->sk_tcplen += len;
        if (len != want) {
+               svc_tcp_save_pages(svsk, rqstp);
                if (len < 0 && len != -EAGAIN)
                        goto err_other;
-               svc_tcp_save_pages(svsk, rqstp);
                dprintk("svc: incomplete TCP record (%d of %d)\n",
                        svsk->sk_tcplen, svsk->sk_reclen);
                goto err_noclose;
index a5a402a7d21f9e888b1c3f45b3bed09e8baf57e8..5d7f61d7559c9753c9bff0f29b371b5e62b5f0d9 100644 (file)
@@ -969,11 +969,11 @@ static bool xprt_dynamic_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
        return false;
 }
 
-static void xprt_alloc_slot(struct rpc_task *task)
+void xprt_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
 {
-       struct rpc_xprt *xprt = task->tk_xprt;
        struct rpc_rqst *req;
 
+       spin_lock(&xprt->reserve_lock);
        if (!list_empty(&xprt->free)) {
                req = list_entry(xprt->free.next, struct rpc_rqst, rq_list);
                list_del(&req->rq_list);
@@ -994,12 +994,29 @@ static void xprt_alloc_slot(struct rpc_task *task)
        default:
                task->tk_status = -EAGAIN;
        }
+       spin_unlock(&xprt->reserve_lock);
        return;
 out_init_req:
        task->tk_status = 0;
        task->tk_rqstp = req;
        xprt_request_init(task, xprt);
+       spin_unlock(&xprt->reserve_lock);
+}
+EXPORT_SYMBOL_GPL(xprt_alloc_slot);
+
+void xprt_lock_and_alloc_slot(struct rpc_xprt *xprt, struct rpc_task *task)
+{
+       /* Note: grabbing the xprt_lock_write() ensures that we throttle
+        * new slot allocation if the transport is congested (i.e. when
+        * reconnecting a stream transport or when out of socket write
+        * buffer space).
+        */
+       if (xprt_lock_write(xprt, task)) {
+               xprt_alloc_slot(xprt, task);
+               xprt_release_write(xprt, task);
+       }
 }
+EXPORT_SYMBOL_GPL(xprt_lock_and_alloc_slot);
 
 static void xprt_free_slot(struct rpc_xprt *xprt, struct rpc_rqst *req)
 {
@@ -1083,20 +1100,9 @@ void xprt_reserve(struct rpc_task *task)
        if (task->tk_rqstp != NULL)
                return;
 
-       /* Note: grabbing the xprt_lock_write() here is not strictly needed,
-        * but ensures that we throttle new slot allocation if the transport
-        * is congested (e.g. if reconnecting or if we're out of socket
-        * write buffer space).
-        */
        task->tk_timeout = 0;
        task->tk_status = -EAGAIN;
-       if (!xprt_lock_write(xprt, task))
-               return;
-
-       spin_lock(&xprt->reserve_lock);
-       xprt_alloc_slot(task);
-       spin_unlock(&xprt->reserve_lock);
-       xprt_release_write(xprt, task);
+       xprt->ops->alloc_slot(xprt, task);
 }
 
 static inline __be32 xprt_alloc_xid(struct rpc_xprt *xprt)
index 06cdbff79e4af433d5a4ea3a2766d6d09a9b5a01..5d9202dc7cb127f5158a2a6e275fa0656c18f0a6 100644 (file)
@@ -713,6 +713,7 @@ static void xprt_rdma_print_stats(struct rpc_xprt *xprt, struct seq_file *seq)
 static struct rpc_xprt_ops xprt_rdma_procs = {
        .reserve_xprt           = xprt_rdma_reserve_xprt,
        .release_xprt           = xprt_release_xprt_cong, /* sunrpc/xprt.c */
+       .alloc_slot             = xprt_alloc_slot,
        .release_request        = xprt_release_rqst_cong,       /* ditto */
        .set_retrans_timeout    = xprt_set_retrans_timeout_def, /* ditto */
        .rpcbind                = rpcb_getport_async,   /* sunrpc/rpcb_clnt.c */
index 400567243f84ba95e8f04d8a631a3b74539c53ea..a35b8e52e551d4b931110a78727604c8d6af8283 100644 (file)
@@ -2473,6 +2473,7 @@ static void bc_destroy(struct rpc_xprt *xprt)
 static struct rpc_xprt_ops xs_local_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
+       .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = xs_local_rpcbind,
        .set_port               = xs_local_set_port,
        .connect                = xs_connect,
@@ -2489,6 +2490,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
        .set_buffer_size        = xs_udp_set_buffer_size,
        .reserve_xprt           = xprt_reserve_xprt_cong,
        .release_xprt           = xprt_release_xprt_cong,
+       .alloc_slot             = xprt_alloc_slot,
        .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
@@ -2506,6 +2508,7 @@ static struct rpc_xprt_ops xs_udp_ops = {
 static struct rpc_xprt_ops xs_tcp_ops = {
        .reserve_xprt           = xprt_reserve_xprt,
        .release_xprt           = xs_tcp_release_xprt,
+       .alloc_slot             = xprt_lock_and_alloc_slot,
        .rpcbind                = rpcb_getport_async,
        .set_port               = xs_set_port,
        .connect                = xs_connect,
index 97026f3b215a1c85b3ddf0f0f6cf71636e76a586..1e37dbf00cb3f3850d3785827f896ca09339873b 100644 (file)
@@ -5633,8 +5633,10 @@ static int nl80211_connect(struct sk_buff *skb, struct genl_info *info)
                       sizeof(connect.ht_capa_mask));
 
        if (info->attrs[NL80211_ATTR_HT_CAPABILITY]) {
-               if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK])
+               if (!info->attrs[NL80211_ATTR_HT_CAPABILITY_MASK]) {
+                       kfree(connkeys);
                        return -EINVAL;
+               }
                memcpy(&connect.ht_capa,
                       nla_data(info->attrs[NL80211_ATTR_HT_CAPABILITY]),
                       sizeof(connect.ht_capa));
index 2ded3c7fad063a067151595c774b9bddd14bdc9a..72d170ca340665ea5c893cc1bec2316219abbf7c 100644 (file)
@@ -350,6 +350,9 @@ static void reg_regdb_search(struct work_struct *work)
        struct reg_regdb_search_request *request;
        const struct ieee80211_regdomain *curdom, *regdom;
        int i, r;
+       bool set_reg = false;
+
+       mutex_lock(&cfg80211_mutex);
 
        mutex_lock(&reg_regdb_search_mutex);
        while (!list_empty(&reg_regdb_search_list)) {
@@ -365,9 +368,7 @@ static void reg_regdb_search(struct work_struct *work)
                                r = reg_copy_regd(&regdom, curdom);
                                if (r)
                                        break;
-                               mutex_lock(&cfg80211_mutex);
-                               set_regdom(regdom);
-                               mutex_unlock(&cfg80211_mutex);
+                               set_reg = true;
                                break;
                        }
                }
@@ -375,6 +376,11 @@ static void reg_regdb_search(struct work_struct *work)
                kfree(request);
        }
        mutex_unlock(&reg_regdb_search_mutex);
+
+       if (set_reg)
+               set_regdom(regdom);
+
+       mutex_unlock(&cfg80211_mutex);
 }
 
 static DECLARE_WORK(reg_regdb_work, reg_regdb_search);
index 54a0dc2e2f8d45d7a842be98882969f696c07ec2..ab2bb42fe094b7390d5135ec6e37b9113ea8219b 100644 (file)
@@ -212,7 +212,7 @@ resume:
                /* only the first xfrm gets the encap type */
                encap_type = 0;
 
-               if (async && x->repl->check(x, skb, seq)) {
+               if (async && x->repl->recheck(x, skb, seq)) {
                        XFRM_INC_STATS(net, LINUX_MIB_XFRMINSTATESEQERROR);
                        goto drop_unlock;
                }
index 5a2aa17e4d3c4a3667783266ddbb8992a3eff6bd..387848e900783f6e6862c6d2c0b52ab45bbcfe50 100644 (file)
@@ -585,6 +585,7 @@ int xfrm_policy_insert(int dir, struct xfrm_policy *policy, int excl)
        xfrm_pol_hold(policy);
        net->xfrm.policy_count[dir]++;
        atomic_inc(&flow_cache_genid);
+       rt_genid_bump(net);
        if (delpol)
                __xfrm_policy_unlink(delpol, dir);
        policy->index = delpol ? delpol->index : xfrm_gen_index(net, dir);
@@ -1763,7 +1764,7 @@ static struct dst_entry *make_blackhole(struct net *net, u16 family,
 
        if (!afinfo) {
                dst_release(dst_orig);
-               ret = ERR_PTR(-EINVAL);
+               return ERR_PTR(-EINVAL);
        } else {
                ret = afinfo->blackhole_route(net, dst_orig);
        }
index 2f6d11d04a2b29910a1f284d3e3af8b0db1bfcce..3efb07d3eb27425c8b9b5114c925eb9e7f402c9e 100644 (file)
@@ -420,6 +420,18 @@ err:
        return -EINVAL;
 }
 
+static int xfrm_replay_recheck_esn(struct xfrm_state *x,
+                                  struct sk_buff *skb, __be32 net_seq)
+{
+       if (unlikely(XFRM_SKB_CB(skb)->seq.input.hi !=
+                    htonl(xfrm_replay_seqhi(x, net_seq)))) {
+                       x->stats.replay_window++;
+                       return -EINVAL;
+       }
+
+       return xfrm_replay_check_esn(x, skb, net_seq);
+}
+
 static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
 {
        unsigned int bitnr, nr, i;
@@ -479,6 +491,7 @@ static void xfrm_replay_advance_esn(struct xfrm_state *x, __be32 net_seq)
 static struct xfrm_replay xfrm_replay_legacy = {
        .advance        = xfrm_replay_advance,
        .check          = xfrm_replay_check,
+       .recheck        = xfrm_replay_check,
        .notify         = xfrm_replay_notify,
        .overflow       = xfrm_replay_overflow,
 };
@@ -486,6 +499,7 @@ static struct xfrm_replay xfrm_replay_legacy = {
 static struct xfrm_replay xfrm_replay_bmp = {
        .advance        = xfrm_replay_advance_bmp,
        .check          = xfrm_replay_check_bmp,
+       .recheck        = xfrm_replay_check_bmp,
        .notify         = xfrm_replay_notify_bmp,
        .overflow       = xfrm_replay_overflow_bmp,
 };
@@ -493,6 +507,7 @@ static struct xfrm_replay xfrm_replay_bmp = {
 static struct xfrm_replay xfrm_replay_esn = {
        .advance        = xfrm_replay_advance_esn,
        .check          = xfrm_replay_check_esn,
+       .recheck        = xfrm_replay_recheck_esn,
        .notify         = xfrm_replay_notify_bmp,
        .overflow       = xfrm_replay_overflow_esn,
 };
index 87cd0e4d42829a19797ae3e2371c47723fd40fb7..210be48d8ae3c295a3f9e9642c356acd9866c92c 100644 (file)
@@ -1994,8 +1994,10 @@ int __xfrm_init_state(struct xfrm_state *x, bool init_replay)
                goto error;
 
        x->outer_mode = xfrm_get_mode(x->props.mode, family);
-       if (x->outer_mode == NULL)
+       if (x->outer_mode == NULL) {
+               err = -EPROTONOSUPPORT;
                goto error;
+       }
 
        if (init_replay) {
                err = xfrm_init_replay(x);
index e75d8e47f35cab2bdddd1051e6da556ef20eb26c..289f4bf18ff05751c5938c8722b098f6a560ee00 100644 (file)
@@ -123,9 +123,21 @@ static inline int verify_replay(struct xfrm_usersa_info *p,
                                struct nlattr **attrs)
 {
        struct nlattr *rt = attrs[XFRMA_REPLAY_ESN_VAL];
+       struct xfrm_replay_state_esn *rs;
 
-       if ((p->flags & XFRM_STATE_ESN) && !rt)
-               return -EINVAL;
+       if (p->flags & XFRM_STATE_ESN) {
+               if (!rt)
+                       return -EINVAL;
+
+               rs = nla_data(rt);
+
+               if (rs->bmp_len > XFRMA_REPLAY_ESN_MAX / sizeof(rs->bmp[0]) / 8)
+                       return -EINVAL;
+
+               if (nla_len(rt) < xfrm_replay_state_esn_len(rs) &&
+                   nla_len(rt) != sizeof(*rs))
+                       return -EINVAL;
+       }
 
        if (!rt)
                return 0;
@@ -370,14 +382,15 @@ static inline int xfrm_replay_verify_len(struct xfrm_replay_state_esn *replay_es
                                         struct nlattr *rp)
 {
        struct xfrm_replay_state_esn *up;
+       int ulen;
 
        if (!replay_esn || !rp)
                return 0;
 
        up = nla_data(rp);
+       ulen = xfrm_replay_state_esn_len(up);
 
-       if (xfrm_replay_state_esn_len(replay_esn) !=
-                       xfrm_replay_state_esn_len(up))
+       if (nla_len(rp) < ulen || xfrm_replay_state_esn_len(replay_esn) != ulen)
                return -EINVAL;
 
        return 0;
@@ -388,22 +401,28 @@ static int xfrm_alloc_replay_state_esn(struct xfrm_replay_state_esn **replay_esn
                                       struct nlattr *rta)
 {
        struct xfrm_replay_state_esn *p, *pp, *up;
+       int klen, ulen;
 
        if (!rta)
                return 0;
 
        up = nla_data(rta);
+       klen = xfrm_replay_state_esn_len(up);
+       ulen = nla_len(rta) >= klen ? klen : sizeof(*up);
 
-       p = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+       p = kzalloc(klen, GFP_KERNEL);
        if (!p)
                return -ENOMEM;
 
-       pp = kmemdup(up, xfrm_replay_state_esn_len(up), GFP_KERNEL);
+       pp = kzalloc(klen, GFP_KERNEL);
        if (!pp) {
                kfree(p);
                return -ENOMEM;
        }
 
+       memcpy(p, up, ulen);
+       memcpy(pp, up, ulen);
+
        *replay_esn = p;
        *preplay_esn = pp;
 
@@ -442,10 +461,11 @@ static void copy_from_user_state(struct xfrm_state *x, struct xfrm_usersa_info *
  * somehow made shareable and move it to xfrm_state.c - JHS
  *
 */
-static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs)
+static void xfrm_update_ae_params(struct xfrm_state *x, struct nlattr **attrs,
+                                 int update_esn)
 {
        struct nlattr *rp = attrs[XFRMA_REPLAY_VAL];
-       struct nlattr *re = attrs[XFRMA_REPLAY_ESN_VAL];
+       struct nlattr *re = update_esn ? attrs[XFRMA_REPLAY_ESN_VAL] : NULL;
        struct nlattr *lt = attrs[XFRMA_LTIME_VAL];
        struct nlattr *et = attrs[XFRMA_ETIMER_THRESH];
        struct nlattr *rt = attrs[XFRMA_REPLAY_THRESH];
@@ -555,7 +575,7 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
                goto error;
 
        /* override default values from above */
-       xfrm_update_ae_params(x, attrs);
+       xfrm_update_ae_params(x, attrs, 0);
 
        return x;
 
@@ -689,6 +709,7 @@ out:
 
 static void copy_to_user_state(struct xfrm_state *x, struct xfrm_usersa_info *p)
 {
+       memset(p, 0, sizeof(*p));
        memcpy(&p->id, &x->id, sizeof(p->id));
        memcpy(&p->sel, &x->sel, sizeof(p->sel));
        memcpy(&p->lft, &x->lft, sizeof(p->lft));
@@ -742,7 +763,7 @@ static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
                return -EMSGSIZE;
 
        algo = nla_data(nla);
-       strcpy(algo->alg_name, auth->alg_name);
+       strncpy(algo->alg_name, auth->alg_name, sizeof(algo->alg_name));
        memcpy(algo->alg_key, auth->alg_key, (auth->alg_key_len + 7) / 8);
        algo->alg_key_len = auth->alg_key_len;
 
@@ -878,6 +899,7 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
 {
        struct xfrm_dump_info info;
        struct sk_buff *skb;
+       int err;
 
        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_ATOMIC);
        if (!skb)
@@ -888,9 +910,10 @@ static struct sk_buff *xfrm_state_netlink(struct sk_buff *in_skb,
        info.nlmsg_seq = seq;
        info.nlmsg_flags = 0;
 
-       if (dump_one_state(x, 0, &info)) {
+       err = dump_one_state(x, 0, &info);
+       if (err) {
                kfree_skb(skb);
-               return NULL;
+               return ERR_PTR(err);
        }
 
        return skb;
@@ -1317,6 +1340,7 @@ static void copy_from_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy
 
 static void copy_to_user_policy(struct xfrm_policy *xp, struct xfrm_userpolicy_info *p, int dir)
 {
+       memset(p, 0, sizeof(*p));
        memcpy(&p->sel, &xp->selector, sizeof(p->sel));
        memcpy(&p->lft, &xp->lft, sizeof(p->lft));
        memcpy(&p->curlft, &xp->curlft, sizeof(p->curlft));
@@ -1421,6 +1445,7 @@ static int copy_to_user_tmpl(struct xfrm_policy *xp, struct sk_buff *skb)
                struct xfrm_user_tmpl *up = &vec[i];
                struct xfrm_tmpl *kp = &xp->xfrm_vec[i];
 
+               memset(up, 0, sizeof(*up));
                memcpy(&up->id, &kp->id, sizeof(up->id));
                up->family = kp->encap_family;
                memcpy(&up->saddr, &kp->saddr, sizeof(up->saddr));
@@ -1546,6 +1571,7 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
 {
        struct xfrm_dump_info info;
        struct sk_buff *skb;
+       int err;
 
        skb = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL);
        if (!skb)
@@ -1556,9 +1582,10 @@ static struct sk_buff *xfrm_policy_netlink(struct sk_buff *in_skb,
        info.nlmsg_seq = seq;
        info.nlmsg_flags = 0;
 
-       if (dump_one_policy(xp, dir, 0, &info) < 0) {
+       err = dump_one_policy(xp, dir, 0, &info);
+       if (err) {
                kfree_skb(skb);
-               return NULL;
+               return ERR_PTR(err);
        }
 
        return skb;
@@ -1822,7 +1849,7 @@ static int xfrm_new_ae(struct sk_buff *skb, struct nlmsghdr *nlh,
                goto out;
 
        spin_lock_bh(&x->lock);
-       xfrm_update_ae_params(x, attrs);
+       xfrm_update_ae_params(x, attrs, 1);
        spin_unlock_bh(&x->lock);
 
        c.event = nlh->nlmsg_type;
index 6bf8e87f1dcf124021083b25babe9aab317b7bbf..4d908d16c035c4e6c582e254e531998e7f6156ae 100644 (file)
@@ -27,7 +27,7 @@ endif
 installed-mod-fw := $(addprefix $(INSTALL_FW_PATH)/,$(mod-fw))
 
 installed-fw := $(addprefix $(INSTALL_FW_PATH)/,$(fw-shipped-all))
-installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/.
+installed-fw-dirs := $(sort $(dir $(installed-fw))) $(INSTALL_FW_PATH)/./
 
 # Workaround for make < 3.81, where .SECONDEXPANSION doesn't work.
 PHONY += $(INSTALL_FW_PATH)/$$(%) install-all-dirs
index d24810fc6af6caf3a15ea3f5a55b33f4f08a667b..fd8fa9aa7c4edd698430a9cb0647a8d26095a9a2 100755 (executable)
@@ -200,7 +200,7 @@ EOF
 syscall_list() {
     grep '^[0-9]' "$1" | sort -n | (
        while read nr abi name entry ; do
-           echo <<EOF
+           cat <<EOF
 #if !defined(__NR_${name}) && !defined(__IGNORE_${name})
 #warning syscall ${name} not implemented
 #endif
index 4629038c9e5acb677499ace431355a818ee4b3d6..b3d907eb93a91e7437ec8be8dac4248990eaf1e0 100644 (file)
@@ -74,8 +74,13 @@ kallsyms()
        info KSYM ${2}
        local kallsymopt;
 
+       if [ -n "${CONFIG_SYMBOL_PREFIX}" ]; then
+               kallsymopt="${kallsymopt} \
+                           --symbol-prefix=${CONFIG_SYMBOL_PREFIX}"
+       fi
+
        if [ -n "${CONFIG_KALLSYMS_ALL}" ]; then
-               kallsymopt=--all-symbols
+               kallsymopt="${kallsymopt} --all-symbols"
        fi
 
        local aflags="${KBUILD_AFLAGS} ${KBUILD_AFLAGS_KERNEL}               \
@@ -211,7 +216,7 @@ if [ -n "${CONFIG_KALLSYMS}" ]; then
 
        if ! cmp -s System.map .tmp_System.map; then
                echo >&2 Inconsistent kallsyms data
-               echo >&2 echo Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
+               echo >&2 Try "make KALLSYMS_EXTRA_PASS=1" as a workaround
                cleanup
                exit 1
        fi
index c220f314709cc1345792e4a4ddab28cd63a23177..65f67cb0aefb22f323d8048c140417555c273c9d 100644 (file)
@@ -51,6 +51,7 @@ int selinux_xfrm_decode_session(struct sk_buff *skb, u32 *sid, int ckall);
 static inline void selinux_xfrm_notify_policyload(void)
 {
        atomic_inc(&flow_cache_genid);
+       rt_genid_bump(&init_net);
 }
 #else
 static inline int selinux_xfrm_enabled(void)
index ec2118d0e27aca3f5fef6c2ddd72f8b166ce98ca..eb60cb8dbb8a6f12d965912e923197cdd2f4e8b5 100644 (file)
@@ -80,14 +80,12 @@ static int snd_compr_open(struct inode *inode, struct file *f)
        int maj = imajor(inode);
        int ret;
 
-       if (f->f_flags & O_WRONLY)
+       if ((f->f_flags & O_ACCMODE) == O_WRONLY)
                dirn = SND_COMPRESS_PLAYBACK;
-       else if (f->f_flags & O_RDONLY)
+       else if ((f->f_flags & O_ACCMODE) == O_RDONLY)
                dirn = SND_COMPRESS_CAPTURE;
-       else {
-               pr_err("invalid direction\n");
+       else
                return -EINVAL;
-       }
 
        if (maj == snd_major)
                compr = snd_lookup_minor_data(iminor(inode),
index d14edb7d6484a1963cd9ae0c4b61750a349bfbf0..3c6c1e3226f365c82c45cc1f98065520d24bfbb7 100644 (file)
@@ -37,9 +37,6 @@ MODULE_AUTHOR("Jaroslav Kysela <perex@perex.cz>");
 MODULE_DESCRIPTION("Routines for control of TEA5757/5759 Philips AM/FM radio tuner chips");
 MODULE_LICENSE("GPL");
 
-#define FREQ_LO                ((tea->tea5759 ? 760 :  875) * 1600U)
-#define FREQ_HI                ((tea->tea5759 ? 910 : 1080) * 1600U)
-
 /*
  * definitions
  */
@@ -50,8 +47,8 @@ MODULE_LICENSE("GPL");
 #define TEA575X_BIT_BAND_MASK  (3<<20)
 #define TEA575X_BIT_BAND_FM    (0<<20)
 #define TEA575X_BIT_BAND_MW    (1<<20)
-#define TEA575X_BIT_BAND_LW    (1<<21)
-#define TEA575X_BIT_BAND_SW    (1<<22)
+#define TEA575X_BIT_BAND_LW    (2<<20)
+#define TEA575X_BIT_BAND_SW    (3<<20)
 #define TEA575X_BIT_PORT_0     (1<<19)         /* user bit */
 #define TEA575X_BIT_PORT_1     (1<<18)         /* user bit */
 #define TEA575X_BIT_SEARCH_MASK        (3<<16)         /* search level */
@@ -62,6 +59,37 @@ MODULE_LICENSE("GPL");
 #define TEA575X_BIT_DUMMY      (1<<15)         /* buffer */
 #define TEA575X_BIT_FREQ_MASK  0x7fff
 
+enum { BAND_FM, BAND_FM_JAPAN, BAND_AM };
+
+static const struct v4l2_frequency_band bands[] = {
+       {
+               .type = V4L2_TUNER_RADIO,
+               .index = 0,
+               .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+                             V4L2_TUNER_CAP_FREQ_BANDS,
+               .rangelow   =  87500 * 16,
+               .rangehigh  = 108000 * 16,
+               .modulation = V4L2_BAND_MODULATION_FM,
+       },
+       {
+               .type = V4L2_TUNER_RADIO,
+               .index = 0,
+               .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO |
+                             V4L2_TUNER_CAP_FREQ_BANDS,
+               .rangelow   = 76000 * 16,
+               .rangehigh  = 91000 * 16,
+               .modulation = V4L2_BAND_MODULATION_FM,
+       },
+       {
+               .type = V4L2_TUNER_RADIO,
+               .index = 1,
+               .capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_FREQ_BANDS,
+               .rangelow   =  530 * 16,
+               .rangehigh  = 1710 * 16,
+               .modulation = V4L2_BAND_MODULATION_AM,
+       },
+};
+
 /*
  * lowlevel part
  */
@@ -133,16 +161,29 @@ static u32 snd_tea575x_val_to_freq(struct snd_tea575x *tea, u32 val)
        if (freq == 0)
                return freq;
 
-       /* freq *= 12.5 */
-       freq *= 125;
-       freq /= 10;
-       /* crystal fixup */
-       if (tea->tea5759)
-               freq += TEA575X_FMIF;
-       else
+       switch (tea->band) {
+       case BAND_FM:
+               /* freq *= 12.5 */
+               freq *= 125;
+               freq /= 10;
+               /* crystal fixup */
                freq -= TEA575X_FMIF;
+               break;
+       case BAND_FM_JAPAN:
+               /* freq *= 12.5 */
+               freq *= 125;
+               freq /= 10;
+               /* crystal fixup */
+               freq += TEA575X_FMIF;
+               break;
+       case BAND_AM:
+               /* crystal fixup */
+               freq -= TEA575X_AMIF;
+               break;
+       }
 
-       return clamp(freq * 16, FREQ_LO, FREQ_HI); /* from kHz */
+       return clamp(freq * 16, bands[tea->band].rangelow,
+                               bands[tea->band].rangehigh); /* from kHz */
 }
 
 static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
@@ -150,21 +191,37 @@ static u32 snd_tea575x_get_freq(struct snd_tea575x *tea)
        return snd_tea575x_val_to_freq(tea, snd_tea575x_read(tea));
 }
 
-static void snd_tea575x_set_freq(struct snd_tea575x *tea)
+void snd_tea575x_set_freq(struct snd_tea575x *tea)
 {
-       u32 freq = tea->freq;
+       u32 freq = tea->freq / 16;      /* to kHz */
+       u32 band = 0;
 
-       freq /= 16;             /* to kHz */
-       /* crystal fixup */
-       if (tea->tea5759)
-               freq -= TEA575X_FMIF;
-       else
+       switch (tea->band) {
+       case BAND_FM:
+               band = TEA575X_BIT_BAND_FM;
+               /* crystal fixup */
                freq += TEA575X_FMIF;
-       /* freq /= 12.5 */
-       freq *= 10;
-       freq /= 125;
+               /* freq /= 12.5 */
+               freq *= 10;
+               freq /= 125;
+               break;
+       case BAND_FM_JAPAN:
+               band = TEA575X_BIT_BAND_FM;
+               /* crystal fixup */
+               freq -= TEA575X_FMIF;
+               /* freq /= 12.5 */
+               freq *= 10;
+               freq /= 125;
+               break;
+       case BAND_AM:
+               band = TEA575X_BIT_BAND_MW;
+               /* crystal fixup */
+               freq += TEA575X_AMIF;
+               break;
+       }
 
-       tea->val &= ~TEA575X_BIT_FREQ_MASK;
+       tea->val &= ~(TEA575X_BIT_FREQ_MASK | TEA575X_BIT_BAND_MASK);
+       tea->val |= band;
        tea->val |= freq & TEA575X_BIT_FREQ_MASK;
        snd_tea575x_write(tea, tea->val);
        tea->freq = snd_tea575x_val_to_freq(tea, tea->val);
@@ -190,23 +247,57 @@ static int vidioc_querycap(struct file *file, void  *priv,
        return 0;
 }
 
+static int vidioc_enum_freq_bands(struct file *file, void *priv,
+                                        struct v4l2_frequency_band *band)
+{
+       struct snd_tea575x *tea = video_drvdata(file);
+       int index;
+
+       if (band->tuner != 0)
+               return -EINVAL;
+
+       switch (band->index) {
+       case 0:
+               if (tea->tea5759)
+                       index = BAND_FM_JAPAN;
+               else
+                       index = BAND_FM;
+               break;
+       case 1:
+               if (tea->has_am) {
+                       index = BAND_AM;
+                       break;
+               }
+               /* Fall through */
+       default:
+               return -EINVAL;
+       }
+
+       *band = bands[index];
+       if (!tea->cannot_read_data)
+               band->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
+
+       return 0;
+}
+
 static int vidioc_g_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
        struct snd_tea575x *tea = video_drvdata(file);
+       struct v4l2_frequency_band band_fm = { 0, };
 
        if (v->index > 0)
                return -EINVAL;
 
        snd_tea575x_read(tea);
+       vidioc_enum_freq_bands(file, priv, &band_fm);
 
-       strcpy(v->name, "FM");
+       memset(v, 0, sizeof(*v));
+       strlcpy(v->name, tea->has_am ? "FM/AM" : "FM", sizeof(v->name));
        v->type = V4L2_TUNER_RADIO;
-       v->capability = V4L2_TUNER_CAP_LOW | V4L2_TUNER_CAP_STEREO;
-       if (!tea->cannot_read_data)
-               v->capability |= V4L2_TUNER_CAP_HWSEEK_BOUNDED;
-       v->rangelow = FREQ_LO;
-       v->rangehigh = FREQ_HI;
+       v->capability = band_fm.capability;
+       v->rangelow = tea->has_am ? bands[BAND_AM].rangelow : band_fm.rangelow;
+       v->rangehigh = band_fm.rangehigh;
        v->rxsubchans = tea->stereo ? V4L2_TUNER_SUB_STEREO : V4L2_TUNER_SUB_MONO;
        v->audmode = (tea->val & TEA575X_BIT_MONO) ?
                V4L2_TUNER_MODE_MONO : V4L2_TUNER_MODE_STEREO;
@@ -218,13 +309,17 @@ static int vidioc_s_tuner(struct file *file, void *priv,
                                        struct v4l2_tuner *v)
 {
        struct snd_tea575x *tea = video_drvdata(file);
+       u32 orig_val = tea->val;
 
        if (v->index)
                return -EINVAL;
        tea->val &= ~TEA575X_BIT_MONO;
        if (v->audmode == V4L2_TUNER_MODE_MONO)
                tea->val |= TEA575X_BIT_MONO;
-       snd_tea575x_write(tea, tea->val);
+       /* Only apply changes if currently tuning FM */
+       if (tea->band != BAND_AM && tea->val != orig_val)
+               snd_tea575x_set_freq(tea);
+
        return 0;
 }
 
@@ -248,24 +343,56 @@ static int vidioc_s_frequency(struct file *file, void *priv,
        if (f->tuner != 0 || f->type != V4L2_TUNER_RADIO)
                return -EINVAL;
 
-       tea->val &= ~TEA575X_BIT_SEARCH;
-       tea->freq = clamp(f->frequency, FREQ_LO, FREQ_HI);
+       if (tea->has_am && f->frequency < (20000 * 16))
+               tea->band = BAND_AM;
+       else if (tea->tea5759)
+               tea->band = BAND_FM_JAPAN;
+       else
+               tea->band = BAND_FM;
+
+       tea->freq = clamp(f->frequency, bands[tea->band].rangelow,
+                                       bands[tea->band].rangehigh);
        snd_tea575x_set_freq(tea);
        return 0;
 }
 
 static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
-                                       struct v4l2_hw_freq_seek *a)
+                                       const struct v4l2_hw_freq_seek *a)
 {
        struct snd_tea575x *tea = video_drvdata(file);
        unsigned long timeout;
-       int i;
+       int i, spacing;
 
        if (tea->cannot_read_data)
                return -ENOTTY;
        if (a->tuner || a->wrap_around)
                return -EINVAL;
 
+       if (file->f_flags & O_NONBLOCK)
+               return -EWOULDBLOCK;
+
+       if (a->rangelow || a->rangehigh) {
+               for (i = 0; i < ARRAY_SIZE(bands); i++) {
+                       if ((i == BAND_FM && tea->tea5759) ||
+                           (i == BAND_FM_JAPAN && !tea->tea5759) ||
+                           (i == BAND_AM && !tea->has_am))
+                               continue;
+                       if (bands[i].rangelow  == a->rangelow &&
+                           bands[i].rangehigh == a->rangehigh)
+                               break;
+               }
+               if (i == ARRAY_SIZE(bands))
+                       return -EINVAL; /* No matching band found */
+               if (i != tea->band) {
+                       tea->band = i;
+                       tea->freq = clamp(tea->freq, bands[i].rangelow,
+                                                    bands[i].rangehigh);
+                       snd_tea575x_set_freq(tea);
+               }
+       }
+
+       spacing = (tea->band == BAND_AM) ? 5 : 50; /* kHz */
+
        /* clear the frequency, HW will fill it in */
        tea->val &= ~TEA575X_BIT_FREQ_MASK;
        tea->val |= TEA575X_BIT_SEARCH;
@@ -297,10 +424,10 @@ static int vidioc_s_hw_freq_seek(struct file *file, void *fh,
                        if (freq == 0) /* shouldn't happen */
                                break;
                        /*
-                        * if we moved by less than 50 kHz, or in the wrong
-                        * direction, continue seeking
+                        * if we moved by less than the spacing, or in the
+                        * wrong direction, continue seeking
                         */
-                       if (abs(tea->freq - freq) < 16 * 50 ||
+                       if (abs(tea->freq - freq) < 16 * spacing ||
                                        (a->seek_upward && freq < tea->freq) ||
                                        (!a->seek_upward && freq > tea->freq)) {
                                snd_tea575x_write(tea, tea->val);
@@ -344,6 +471,7 @@ static const struct v4l2_ioctl_ops tea575x_ioctl_ops = {
        .vidioc_g_frequency = vidioc_g_frequency,
        .vidioc_s_frequency = vidioc_s_frequency,
        .vidioc_s_hw_freq_seek = vidioc_s_hw_freq_seek,
+       .vidioc_enum_freq_bands = vidioc_enum_freq_bands,
        .vidioc_log_status  = v4l2_ctrl_log_status,
        .vidioc_subscribe_event = v4l2_ctrl_subscribe_event,
        .vidioc_unsubscribe_event = v4l2_event_unsubscribe,
@@ -446,3 +574,4 @@ module_exit(alsa_tea575x_module_exit)
 
 EXPORT_SYMBOL(snd_tea575x_init);
 EXPORT_SYMBOL(snd_tea575x_exit);
+EXPORT_SYMBOL(snd_tea575x_set_freq);
index ff3af6e77d610adc5cfba4748bdf25ac587238d7..f99fa251228623a161c6bcaed0d2622f5bf132bf 100644 (file)
@@ -2,8 +2,8 @@
 
 config SND_TEA575X
        tristate
-       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO
-       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO
+       depends on SND_FM801_TEA575X_BOOL || SND_ES1968_RADIO || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK
+       default SND_FM801 || SND_ES1968 || RADIO_SF16FMR2 || RADIO_MAXIRADIO || RADIO_SHARK
 
 menuconfig SND_PCI
        bool "PCI sound devices"
index f560051a949e943e10efb844364d5a978a587fcd..1c65cc5e3a31101d098d6cdb48a2772d1adc38f9 100644 (file)
@@ -1209,6 +1209,9 @@ static void snd_hda_codec_free(struct hda_codec *codec)
        kfree(codec);
 }
 
+static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec,
+                               hda_nid_t fg, unsigned int power_state);
+
 static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
                                unsigned int power_state);
 
@@ -1317,6 +1320,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus,
                                           AC_VERB_GET_SUBSYSTEM_ID, 0);
        }
 
+       codec->epss = snd_hda_codec_get_supported_ps(codec,
+                                       codec->afg ? codec->afg : codec->mfg,
+                                       AC_PWRST_EPSS);
+
        /* power-up all before initialization */
        hda_set_power_state(codec,
                            codec->afg ? codec->afg : codec->mfg,
@@ -2346,6 +2353,7 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        }
        if (codec->patch_ops.free)
                codec->patch_ops.free(codec);
+       memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
        snd_hda_jack_tbl_clear(codec);
        codec->proc_widget_hook = NULL;
        codec->spec = NULL;
@@ -2361,7 +2369,6 @@ int snd_hda_codec_reset(struct hda_codec *codec)
        codec->num_pcms = 0;
        codec->pcm_info = NULL;
        codec->preset = NULL;
-       memset(&codec->patch_ops, 0, sizeof(codec->patch_ops));
        codec->slave_dig_outs = NULL;
        codec->spdif_status_reset = 0;
        module_put(codec->owner);
@@ -3543,8 +3550,7 @@ static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg,
        /* this delay seems necessary to avoid click noise at power-down */
        if (power_state == AC_PWRST_D3) {
                /* transition time less than 10ms for power down */
-               bool epss = snd_hda_codec_get_supported_ps(codec, fg, AC_PWRST_EPSS);
-               msleep(epss ? 10 : 100);
+               msleep(codec->epss ? 10 : 100);
        }
 
        /* repeat power states setting at most 10 times*/
index 7fbc1bcaf1a9593b6e0ec71b8b5ac2bb5262e336..e5a7e19a80712c0ece3ad1b41617e40512206ad3 100644 (file)
@@ -862,6 +862,7 @@ struct hda_codec {
        unsigned int ignore_misc_bit:1; /* ignore MISC_NO_PRESENCE bit */
        unsigned int no_jack_detect:1;  /* Machine has no jack-detection */
        unsigned int pcm_format_first:1; /* PCM format must be set first */
+       unsigned int epss:1;            /* supporting EPSS? */
 #ifdef CONFIG_SND_HDA_POWER_SAVE
        unsigned int power_on :1;       /* current (global) power-state */
        int power_transition;   /* power-state in transition */
index 60882c62f18006a3b2339d354b58550fdcd30718..c4763c52eaf64ced9e1d520f80fd8b245507dbd6 100644 (file)
@@ -2701,6 +2701,8 @@ static struct snd_pci_quirk position_fix_list[] __devinitdata = {
        SND_PCI_QUIRK(0x1043, 0x813d, "ASUS P5AD2", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81b3, "ASUS", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1043, 0x81e7, "ASUS M2V", POS_FIX_LPIB),
+       SND_PCI_QUIRK(0x1043, 0x1ac3, "ASUS X53S", POS_FIX_POSBUF),
+       SND_PCI_QUIRK(0x1043, 0x1b43, "ASUS K53E", POS_FIX_POSBUF),
        SND_PCI_QUIRK(0x104d, 0x9069, "Sony VPCS11V9E", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x10de, 0xcb89, "Macbook Pro 7,1", POS_FIX_LPIB),
        SND_PCI_QUIRK(0x1297, 0x3166, "Shuttle", POS_FIX_LPIB),
index ea5775a1a7db292e25dd7956b8ac502d1a9db33e..3d4722f0a1cacba8fc9a923f22dbf767433dbd6c 100644 (file)
@@ -1075,7 +1075,7 @@ static struct snd_kcontrol_new stac_smux_mixer = {
 
 static const char * const slave_pfxs[] = {
        "Front", "Surround", "Center", "LFE", "Side",
-       "Headphone", "Speaker", "IEC958",
+       "Headphone", "Speaker", "IEC958", "PCM",
        NULL
 };
 
@@ -4543,6 +4543,9 @@ static void stac92xx_line_out_detect(struct hda_codec *codec,
        struct auto_pin_cfg *cfg = &spec->autocfg;
        int i;
 
+       if (cfg->speaker_outs == 0)
+               return;
+
        for (i = 0; i < cfg->line_outs; i++) {
                if (presence)
                        break;
@@ -5531,6 +5534,7 @@ static int patch_stac92hd83xxx(struct hda_codec *codec)
                snd_hda_codec_set_pincfg(codec, 0xf, 0x2181205e);
        }
 
+       codec->epss = 0; /* longer delay needed for D3 */
        codec->no_trigger_sense = 1;
        codec->spec = spec;
 
index 764cc93dbca402f6372b6f73a0854470f3046f73..075d5aa1fee003bef0dfaa4177ac21d010247277 100644 (file)
@@ -297,6 +297,7 @@ static int ak4396_dac_vol_put(struct snd_kcontrol *kcontrol, struct snd_ctl_elem
 }
 
 static const DECLARE_TLV_DB_SCALE(db_scale_wm_dac, -12700, 100, 1);
+static const DECLARE_TLV_DB_LINEAR(ak4396_db_scale, TLV_DB_GAIN_MUTE, 0);
 
 static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
     {
@@ -307,7 +308,7 @@ static struct snd_kcontrol_new prodigy_hd2_controls[] __devinitdata = {
        .info = ak4396_dac_vol_info,
        .get = ak4396_dac_vol_get,
        .put = ak4396_dac_vol_put,
-       .tlv = { .p = db_scale_wm_dac },
+       .tlv = { .p = ak4396_db_scale },
     },
 };
 
index 5c9cacaf2d525cddabffd0b416c0695dfadaab99..1cf7a32d1b211e779cb7705746c32b07c11afa82 100644 (file)
@@ -426,7 +426,7 @@ static const int arizona_44k1_bclk_rates[] = {
        940800,
        1411200,
        1881600,
-       2882400,
+       2822400,
        3763200,
        5644800,
        7526400,
index 8f726c063f42badc9c598de4af670fb78f8937e1..115a403018105b0eaa2fb64abee56a47b5d32cc4 100644 (file)
@@ -659,7 +659,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {
                .id = MC13783_ID_STEREO_DAC,
                .playback = {
                        .stream_name = "Playback",
-                       .channels_min = 1,
+                       .channels_min = 2,
                        .channels_max = 2,
                        .rates = SNDRV_PCM_RATE_8000_96000,
                        .formats = MC13783_FORMATS,
@@ -670,7 +670,7 @@ static struct snd_soc_dai_driver mc13783_dai_async[] = {
                .id = MC13783_ID_STEREO_CODEC,
                .capture = {
                        .stream_name = "Capture",
-                       .channels_min = 1,
+                       .channels_min = 2,
                        .channels_max = 2,
                        .rates = MC13783_RATES_RECORD,
                        .formats = MC13783_FORMATS,
@@ -692,14 +692,14 @@ static struct snd_soc_dai_driver mc13783_dai_sync[] = {
                .id = MC13783_ID_SYNC,
                .playback = {
                        .stream_name = "Playback",
-                       .channels_min = 1,
+                       .channels_min = 2,
                        .channels_max = 2,
                        .rates = SNDRV_PCM_RATE_8000_96000,
                        .formats = MC13783_FORMATS,
                },
                .capture = {
                        .stream_name = "Capture",
-                       .channels_min = 1,
+                       .channels_min = 2,
                        .channels_max = 2,
                        .rates = MC13783_RATES_RECORD,
                        .formats = MC13783_FORMATS,
index 3fd5b29dc9335b5bee03b0b28f6cbbdfee2ea297..a3acb7a85f6ab26f62e92489e75e0f6b4822f831 100644 (file)
@@ -702,7 +702,7 @@ static bool wm2000_readable_reg(struct device *dev, unsigned int reg)
 }
 
 static const struct regmap_config wm2000_regmap = {
-       .reg_bits = 8,
+       .reg_bits = 16,
        .val_bits = 8,
 
        .max_register = WM2000_REG_IF_CTL,
index 0013afe48e66a83171b93691b46593cb2e64d7ea..dc4262eea4b711990c71e602fe1a0fba7928250b 100644 (file)
@@ -100,7 +100,7 @@ static const struct reg_default wm8904_reg_defaults[] = {
        { 14,  0x0000 },     /* R14  - Power Management 2 */
        { 15,  0x0000 },     /* R15  - Power Management 3 */
        { 18,  0x0000 },     /* R18  - Power Management 6 */
-       { 19,  0x945E },     /* R20  - Clock Rates 0 */
+       { 20,  0x945E },     /* R20  - Clock Rates 0 */
        { 21,  0x0C05 },     /* R21  - Clock Rates 1 */
        { 22,  0x0006 },     /* R22  - Clock Rates 2 */
        { 24,  0x0050 },     /* R24  - Audio Interface 0 */
index fb21b17f17f54ae342b552e05b42df6a0afcaeca..199408ec42612dfe57f63e3933457e901cf7bcfa 100644 (file)
@@ -94,7 +94,7 @@ static int __devinit imx_sgtl5000_probe(struct platform_device *pdev)
                dev_err(&pdev->dev, "audmux internal port setup failed\n");
                return ret;
        }
-       imx_audmux_v2_configure_port(ext_port,
+       ret = imx_audmux_v2_configure_port(ext_port,
                        IMX_AUDMUX_V2_PTCR_SYN,
                        IMX_AUDMUX_V2_PDCR_RXDSEL(int_port));
        if (ret) {
index 009533ab8d1894054ed07c05ae140362d6738582..df65f98211ec2bdc3c664f7a87443f8477dc5476 100644 (file)
@@ -59,7 +59,7 @@ static int am3517evm_hw_params(struct snd_pcm_substream *substream,
                return ret;
        }
 
-       snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
+       ret = snd_soc_dai_set_sysclk(cpu_dai, OMAP_MCBSP_FSR_SRC_FSX, 0,
                                SND_SOC_CLOCK_IN);
        if (ret < 0) {
                printk(KERN_ERR "can't set CPU system clock OMAP_MCBSP_FSR_SRC_FSX\n");
index f3ebc38c10fe7633ea5ec260562b64bfdb7e402f..b70964ea448cef264bf540597850558e7c9fd23c 100644 (file)
@@ -34,9 +34,7 @@ static const struct snd_pcm_hardware dma_hardware = {
        .info                   = SNDRV_PCM_INFO_INTERLEAVED |
                                    SNDRV_PCM_INFO_BLOCK_TRANSFER |
                                    SNDRV_PCM_INFO_MMAP |
-                                   SNDRV_PCM_INFO_MMAP_VALID |
-                                   SNDRV_PCM_INFO_PAUSE |
-                                   SNDRV_PCM_INFO_RESUME,
+                                   SNDRV_PCM_INFO_MMAP_VALID,
        .formats                = SNDRV_PCM_FMTBIT_S16_LE |
                                    SNDRV_PCM_FMTBIT_U16_LE |
                                    SNDRV_PCM_FMTBIT_U8 |
@@ -248,15 +246,11 @@ static int dma_trigger(struct snd_pcm_substream *substream, int cmd)
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-       case SNDRV_PCM_TRIGGER_RESUME:
-       case SNDRV_PCM_TRIGGER_PAUSE_RELEASE:
                prtd->state |= ST_RUNNING;
                prtd->params->ops->trigger(prtd->params->ch);
                break;
 
        case SNDRV_PCM_TRIGGER_STOP:
-       case SNDRV_PCM_TRIGGER_SUSPEND:
-       case SNDRV_PCM_TRIGGER_PAUSE_PUSH:
                prtd->state &= ~ST_RUNNING;
                prtd->params->ops->stop(prtd->params->ch);
                break;
index dd7c49fafd754f949014f88b9a2ad0b80d59cc20..f90139b5f50d74089dc98fd0d19de42cb3732a84 100644 (file)
@@ -291,8 +291,11 @@ static int snd_soc_dapm_set_bias_level(struct snd_soc_dapm_context *dapm,
                if (dapm->codec->driver->set_bias_level)
                        ret = dapm->codec->driver->set_bias_level(dapm->codec,
                                                                  level);
-       } else
+               else
+                       dapm->bias_level = level;
+       } else if (!card || dapm != &card->dapm) {
                dapm->bias_level = level;
+       }
 
        if (ret != 0)
                goto out;
index 97c2cac8e92c726712746d5db4658d7f0898e441..8c7f23729446b1582f6d7625d5933aad905e45d7 100644 (file)
@@ -138,7 +138,7 @@ static void spear_pcm_free(struct snd_pcm *pcm)
                        continue;
 
                buf = &substream->dma_buffer;
-               if (!buf && !buf->area)
+               if (!buf || !buf->area)
                        continue;
 
                dma_free_writecombine(pcm->card->dev, buf->bytes,
index e463529b38bbfbfd35cc745bf430f68399bfee91..76cb1b363b71c2ce2d1be75c27113c3cf2154127 100644 (file)
@@ -89,7 +89,6 @@ static struct snd_soc_jack_gpio tegra_alc5632_hp_jack_gpio = {
        .name = "Headset detection",
        .report = SND_JACK_HEADSET,
        .debounce_time = 150,
-       .invert = 1,
 };
 
 static const struct snd_soc_dapm_widget tegra_alc5632_dapm_widgets[] = {
index 5658bcec1931ce5a76a75a32b020730f41da8c13..8d6900c1ee47e8d1a263584bf470e5c2eec56af4 100644 (file)
@@ -334,11 +334,11 @@ static int tegra_pcm_hw_params(struct snd_pcm_substream *substream,
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
                slave_config.dst_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
                slave_config.dst_addr = dmap->addr;
-               slave_config.src_maxburst = 0;
+               slave_config.dst_maxburst = 4;
        } else {
                slave_config.src_addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES;
                slave_config.src_addr = dmap->addr;
-               slave_config.dst_maxburst = 0;
+               slave_config.src_maxburst = 4;
        }
        slave_config.slave_id = dmap->req_sel;
 
index 5c472f335a64d6e5c11a5ee82e755153312ee40b..eb85113d472a22503aceb1939d5191d9d2c856de 100644 (file)
@@ -663,7 +663,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                        struct ux500_msp **msp_p,
                        struct msp_i2s_platform_data *platform_data)
 {
-       int ret = 0;
        struct resource *res = NULL;
        struct i2s_controller *i2s_cont;
        struct ux500_msp *msp;
@@ -685,15 +684,14 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
        if (res == NULL) {
                dev_err(&pdev->dev, "%s: ERROR: Unable to get resource!\n",
                        __func__);
-               ret = -ENOMEM;
-               goto err_res;
+               return -ENOMEM;
        }
 
-       msp->registers = ioremap(res->start, (res->end - res->start + 1));
+       msp->registers = devm_ioremap(&pdev->dev, res->start,
+                                     resource_size(res));
        if (msp->registers == NULL) {
                dev_err(&pdev->dev, "%s: ERROR: ioremap failed!\n", __func__);
-               ret = -ENOMEM;
-               goto err_res;
+               return -ENOMEM;
        }
 
        msp->msp_state = MSP_STATE_IDLE;
@@ -705,7 +703,7 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
                dev_err(&pdev->dev,
                        "%s: ERROR: Failed to allocate I2S-controller!\n",
                        __func__);
-               goto err_i2s_cont;
+               return -ENOMEM;
        }
        i2s_cont->dev.parent = &pdev->dev;
        i2s_cont->data = (void *)msp;
@@ -716,14 +714,6 @@ int ux500_msp_i2s_init_msp(struct platform_device *pdev,
        msp->i2s_cont = i2s_cont;
 
        return 0;
-
-err_i2s_cont:
-       iounmap(msp->registers);
-
-err_res:
-       devm_kfree(&pdev->dev, msp);
-
-       return ret;
 }
 
 void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
@@ -732,11 +722,6 @@ void ux500_msp_i2s_cleanup_msp(struct platform_device *pdev,
        dev_dbg(msp->dev, "%s: Enter (id = %d).\n", __func__, msp->id);
 
        device_unregister(&msp->i2s_cont->dev);
-       devm_kfree(&pdev->dev, msp->i2s_cont);
-
-       iounmap(msp->registers);
-
-       devm_kfree(&pdev->dev, msp);
 }
 
 MODULE_LICENSE("GPL v2");
index d5b5c3388e28ced3cb7c287399755b56d90e1aed..4a469f0cb6d4750b03fab852d13515022fe0b4af 100644 (file)
@@ -553,7 +553,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                                     struct snd_usb_audio *chip)
 {
        struct snd_card *card;
-       struct list_head *p;
+       struct list_head *p, *n;
 
        if (chip == (void *)-1L)
                return;
@@ -570,7 +570,7 @@ static void snd_usb_audio_disconnect(struct usb_device *dev,
                        snd_usb_stream_disconnect(p);
                }
                /* release the endpoint resources */
-               list_for_each(p, &chip->ep_list) {
+               list_for_each_safe(p, n, &chip->ep_list) {
                        snd_usb_endpoint_free(p);
                }
                /* release the midi resources */
index c411812026884408afd74f1e580f2e87bbe747fc..060dccb9ec75513def50e6f8be32f60f4f3b05f1 100644 (file)
@@ -141,7 +141,7 @@ int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep)
  *
  * For implicit feedback, next_packet_size() is unused.
  */
-static int next_packet_size(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep)
 {
        unsigned long flags;
        int ret;
@@ -177,15 +177,6 @@ static void retire_inbound_urb(struct snd_usb_endpoint *ep,
                ep->retire_data_urb(ep->data_subs, urb);
 }
 
-static void prepare_outbound_urb_sizes(struct snd_usb_endpoint *ep,
-                                      struct snd_urb_ctx *ctx)
-{
-       int i;
-
-       for (i = 0; i < ctx->packets; ++i)
-               ctx->packet_size[i] = next_packet_size(ep);
-}
-
 /*
  * Prepare a PLAYBACK urb for submission to the bus.
  */
@@ -206,7 +197,13 @@ static void prepare_outbound_urb(struct snd_usb_endpoint *ep,
                        /* no data provider, so send silence */
                        unsigned int offs = 0;
                        for (i = 0; i < ctx->packets; ++i) {
-                               int counts = ctx->packet_size[i];
+                               int counts;
+
+                               if (ctx->packet_size[i])
+                                       counts = ctx->packet_size[i];
+                               else
+                                       counts = snd_usb_endpoint_next_packet_size(ep);
+
                                urb->iso_frame_desc[i].offset = offs * ep->stride;
                                urb->iso_frame_desc[i].length = counts * ep->stride;
                                offs += counts;
@@ -370,7 +367,6 @@ static void snd_complete_urb(struct urb *urb)
                        goto exit_clear;
                }
 
-               prepare_outbound_urb_sizes(ep, ctx);
                prepare_outbound_urb(ep, ctx);
        } else {
                retire_inbound_urb(ep, ctx);
@@ -799,7 +795,9 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
 /**
  * snd_usb_endpoint_start: start an snd_usb_endpoint
  *
- * @ep: the endpoint to start
+ * @ep:                the endpoint to start
+ * @can_sleep: flag indicating whether the operation is executed in
+ *             non-atomic context
  *
  * A call to this function will increment the use count of the endpoint.
  * In case it is not already running, the URBs for this endpoint will be
@@ -809,7 +807,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
  *
  * Returns an error if the URB submission failed, 0 in all other cases.
  */
-int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
+int snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep)
 {
        int err;
        unsigned int i;
@@ -821,6 +819,11 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
        if (++ep->use_count != 1)
                return 0;
 
+       /* just to be sure */
+       deactivate_urbs(ep, 0, can_sleep);
+       if (can_sleep)
+               wait_clear_urbs(ep);
+
        ep->active_mask = 0;
        ep->unlink_mask = 0;
        ep->phase = 0;
@@ -850,7 +853,6 @@ int snd_usb_endpoint_start(struct snd_usb_endpoint *ep)
                        goto __error;
 
                if (usb_pipeout(ep->pipe)) {
-                       prepare_outbound_urb_sizes(ep, urb->context);
                        prepare_outbound_urb(ep, urb->context);
                } else {
                        prepare_inbound_urb(ep, urb->context);
index ee2723fb174f61ddb9a3c0c0224bc065b36ba173..cbbbdf226d66b6fa9eec51fe829a1b03cdd8d518 100644 (file)
@@ -13,7 +13,7 @@ int snd_usb_endpoint_set_params(struct snd_usb_endpoint *ep,
                                struct audioformat *fmt,
                                struct snd_usb_endpoint *sync_ep);
 
-int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep);
+int  snd_usb_endpoint_start(struct snd_usb_endpoint *ep, int can_sleep);
 void snd_usb_endpoint_stop(struct snd_usb_endpoint *ep,
                           int force, int can_sleep, int wait);
 int  snd_usb_endpoint_activate(struct snd_usb_endpoint *ep);
@@ -21,6 +21,7 @@ int  snd_usb_endpoint_deactivate(struct snd_usb_endpoint *ep);
 void snd_usb_endpoint_free(struct list_head *head);
 
 int snd_usb_endpoint_implict_feedback_sink(struct snd_usb_endpoint *ep);
+int snd_usb_endpoint_next_packet_size(struct snd_usb_endpoint *ep);
 
 void snd_usb_handle_sync_urb(struct snd_usb_endpoint *ep,
                             struct snd_usb_endpoint *sender,
index 62ec808ed792503e789ea26eb74837998623915e..f782ce19bf5aa14be92a43df553d66b177cb9429 100644 (file)
@@ -212,7 +212,7 @@ int snd_usb_init_pitch(struct snd_usb_audio *chip, int iface,
        }
 }
 
-static int start_endpoints(struct snd_usb_substream *subs)
+static int start_endpoints(struct snd_usb_substream *subs, int can_sleep)
 {
        int err;
 
@@ -225,7 +225,7 @@ static int start_endpoints(struct snd_usb_substream *subs)
                snd_printdd(KERN_DEBUG "Starting data EP @%p\n", ep);
 
                ep->data_subs = subs;
-               err = snd_usb_endpoint_start(ep);
+               err = snd_usb_endpoint_start(ep, can_sleep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_DATA_EP_STARTED, &subs->flags);
                        return err;
@@ -236,10 +236,25 @@ static int start_endpoints(struct snd_usb_substream *subs)
            !test_and_set_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags)) {
                struct snd_usb_endpoint *ep = subs->sync_endpoint;
 
+               if (subs->data_endpoint->iface != subs->sync_endpoint->iface ||
+                   subs->data_endpoint->alt_idx != subs->sync_endpoint->alt_idx) {
+                       err = usb_set_interface(subs->dev,
+                                               subs->sync_endpoint->iface,
+                                               subs->sync_endpoint->alt_idx);
+                       if (err < 0) {
+                               snd_printk(KERN_ERR
+                                          "%d:%d:%d: cannot set interface (%d)\n",
+                                          subs->dev->devnum,
+                                          subs->sync_endpoint->iface,
+                                          subs->sync_endpoint->alt_idx, err);
+                               return -EIO;
+                       }
+               }
+
                snd_printdd(KERN_DEBUG "Starting sync EP @%p\n", ep);
 
                ep->sync_slave = subs->data_endpoint;
-               err = snd_usb_endpoint_start(ep);
+               err = snd_usb_endpoint_start(ep, can_sleep);
                if (err < 0) {
                        clear_bit(SUBSTREAM_FLAG_SYNC_EP_STARTED, &subs->flags);
                        return err;
@@ -544,13 +559,10 @@ static int snd_usb_pcm_prepare(struct snd_pcm_substream *substream)
        subs->last_frame_number = 0;
        runtime->delay = 0;
 
-       /* clear the pending deactivation on the target EPs */
-       deactivate_endpoints(subs);
-
        /* for playback, submit the URBs now; otherwise, the first hwptr_done
         * updates for all URBs would happen at the same time when starting */
        if (subs->direction == SNDRV_PCM_STREAM_PLAYBACK)
-               return start_endpoints(subs);
+               return start_endpoints(subs, 1);
 
        return 0;
 }
@@ -1032,6 +1044,7 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
                                 struct urb *urb)
 {
        struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
+       struct snd_usb_endpoint *ep = subs->data_endpoint;
        struct snd_urb_ctx *ctx = urb->context;
        unsigned int counts, frames, bytes;
        int i, stride, period_elapsed = 0;
@@ -1043,7 +1056,11 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
        urb->number_of_packets = 0;
        spin_lock_irqsave(&subs->lock, flags);
        for (i = 0; i < ctx->packets; i++) {
-               counts = ctx->packet_size[i];
+               if (ctx->packet_size[i])
+                       counts = ctx->packet_size[i];
+               else
+                       counts = snd_usb_endpoint_next_packet_size(ep);
+
                /* set up descriptor */
                urb->iso_frame_desc[i].offset = frames * stride;
                urb->iso_frame_desc[i].length = counts * stride;
@@ -1094,7 +1111,16 @@ static void prepare_playback_urb(struct snd_usb_substream *subs,
        subs->hwptr_done += bytes;
        if (subs->hwptr_done >= runtime->buffer_size * stride)
                subs->hwptr_done -= runtime->buffer_size * stride;
+
+       /* update delay with exact number of samples queued */
+       runtime->delay = subs->last_delay;
        runtime->delay += frames;
+       subs->last_delay = runtime->delay;
+
+       /* realign last_frame_number */
+       subs->last_frame_number = usb_get_current_frame_number(subs->dev);
+       subs->last_frame_number &= 0xFF; /* keep 8 LSBs */
+
        spin_unlock_irqrestore(&subs->lock, flags);
        urb->transfer_buffer_length = bytes;
        if (period_elapsed)
@@ -1112,12 +1138,32 @@ static void retire_playback_urb(struct snd_usb_substream *subs,
        struct snd_pcm_runtime *runtime = subs->pcm_substream->runtime;
        int stride = runtime->frame_bits >> 3;
        int processed = urb->transfer_buffer_length / stride;
+       int est_delay;
+
+       /* ignore the delay accounting when procssed=0 is given, i.e.
+        * silent payloads are procssed before handling the actual data
+        */
+       if (!processed)
+               return;
 
        spin_lock_irqsave(&subs->lock, flags);
-       if (processed > runtime->delay)
-               runtime->delay = 0;
+       est_delay = snd_usb_pcm_delay(subs, runtime->rate);
+       /* update delay with exact number of samples played */
+       if (processed > subs->last_delay)
+               subs->last_delay = 0;
        else
-               runtime->delay -= processed;
+               subs->last_delay -= processed;
+       runtime->delay = subs->last_delay;
+
+       /*
+        * Report when delay estimate is off by more than 2ms.
+        * The error should be lower than 2ms since the estimate relies
+        * on two reads of a counter updated every ms.
+        */
+       if (abs(est_delay - subs->last_delay) * 1000 > runtime->rate * 2)
+               snd_printk(KERN_DEBUG "delay: estimated %d, actual %d\n",
+                       est_delay, subs->last_delay);
+
        spin_unlock_irqrestore(&subs->lock, flags);
 }
 
@@ -1175,7 +1221,7 @@ static int snd_usb_substream_capture_trigger(struct snd_pcm_substream *substream
 
        switch (cmd) {
        case SNDRV_PCM_TRIGGER_START:
-               err = start_endpoints(subs);
+               err = start_endpoints(subs, 0);
                if (err < 0)
                        return err;
 
index 2884e67ee625d6c41c8fb6a6fb495d843a6b86e7..213362850abdab31ca804db1a583dd5c38bdfbbd 100644 (file)
@@ -10,10 +10,12 @@ util/ctype.c
 util/evlist.c
 util/evsel.c
 util/cpumap.c
+util/hweight.c
 util/thread_map.c
 util/util.c
 util/xyarray.c
 util/cgroup.c
 util/debugfs.c
+util/rblist.c
 util/strlist.c
 ../../lib/rbtree.c
index 246852397e301ee86ac5c40f653e4695eae659a8..d617f69131d7667d3847c7e0fc040a717625bf38 100644 (file)
@@ -1976,9 +1976,10 @@ static long kvm_vcpu_compat_ioctl(struct file *filp,
                        if (copy_from_user(&csigset, sigmask_arg->sigset,
                                           sizeof csigset))
                                goto out;
-               }
-               sigset_from_compat(&sigset, &csigset);
-               r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+                       sigset_from_compat(&sigset, &csigset);
+                       r = kvm_vcpu_ioctl_set_sigmask(vcpu, &sigset);
+               } else
+                       r = kvm_vcpu_ioctl_set_sigmask(vcpu, NULL);
                break;
        }
        default: